Decompiled source of ValheimPasswordManager v1.0.1

BepInEx\plugins\JipZeonGit-ValheimPasswordManager\ValheimPasswordManager.dll

Decompiled 6 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GUIFramework;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
using ValheimPasswordManager.Data;
using ValheimPasswordManager.Services;
using ValheimPasswordManager.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("Valheim Password Manager")]
[assembly: AssemblyDescription("Valheim Password Manager")]
[assembly: AssemblyCompany("JipZeonGit")]
[assembly: AssemblyProduct("Valheim Password Manager")]
[assembly: AssemblyCopyright("Copyright © 2026")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.1.0")]
[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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ValheimPasswordManager
{
	[BepInPlugin("JipZeonGit.Valheim.PasswordManager", "Valheim Password Manager", "1.0.1")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "JipZeonGit.Valheim.PasswordManager";

		public const string PluginName = "Valheim Password Manager";

		public const string PluginVersion = "1.0.1";

		private const string ScrollSpeedConfigFileName = "JipZeonGit.Valheim.PasswordManager.ScrollSpeed.cfg";

		private const float DefaultScrollSpeed = 160f;

		private const float MinScrollSpeed = 20f;

		private const float MaxScrollSpeed = 400f;

		private Harmony _harmony;

		private ConfigFile _scrollSpeedConfigFile;

		internal static Plugin Instance { get; private set; }

		internal static ManualLogSource Log => ((BaseUnityPlugin)Instance).Logger;

		internal static PasswordStorageService Storage { get; private set; }

		internal static ModLocalizationService ModLocalization { get; private set; }

		internal static PasswordDialogController DialogController { get; private set; }

		internal static ConfigEntry<float> ScrollSpeedConfig { get; private set; }

		private void Awake()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Expected O, but got Unknown
			Instance = this;
			_scrollSpeedConfigFile = new ConfigFile(Path.Combine(Paths.ConfigPath, "JipZeonGit.Valheim.PasswordManager.ScrollSpeed.cfg"), true);
			ScrollSpeedConfig = _scrollSpeedConfigFile.Bind<float>("UI", "PasswordListScrollSpeed", 160f, new ConfigDescription("Scroll wheel speed for the saved password drawer.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(20f, 400f), Array.Empty<object>()));
			Storage = new PasswordStorageService();
			ModLocalization = new ModLocalizationService();
			DialogController = new PasswordDialogController(Storage);
			_harmony = new Harmony("JipZeonGit.Valheim.PasswordManager");
			_harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Valheim Password Manager 1.0.1 loaded.");
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			ConfigFile scrollSpeedConfigFile = _scrollSpeedConfigFile;
			if (scrollSpeedConfigFile != null)
			{
				scrollSpeedConfigFile.Save();
			}
		}

		internal static float GetPasswordListScrollSpeed()
		{
			if (ScrollSpeedConfig == null)
			{
				return 160f;
			}
			return Mathf.Clamp(ScrollSpeedConfig.Value, 20f, 400f);
		}
	}
}
namespace ValheimPasswordManager.UI
{
	public sealed class PasswordDialogController
	{
		private const float DrawerPadding = 8f;

		private const float RowHeight = 34f;

		private const int MaxVisibleRows = 8;

		private const float ToggleWidth = 32f;

		private static readonly MethodInfo OriginalOnPasswordEntered = AccessTools.Method(typeof(ZNet), "OnPasswordEntered", (Type[])null, (Type[])null);

		private static readonly FieldInfo PasswordDialogField = AccessTools.Field(typeof(ZNet), "m_passwordDialog");

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

		private readonly PasswordStorageService _storage;

		private RectTransform _dialogRoot;

		private GuiInputField _inputField;

		private Button _toggleButton;

		private RectTransform _drawerRoot;

		private RectTransform _contentRoot;

		private ScrollRect _scrollRect;

		private bool _drawerVisible;

		private bool _allowOriginalSubmit;

		private bool _promptOpen;

		private string _pendingPassword;

		private ZNet _pendingZNet;

		public PasswordDialogController(PasswordStorageService storage)
		{
			_storage = storage;
		}

		public void OnPasswordDialogShown(ZNet znet)
		{
			try
			{
				ClearServerPasswordCache();
				object? obj = PasswordDialogField?.GetValue(znet);
				RectTransform val = (RectTransform)((obj is RectTransform) ? obj : null);
				if ((Object)(object)val == (Object)null)
				{
					Plugin.Log.LogWarning((object)"Password dialog root not found; skipping UI injection.");
					return;
				}
				EnsureInjected(val);
				((Component)val).gameObject.SetActive(true);
				RefreshRows();
			}
			catch (Exception arg)
			{
				Plugin.Log.LogWarning((object)$"Failed to enhance password dialog safely: {arg}");
			}
		}

		public bool ShouldAllowOriginalSubmit(ZNet znet, string password)
		{
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Expected O, but got Unknown
			//IL_00e4: Expected O, but got Unknown
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Expected O, but got Unknown
			if (_allowOriginalSubmit)
			{
				_allowOriginalSubmit = false;
				return true;
			}
			if (string.IsNullOrWhiteSpace(password))
			{
				return true;
			}
			CloseDrawer();
			if (_storage.Contains(password))
			{
				_storage.Touch(password);
				return true;
			}
			if (_promptOpen && string.Equals(_pendingPassword, password, StringComparison.Ordinal) && _pendingZNet == znet)
			{
				return false;
			}
			_promptOpen = true;
			_pendingPassword = password;
			_pendingZNet = znet;
			SetDialogVisible(visible: false);
			string text = Plugin.ModLocalization?.GetSavePasswordPromptForCurrentLanguage() ?? "Save this password?";
			UnifiedPopup.Push((PopupBase)new YesNoPopup(text, string.Empty, (PopupButtonCallback)delegate
			{
				ContinuePendingSubmission(savePassword: true);
			}, (PopupButtonCallback)delegate
			{
				ContinuePendingSubmission(savePassword: false);
			}, false));
			return false;
		}

		private void ContinuePendingSubmission(bool savePassword)
		{
			try
			{
				UnifiedPopup.Pop();
				string pendingPassword = _pendingPassword;
				ZNet pendingZNet = _pendingZNet;
				_promptOpen = false;
				_pendingPassword = null;
				_pendingZNet = null;
				if ((Object)(object)pendingZNet == (Object)null || string.IsNullOrWhiteSpace(pendingPassword))
				{
					SetDialogVisible(visible: true);
					return;
				}
				if (savePassword)
				{
					_storage.Upsert(pendingPassword);
					RefreshRows();
				}
				ClearServerPasswordCache();
				_allowOriginalSubmit = true;
				OriginalOnPasswordEntered?.Invoke(pendingZNet, new object[1] { pendingPassword });
				ClearServerPasswordCache();
			}
			catch (Exception arg)
			{
				_promptOpen = false;
				Plugin.Log.LogWarning((object)$"Failed to continue password submission safely: {arg}");
				SetDialogVisible(visible: true);
			}
		}

		private void EnsureInjected(RectTransform dialogRoot)
		{
			if ((Object)(object)_dialogRoot == (Object)(object)dialogRoot && (Object)(object)_toggleButton != (Object)null && (Object)(object)_drawerRoot != (Object)null)
			{
				return;
			}
			_dialogRoot = dialogRoot;
			_inputField = ((Component)dialogRoot).GetComponentInChildren<GuiInputField>(true);
			if ((Object)(object)_inputField == (Object)null)
			{
				Plugin.Log.LogWarning((object)"Password dialog input field not found; cannot inject password manager UI.");
				return;
			}
			Transform transform = ((Component)_inputField).transform;
			RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)"Password input field has no RectTransform; cannot inject password manager UI.");
				return;
			}
			if ((Object)(object)_toggleButton == (Object)null)
			{
				_toggleButton = BuildToggleButton(val);
			}
			if ((Object)(object)_drawerRoot == (Object)null)
			{
				BuildDrawer(val);
			}
			CloseDrawer();
		}

		private Button BuildToggleButton(RectTransform inputRect)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Expected O, but got Unknown
			GameObject val = new GameObject("PasswordManagerToggle", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Button)
			});
			val.transform.SetParent((Transform)(object)inputRect, false);
			RectTransform component = val.GetComponent<RectTransform>();
			component.anchorMin = new Vector2(1f, 0f);
			component.anchorMax = new Vector2(1f, 1f);
			component.pivot = new Vector2(1f, 0.5f);
			component.sizeDelta = new Vector2(32f, -4f);
			component.anchoredPosition = new Vector2(-2f, 0f);
			Image component2 = val.GetComponent<Image>();
			CopyImageStyle(FindBestImageTemplate((Component)(object)inputRect), component2, new Color(0.34f, 0.27f, 0.2f, 0.95f));
			Button component3 = val.GetComponent<Button>();
			((Selectable)component3).targetGraphic = (Graphic)(object)component2;
			((UnityEvent)component3.onClick).AddListener(new UnityAction(ToggleDrawer));
			BuildTriangleIcon(val.transform);
			return component3;
		}

		private void BuildDrawer(RectTransform inputRect)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Expected O, but got Unknown
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: 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_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0242: Expected O, but got Unknown
			//IL_0273: 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_02a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fc: Expected O, but got Unknown
			Transform parent = ((Transform)inputRect).parent;
			RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null);
			if ((Object)(object)val == (Object)null)
			{
				val = _dialogRoot;
			}
			GameObject val2 = new GameObject("PasswordManagerDrawer", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val2.transform.SetParent((Transform)(object)val, false);
			_drawerRoot = val2.GetComponent<RectTransform>();
			_drawerRoot.anchorMin = inputRect.anchorMin;
			_drawerRoot.anchorMax = inputRect.anchorMax;
			_drawerRoot.pivot = new Vector2(inputRect.pivot.x, 1f);
			RectTransform drawerRoot = _drawerRoot;
			Rect rect = inputRect.rect;
			drawerRoot.sizeDelta = new Vector2(Mathf.Max(220f, ((Rect)(ref rect)).width), 0f);
			RectTransform drawerRoot2 = _drawerRoot;
			Vector2 anchoredPosition = inputRect.anchoredPosition;
			rect = inputRect.rect;
			drawerRoot2.anchoredPosition = anchoredPosition + new Vector2(0f, 0f - ((Rect)(ref rect)).height - 8f);
			Image component = val2.GetComponent<Image>();
			CopyImageStyle(FindBestImageTemplate((Component)(object)_dialogRoot), component, new Color(0.29f, 0.19f, 0.12f, 0.97f));
			GameObject val3 = new GameObject("Viewport", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(RectMask2D)
			});
			val3.transform.SetParent(val2.transform, false);
			RectTransform component2 = val3.GetComponent<RectTransform>();
			component2.anchorMin = Vector2.zero;
			component2.anchorMax = Vector2.one;
			component2.offsetMin = new Vector2(8f, 8f);
			component2.offsetMax = new Vector2(-8f, -8f);
			Image component3 = val3.GetComponent<Image>();
			((Graphic)component3).color = new Color(0f, 0f, 0f, 0.03f);
			GameObject val4 = new GameObject("Content", new Type[3]
			{
				typeof(RectTransform),
				typeof(VerticalLayoutGroup),
				typeof(ContentSizeFitter)
			});
			val4.transform.SetParent(val3.transform, false);
			_contentRoot = val4.GetComponent<RectTransform>();
			_contentRoot.anchorMin = new Vector2(0f, 1f);
			_contentRoot.anchorMax = new Vector2(1f, 1f);
			_contentRoot.pivot = new Vector2(0.5f, 1f);
			_contentRoot.offsetMin = Vector2.zero;
			_contentRoot.offsetMax = Vector2.zero;
			VerticalLayoutGroup component4 = val4.GetComponent<VerticalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)component4).spacing = 2f;
			((LayoutGroup)component4).padding = new RectOffset(0, 0, 0, 0);
			((LayoutGroup)component4).childAlignment = (TextAnchor)1;
			((HorizontalOrVerticalLayoutGroup)component4).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)component4).childControlHeight = false;
			((HorizontalOrVerticalLayoutGroup)component4).childForceExpandWidth = true;
			((HorizontalOrVerticalLayoutGroup)component4).childForceExpandHeight = false;
			ContentSizeFitter component5 = val4.GetComponent<ContentSizeFitter>();
			component5.verticalFit = (FitMode)2;
			_scrollRect = val2.AddComponent<ScrollRect>();
			_scrollRect.viewport = component2;
			_scrollRect.content = _contentRoot;
			_scrollRect.horizontal = false;
			_scrollRect.vertical = true;
			_scrollRect.scrollSensitivity = Plugin.GetPasswordListScrollSpeed();
			_scrollRect.movementType = (MovementType)2;
		}

		private void RefreshRows()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			if ((Object)(object)_contentRoot == (Object)null)
			{
				return;
			}
			foreach (Transform item in (Transform)_contentRoot)
			{
				Transform val = item;
				Object.Destroy((Object)(object)((Component)val).gameObject);
			}
			IReadOnlyList<SavedPasswordEntry> entries = _storage.GetEntries();
			foreach (SavedPasswordEntry item2 in entries)
			{
				BuildRow(item2);
			}
			if ((Object)(object)_toggleButton != (Object)null)
			{
				((Selectable)_toggleButton).interactable = entries.Count > 0;
			}
			UpdateDrawerHeight(entries.Count);
			if ((Object)(object)_scrollRect != (Object)null)
			{
				_scrollRect.scrollSensitivity = Plugin.GetPasswordListScrollSpeed();
				LayoutRebuilder.ForceRebuildLayoutImmediate(_drawerRoot);
				_scrollRect.verticalNormalizedPosition = 1f;
			}
		}

		private void BuildRow(SavedPasswordEntry entry)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Expected O, but got Unknown
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Expected O, but got Unknown
			//IL_0198: 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_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0266: Expected O, but got Unknown
			//IL_028f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0315: Unknown result type (might be due to invalid IL or missing references)
			//IL_0341: Unknown result type (might be due to invalid IL or missing references)
			//IL_034b: Expected O, but got Unknown
			GameObject val = new GameObject("PasswordRow", new Type[4]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Button),
				typeof(LayoutElement)
			});
			val.transform.SetParent((Transform)(object)_contentRoot, false);
			RectTransform component = val.GetComponent<RectTransform>();
			component.anchorMin = new Vector2(0f, 1f);
			component.anchorMax = new Vector2(1f, 1f);
			component.pivot = new Vector2(0.5f, 1f);
			component.sizeDelta = new Vector2(0f, 34f);
			LayoutElement component2 = val.GetComponent<LayoutElement>();
			component2.preferredHeight = 34f;
			Image component3 = val.GetComponent<Image>();
			CopyImageStyle(FindBestImageTemplate((Component)(object)((Component)_inputField).transform), component3, new Color(0.21f, 0.14f, 0.09f, 0.96f));
			Button component4 = val.GetComponent<Button>();
			((Selectable)component4).targetGraphic = (Graphic)(object)component3;
			((UnityEvent)component4.onClick).AddListener((UnityAction)delegate
			{
				SetInputText(entry.password);
				CloseDrawer();
			});
			GameObject val2 = new GameObject("Password", new Type[2]
			{
				typeof(RectTransform),
				typeof(TextMeshProUGUI)
			});
			val2.transform.SetParent(val.transform, false);
			RectTransform component5 = val2.GetComponent<RectTransform>();
			component5.anchorMin = new Vector2(0f, 0f);
			component5.anchorMax = new Vector2(1f, 1f);
			component5.offsetMin = new Vector2(12f, 0f);
			component5.offsetMax = new Vector2(-42f, 0f);
			TextMeshProUGUI component6 = val2.GetComponent<TextMeshProUGUI>();
			CopyTextStyle(FindInputTextTemplate((Component)(object)_dialogRoot), (TMP_Text)(object)component6);
			((TMP_Text)component6).alignment = (TextAlignmentOptions)4097;
			((TMP_Text)component6).textWrappingMode = (TextWrappingModes)0;
			((TMP_Text)component6).text = entry.password;
			GameObject val3 = new GameObject("DeleteButton", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Button)
			});
			val3.transform.SetParent(val.transform, false);
			RectTransform component7 = val3.GetComponent<RectTransform>();
			component7.anchorMin = new Vector2(1f, 0.5f);
			component7.anchorMax = new Vector2(1f, 0.5f);
			component7.pivot = new Vector2(1f, 0.5f);
			component7.sizeDelta = new Vector2(28f, 28f);
			component7.anchoredPosition = new Vector2(-6f, 0f);
			Image component8 = val3.GetComponent<Image>();
			((Graphic)component8).color = new Color(0.2f, 0.05f, 0.05f, 0.55f);
			Button component9 = val3.GetComponent<Button>();
			((Selectable)component9).targetGraphic = (Graphic)(object)component8;
			((UnityEvent)component9.onClick).AddListener((UnityAction)delegate
			{
				_storage.Remove(entry.password);
				RefreshRows();
			});
			BuildTrashCanIcon(val3.transform);
		}

		private void SetInputText(string password)
		{
			if (!((Object)(object)_inputField == (Object)null))
			{
				((TMP_InputField)_inputField).text = password ?? string.Empty;
				_inputField.ActivateInputField();
			}
		}

		private void ToggleDrawer()
		{
			if (!((Object)(object)_drawerRoot == (Object)null))
			{
				if (_drawerVisible)
				{
					CloseDrawer();
				}
				else
				{
					OpenDrawer();
				}
			}
		}

		private void OpenDrawer()
		{
			if (!((Object)(object)_drawerRoot == (Object)null) && (!((Object)(object)_toggleButton != (Object)null) || ((Selectable)_toggleButton).interactable))
			{
				_drawerVisible = true;
				((Component)_drawerRoot).gameObject.SetActive(true);
				if ((Object)(object)_scrollRect != (Object)null)
				{
					_scrollRect.scrollSensitivity = Plugin.GetPasswordListScrollSpeed();
					LayoutRebuilder.ForceRebuildLayoutImmediate(_drawerRoot);
					_scrollRect.verticalNormalizedPosition = 1f;
				}
			}
		}

		private void CloseDrawer()
		{
			_drawerVisible = false;
			if ((Object)(object)_drawerRoot != (Object)null)
			{
				((Component)_drawerRoot).gameObject.SetActive(false);
			}
		}

		private void UpdateDrawerHeight(int count)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_drawerRoot == (Object)null))
			{
				int num = Mathf.Clamp(count, 0, 8);
				float num2 = ((num <= 0) ? 0f : ((float)num * 34f + (float)Mathf.Max(0, num - 1) * 2f + 16f));
				_drawerRoot.sizeDelta = new Vector2(_drawerRoot.sizeDelta.x, num2);
				if (count <= 0)
				{
					CloseDrawer();
				}
			}
		}

		private void SetDialogVisible(bool visible)
		{
			if ((Object)(object)_dialogRoot != (Object)null)
			{
				((Component)_dialogRoot).gameObject.SetActive(visible);
			}
		}

		private static void ClearServerPasswordCache()
		{
			ServerPasswordBackingField?.SetValue(null, string.Empty);
		}

		private static Image FindBestImageTemplate(Component root)
		{
			if ((Object)(object)root == (Object)null)
			{
				return null;
			}
			Image component = root.GetComponent<Image>();
			if ((Object)(object)component != (Object)null)
			{
				return component;
			}
			return root.GetComponentInChildren<Image>(true);
		}

		private static TMP_Text FindInputTextTemplate(Component root)
		{
			if ((Object)(object)root == (Object)null)
			{
				return null;
			}
			return root.GetComponentInChildren<TMP_Text>(true);
		}

		private static void BuildTriangleIcon(Transform parent)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: 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_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: 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_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("ArrowIcon", new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(parent, false);
			RectTransform component = val.GetComponent<RectTransform>();
			component.anchorMin = Vector2.zero;
			component.anchorMax = Vector2.one;
			component.offsetMin = Vector2.zero;
			component.offsetMax = Vector2.zero;
			Color color = default(Color);
			((Color)(ref color))..ctor(0.82f, 0.72f, 0.52f, 1f);
			CreateIconPart(val.transform, "Top", new Vector2(0.5f, 0.6f), new Vector2(14f, 2f), color);
			CreateIconPart(val.transform, "Middle", new Vector2(0.5f, 0.48f), new Vector2(10f, 2f), color);
			CreateIconPart(val.transform, "Bottom", new Vector2(0.5f, 0.36f), new Vector2(6f, 2f), color);
		}

		private static void BuildTrashCanIcon(Transform parent)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: 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_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: 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_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: 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_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("DeleteIcon", new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(parent, false);
			RectTransform component = val.GetComponent<RectTransform>();
			component.anchorMin = Vector2.zero;
			component.anchorMax = Vector2.one;
			component.offsetMin = Vector2.zero;
			component.offsetMax = Vector2.zero;
			Color color = default(Color);
			((Color)(ref color))..ctor(0.86f, 0.25f, 0.25f, 1f);
			CreateIconPart(val.transform, "Body", new Vector2(0.5f, 0.38f), new Vector2(10f, 12f), color);
			CreateIconPart(val.transform, "Lid", new Vector2(0.5f, 0.68f), new Vector2(13f, 2f), color);
			CreateIconPart(val.transform, "Handle", new Vector2(0.5f, 0.79f), new Vector2(5f, 2f), color);
			CreateIconPart(val.transform, "LeftLine", new Vector2(0.37f, 0.38f), new Vector2(1f, 8f), new Color(0.45f, 0.09f, 0.09f, 0.85f));
			CreateIconPart(val.transform, "CenterLine", new Vector2(0.5f, 0.38f), new Vector2(1f, 8f), new Color(0.45f, 0.09f, 0.09f, 0.85f));
			CreateIconPart(val.transform, "RightLine", new Vector2(0.63f, 0.38f), new Vector2(1f, 8f), new Color(0.45f, 0.09f, 0.09f, 0.85f));
		}

		private static void CreateIconPart(Transform parent, string name, Vector2 anchor, Vector2 size, Color color)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val.transform.SetParent(parent, false);
			RectTransform component = val.GetComponent<RectTransform>();
			component.anchorMin = anchor;
			component.anchorMax = anchor;
			component.pivot = new Vector2(0.5f, 0.5f);
			component.sizeDelta = size;
			component.anchoredPosition = Vector2.zero;
			Image component2 = val.GetComponent<Image>();
			((Graphic)component2).color = color;
			((Graphic)component2).raycastTarget = false;
		}

		private static void CopyImageStyle(Image source, Image target, Color fallbackColor)
		{
			//IL_0061: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: 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)
			if (!((Object)(object)target == (Object)null))
			{
				if ((Object)(object)source != (Object)null)
				{
					target.sprite = source.sprite;
					target.type = source.type;
					((Graphic)target).material = ((Graphic)source).material;
					target.pixelsPerUnitMultiplier = source.pixelsPerUnitMultiplier;
					((Graphic)target).color = ((Graphic)source).color;
				}
				else
				{
					((Graphic)target).color = fallbackColor;
				}
				if (((Graphic)target).color.a <= 0.01f)
				{
					((Graphic)target).color = fallbackColor;
				}
			}
		}

		private static void CopyTextStyle(TMP_Text source, TMP_Text target)
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)target == (Object)null))
			{
				if ((Object)(object)source != (Object)null)
				{
					target.font = source.font;
					target.fontSharedMaterial = source.fontSharedMaterial;
					target.fontSize = source.fontSize;
					((Graphic)target).color = ((Graphic)source).color;
					target.enableAutoSizing = false;
					target.richText = false;
				}
				else
				{
					target.fontSize = 18f;
					((Graphic)target).color = Color.white;
				}
			}
		}
	}
}
namespace ValheimPasswordManager.Services
{
	public sealed class ModLocalizationService
	{
		private static readonly MethodInfo GetSelectedLanguageMethod = AccessTools.Method(typeof(Localization), "GetSelectedLanguage", (Type[])null, (Type[])null);

		private static readonly Dictionary<string, string> SavePasswordPromptTranslations = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
		{
			["Chinese"] = "是否保存该密码?",
			["Chinese_Trad"] = "是否儲存該密碼?",
			["Czech"] = "Uložit toto heslo?",
			["Danish"] = "Vil du gemme denne adgangskode?",
			["Dutch"] = "Dit wachtwoord opslaan?",
			["English"] = "Save this password?",
			["Finnish"] = "Tallennetaanko tämä salasana?",
			["French"] = "Enregistrer ce mot de passe ?",
			["German"] = "Dieses Passwort speichern?",
			["Greek"] = "Αποθήκευση αυτού του κωδικού πρόσβασης;",
			["Hungarian"] = "Menti ezt a jelszót?",
			["Italian"] = "Salvare questa password?",
			["Japanese"] = "このパスワードを保存しますか?",
			["Korean"] = "이 비밀번호를 저장할까요?",
			["Norwegian"] = "Lagre dette passordet?",
			["Polish"] = "Zapisać to hasło?",
			["Portuguese_Brazilian"] = "Salvar esta senha?",
			["Portuguese_European"] = "Guardar esta palavra-passe?",
			["Russian"] = "Сохранить этот пароль?",
			["Slovak"] = "Uložiť toto heslo?",
			["Spanish"] = "¿Guardar esta contraseña?",
			["Swedish"] = "Spara det här lösenordet?",
			["Turkish"] = "Bu parola kaydedilsin mi?"
		};

		public string GetSavePasswordPromptForCurrentLanguage()
		{
			try
			{
				Localization instance = Localization.instance;
				string currentLanguage = GetCurrentLanguage(instance);
				return GetSavePasswordPrompt(currentLanguage);
			}
			catch (Exception arg)
			{
				Plugin.Log.LogWarning((object)$"Failed to resolve localized prompt text safely: {arg}");
				return GetSavePasswordPrompt("English");
			}
		}

		private static string GetCurrentLanguage(Localization localization)
		{
			if (localization == null)
			{
				return "English";
			}
			string text = GetSelectedLanguageMethod?.Invoke(localization, null) as string;
			return string.IsNullOrWhiteSpace(text) ? "English" : text;
		}

		private static string GetSavePasswordPrompt(string language)
		{
			if (!string.IsNullOrWhiteSpace(language) && SavePasswordPromptTranslations.TryGetValue(language, out var value))
			{
				return value;
			}
			return SavePasswordPromptTranslations["English"];
		}
	}
	public sealed class PasswordStorageService
	{
		private const string StoreFileName = "JipZeonGit.Valheim.PasswordManager.json";

		private readonly object _sync = new object();

		private readonly string _filePath;

		private readonly DataContractJsonSerializer _serializer;

		private PasswordStoreFile _store;

		public PasswordStorageService()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			_filePath = Path.Combine(Paths.ConfigPath, "JipZeonGit.Valheim.PasswordManager.json");
			_serializer = new DataContractJsonSerializer(typeof(PasswordStoreFile));
			_store = LoadOrCreate();
			Save();
		}

		public IReadOnlyList<SavedPasswordEntry> GetEntries()
		{
			lock (_sync)
			{
				return (from x in _store.entries.Where(IsValidEntry)
					orderby ParseUtc(x.lastUsedUtc) descending, ParseUtc(x.createdAtUtc) descending
					select x).Select(CloneEntry).ToList();
			}
		}

		public bool Contains(string password)
		{
			if (string.IsNullOrWhiteSpace(password))
			{
				return false;
			}
			lock (_sync)
			{
				return _store.entries.Any((SavedPasswordEntry x) => string.Equals(x.password, password, StringComparison.Ordinal));
			}
		}

		public void Upsert(string password)
		{
			if (string.IsNullOrWhiteSpace(password))
			{
				return;
			}
			lock (_sync)
			{
				string text = DateTime.UtcNow.ToString("O");
				SavedPasswordEntry savedPasswordEntry = _store.entries.FirstOrDefault((SavedPasswordEntry x) => string.Equals(x.password, password, StringComparison.Ordinal));
				if (savedPasswordEntry == null)
				{
					savedPasswordEntry = new SavedPasswordEntry
					{
						password = password,
						createdAtUtc = text,
						lastUsedUtc = text
					};
					_store.entries.Add(savedPasswordEntry);
				}
				else
				{
					if (string.IsNullOrWhiteSpace(savedPasswordEntry.createdAtUtc))
					{
						savedPasswordEntry.createdAtUtc = text;
					}
					savedPasswordEntry.lastUsedUtc = text;
				}
				Save();
			}
		}

		public void Touch(string password)
		{
			if (string.IsNullOrWhiteSpace(password))
			{
				return;
			}
			lock (_sync)
			{
				SavedPasswordEntry savedPasswordEntry = _store.entries.FirstOrDefault((SavedPasswordEntry x) => string.Equals(x.password, password, StringComparison.Ordinal));
				if (savedPasswordEntry != null)
				{
					savedPasswordEntry.lastUsedUtc = DateTime.UtcNow.ToString("O");
					Save();
				}
			}
		}

		public void Remove(string password)
		{
			if (string.IsNullOrWhiteSpace(password))
			{
				return;
			}
			lock (_sync)
			{
				_store.entries.RemoveAll((SavedPasswordEntry x) => string.Equals(x.password, password, StringComparison.Ordinal));
				Save();
			}
		}

		public string GetFilePath()
		{
			return _filePath;
		}

		private PasswordStoreFile LoadOrCreate()
		{
			try
			{
				Directory.CreateDirectory(Path.GetDirectoryName(_filePath) ?? Paths.ConfigPath);
				if (!File.Exists(_filePath))
				{
					return CreateEmptyStore();
				}
				string text = File.ReadAllText(_filePath);
				if (string.IsNullOrWhiteSpace(text))
				{
					return CreateEmptyStore();
				}
				string s = NormalizeJson(text);
				PasswordStoreFile passwordStoreFile;
				using (MemoryStream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(s)))
				{
					passwordStoreFile = ((XmlObjectSerializer)_serializer).ReadObject((Stream)memoryStream) as PasswordStoreFile;
				}
				if (passwordStoreFile?.entries == null)
				{
					throw new InvalidDataException("JSON root or entries list is missing.");
				}
				passwordStoreFile.entries = (from x in passwordStoreFile.entries.Where(IsValidEntry).GroupBy<SavedPasswordEntry, string>((SavedPasswordEntry x) => x.password, StringComparer.Ordinal)
					select x.OrderByDescending((SavedPasswordEntry y) => ParseUtc(y.lastUsedUtc)).First()).ToList();
				return passwordStoreFile;
			}
			catch (Exception arg)
			{
				Plugin.Log.LogWarning((object)$"Failed to load password store, backing it up and recreating. Error: {arg}");
				BackupCorruptFile();
				return CreateEmptyStore();
			}
		}

		private void Save()
		{
			try
			{
				Directory.CreateDirectory(Path.GetDirectoryName(_filePath) ?? Paths.ConfigPath);
				using MemoryStream memoryStream = new MemoryStream();
				((XmlObjectSerializer)_serializer).WriteObject((Stream)memoryStream, (object)_store);
				File.WriteAllBytes(_filePath, memoryStream.ToArray());
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"Failed to save password store at {_filePath}: {arg}");
			}
		}

		private void BackupCorruptFile()
		{
			try
			{
				if (File.Exists(_filePath))
				{
					string destFileName = _filePath + ".corrupt-" + DateTime.UtcNow.ToString("yyyyMMddHHmmss") + ".bak";
					File.Copy(_filePath, destFileName, overwrite: true);
				}
			}
			catch (Exception arg)
			{
				Plugin.Log.LogWarning((object)$"Failed to back up corrupt password store: {arg}");
			}
		}

		private static PasswordStoreFile CreateEmptyStore()
		{
			return new PasswordStoreFile();
		}

		private static string NormalizeJson(string json)
		{
			return (json ?? string.Empty).Trim().TrimStart('\ufeff', '\u200b', '\0');
		}

		private static bool IsValidEntry(SavedPasswordEntry entry)
		{
			return entry != null && !string.IsNullOrWhiteSpace(entry.password);
		}

		private static DateTime ParseUtc(string value)
		{
			if (DateTime.TryParse(value, null, DateTimeStyles.RoundtripKind, out var result))
			{
				return result.ToUniversalTime();
			}
			return DateTime.MinValue;
		}

		private static SavedPasswordEntry CloneEntry(SavedPasswordEntry entry)
		{
			return new SavedPasswordEntry
			{
				password = entry.password,
				createdAtUtc = entry.createdAtUtc,
				lastUsedUtc = entry.lastUsedUtc
			};
		}
	}
}
namespace ValheimPasswordManager.Patches
{
	[HarmonyPatch(typeof(ZNet), "RPC_ClientHandshake")]
	internal static class ZNetClientHandshakePatch
	{
		private static void Postfix(ZNet __instance, bool needPassword)
		{
			if (needPassword)
			{
				Plugin.DialogController.OnPasswordDialogShown(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(ZNet), "OnPasswordEntered")]
	internal static class ZNetPasswordSubmitPatch
	{
		private static bool Prefix(ZNet __instance, string pwd)
		{
			return Plugin.DialogController.ShouldAllowOriginalSubmit(__instance, pwd);
		}
	}
}
namespace ValheimPasswordManager.Data
{
	[DataContract]
	public sealed class PasswordStoreFile
	{
		[DataMember(Name = "entries")]
		public List<SavedPasswordEntry> entries = new List<SavedPasswordEntry>();
	}
	[DataContract]
	public sealed class SavedPasswordEntry
	{
		[DataMember(Name = "password")]
		public string password = string.Empty;

		[DataMember(Name = "createdAtUtc")]
		public string createdAtUtc = string.Empty;

		[DataMember(Name = "lastUsedUtc")]
		public string lastUsedUtc = string.Empty;
	}
}