Please disclose if your mod was created primarily using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ValheimPasswordManager v1.0.1
BepInEx\plugins\JipZeonGit-ValheimPasswordManager\ValheimPasswordManager.dll
Decompiled 6 hours agousing 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; } }