using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using ShieldRestyler.Data; using ShieldRestyler.Patches; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("ShieldRestyler")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("HP")] [assembly: AssemblyProduct("ShieldRestyler")] [assembly: AssemblyCopyright("Copyright © HP 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("4b016a14-be14-4ddd-b106-a3020d02e2e3")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = "")] [assembly: AssemblyVersion("1.0.0.0")] namespace ShieldRestyler { [BepInPlugin("YouDied.ShieldRestyler", "Shield Restyler", "1.0.0")] [BepInProcess("valheim.exe")] public class ShieldRestylerPlugin : BaseUnityPlugin { public const string PluginGUID = "YouDied.ShieldRestyler"; public const string PluginName = "Shield Restyler"; public const string PluginVersion = "1.0.0"; internal static ManualLogSource Log; public static ConfigEntry OpenStylerKey; private readonly Harmony _harmony = new Harmony("YouDied.ShieldRestyler"); private void Awake() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; OpenStylerKey = ((BaseUnityPlugin)this).Config.Bind("General", "OpenStylerKey", new KeyboardShortcut((KeyCode)96, Array.Empty()), "Press while hovering a shield in the inventory grid to cycle its visual style."); _harmony.PatchAll(); InventoryGui_Patches.Apply(_harmony); ManualLogSource log = Log; KeyboardShortcut value = OpenStylerKey.Value; log.LogInfo((object)string.Format("{0} {1} loaded. Press [{2}] while hovering a shield to cycle styles.", "Shield Restyler", "1.0.0", ((KeyboardShortcut)(ref value)).MainKey)); } private void OnDestroy() { _harmony.UnpatchSelf(); } } } namespace ShieldRestyler.Patches { public static class InventoryGui_Patches { internal static ItemData LastHoveredShield; public static void Apply(Harmony harmony) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; MethodInfo method = typeof(InventoryGui).GetMethod("Update", bindingAttr); if (method != null) { harmony.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(typeof(InventoryGui_Patches), "Update_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ShieldRestylerPlugin.Log.LogInfo((object)"[ShieldRestyler] Patched InventoryGui.Update"); } } private static void Update_Postfix() { //IL_0019: 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_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) if (!InventoryGui.IsVisible()) { return; } KeyboardShortcut value = ShieldRestylerPlugin.OpenStylerKey.Value; KeyCode mainKey = ((KeyboardShortcut)(ref value)).MainKey; if (Input.GetKeyDown(mainKey) && LastHoveredShield != null) { string prefabName = GetPrefabName(LastHoveredShield); if (ShieldVariantDatabase.HasVariants(prefabName)) { List variants = ShieldVariantDatabase.GetVariants(prefabName); int num = (LastHoveredShield.m_variant + 1) % variants.Count; LastHoveredShield.m_variant = num; string slotKey = StyleSaveData.MakeSlotKey(LastHoveredShield); StyleSaveData.SetChoice(slotKey, num); ShieldRestylerPlugin.Log.LogInfo((object)$"[ShieldRestyler] {LastHoveredShield.m_shared.m_name} → variant {num} ({variants[num]})"); } } } internal static string GetPrefabName(ItemData item) { if ((Object)(object)item.m_dropPrefab != (Object)null) { return ((Object)item.m_dropPrefab).name; } string text = item.m_shared.m_name.Replace("$item_", ""); string[] array = text.Split(new char[1] { '_' }); StringBuilder stringBuilder = new StringBuilder(); string[] array2 = array; foreach (string text2 in array2) { if (text2.Length > 0) { stringBuilder.Append(char.ToUpper(text2[0])).Append(text2.Substring(1)); } } return stringBuilder.ToString(); } } [HarmonyPatch(typeof(InventoryGrid), "UpdateGui")] public static class InventoryGrid_UpdateGui_Patch { private static FieldInfo _elementsField; private static FieldInfo _posField; private static FieldInfo _goField; private static bool _ready; [HarmonyPostfix] private static void Postfix(InventoryGrid __instance) { //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Invalid comparison between Unknown and I4 //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Player.m_localPlayer == (Object)null || __instance.GetInventory() != ((Humanoid)Player.m_localPlayer).GetInventory() || !InventoryGui.IsVisible()) { return; } if (!_ready) { BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; _elementsField = typeof(InventoryGrid).GetField("m_elements", bindingAttr); if (_elementsField == null || !(_elementsField.GetValue(__instance) is IList list) || list.Count == 0) { return; } Type type = list[0].GetType(); _posField = type.GetField("m_pos", bindingAttr); _goField = type.GetField("m_go", bindingAttr); _ready = _posField != null && _goField != null; if (_ready) { ShieldRestylerPlugin.Log.LogInfo((object)"[ShieldRestyler] InventoryGrid fields resolved."); } } if (!_ready) { return; } IList list2 = _elementsField.GetValue(__instance) as IList; Inventory inventory = __instance.GetInventory(); Vector3 mousePosition = Input.mousePosition; ItemData val = null; foreach (object item in list2) { object? value = _goField.GetValue(item); GameObject val2 = (GameObject)((value is GameObject) ? value : null); if (!((Object)(object)val2 == (Object)null) && val2.activeInHierarchy) { RectTransform component = val2.GetComponent(); if (!((Object)(object)component == (Object)null) && RectTransformUtility.RectangleContainsScreenPoint(component, Vector2.op_Implicit(mousePosition))) { Vector2i val3 = (Vector2i)_posField.GetValue(item); val = inventory.GetItemAt(val3.x, val3.y); break; } } } InventoryGui_Patches.LastHoveredShield = ((val != null && (int)val.m_shared.m_itemType == 5) ? val : null); } } [HarmonyPatch(typeof(Player), "OnSpawned")] public static class Player_OnSpawned_Patch { [HarmonyPostfix] private static void Postfix(Player __instance) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Invalid comparison between Unknown and I4 if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } Game instance = Game.instance; object obj; if (instance == null) { obj = null; } else { PlayerProfile playerProfile = instance.GetPlayerProfile(); obj = ((playerProfile != null) ? playerProfile.GetName() : null); } if (obj == null) { obj = "unknown"; } string characterName = (string)obj; StyleSaveData.LoadForCharacter(characterName); Inventory inventory = ((Humanoid)__instance).GetInventory(); if (inventory == null) { return; } foreach (ItemData allItem in inventory.GetAllItems()) { if ((int)allItem.m_shared.m_itemType == 5) { string prefabName = (((Object)(object)allItem.m_dropPrefab != (Object)null) ? ((Object)allItem.m_dropPrefab).name : ""); if (ShieldVariantDatabase.HasVariants(prefabName)) { allItem.m_variant = StyleSaveData.GetChoice(StyleSaveData.MakeSlotKey(allItem)); } } } } } } namespace ShieldRestyler.Data { public static class ShieldVariantDatabase { public static readonly Dictionary> Variants = new Dictionary> { { "ShieldWood", new List { "Plain", "Iron Rivets", "Sun Cross", "Spirals" } }, { "ShieldWoodTower", new List { "Plain", "Diamond", "Cross", "Banded" } }, { "ShieldBoneTower", new List { "Ribbed", "Skull Face", "Spine Cross", "Jagged" } }, { "ShieldBronze", new List { "Plain", "Concentric Rings", "Sun Boss", "Etched Rim" } }, { "ShieldBronzeBuckler", new List { "Plain", "Punched", "Riveted", "Embossed" } }, { "ShieldIron", new List { "Plain", "Banded", "Studded", "Engraved", "Worn" } }, { "ShieldIronTower", new List { "Plain", "Flanged", "Cross Guard", "Spiked", "Runic" } }, { "ShieldIronBuckler", new List { "Smooth", "Hammered", "Punched", "Etched" } }, { "ShieldSilver", new List { "Plain", "Moon Crest", "Wolf Howl", "Frost Rune", "Dragon Fang", "Blizzard" } }, { "ShieldBlackmetal", new List { "Plain", "Serpent Eye", "Fuling Glyph", "Death Mark", "Tar Splash", "Runed", "Warlord" } }, { "ShieldBlackmetalTower", new List { "Plain", "Spiked", "Rune Wall", "Glyph Crest", "War Chief", "Obsidian" } }, { "ShieldCarapace", new List { "Natural", "Polished", "Cracked", "Runed", "Seeker Glyph" } }, { "ShieldCarapaceBuckler", new List { "Natural", "Polished", "Cracked", "Runed" } }, { "ShieldFlametal", new List { "Ember", "Scorched", "Molten", "Ash Rune", "Cinder Crest", "Inferno" } }, { "ShieldFlametalTower", new List { "Ember", "Scorched", "Molten", "Ash Rune", "Cinder Crest", "Inferno", "Volcanic" } } }; public static bool HasVariants(string prefabName) { return Variants.ContainsKey(prefabName); } public static List GetVariants(string prefabName) { List value; return Variants.TryGetValue(prefabName, out value) ? value : null; } } public static class StyleSaveData { private static readonly string SaveDir = Path.Combine(Paths.ConfigPath, "ShieldRestyler"); private static Dictionary _choices = new Dictionary(); private static string _currentCharacter = ""; private static ManualLogSource Log => ShieldRestylerPlugin.Log; public static int GetChoice(string slotKey) { int value; return _choices.TryGetValue(slotKey, out value) ? value : 0; } public static void SetChoice(string slotKey, int variant) { _choices[slotKey] = variant; SaveToDisk(); } public static void LoadForCharacter(string characterName) { _currentCharacter = characterName; _choices.Clear(); string savePath = GetSavePath(characterName); if (!File.Exists(savePath)) { return; } string[] array = File.ReadAllLines(savePath); foreach (string text in array) { if (!string.IsNullOrWhiteSpace(text)) { string[] array2 = text.Split(new char[1] { '=' }); if (array2.Length == 2 && int.TryParse(array2[1], out var result)) { _choices[array2[0]] = result; } } } Log.LogDebug((object)$"[StyleSaveData] Loaded {_choices.Count} choices for '{characterName}'."); } private static void SaveToDisk() { if (string.IsNullOrEmpty(_currentCharacter)) { return; } Directory.CreateDirectory(SaveDir); List list = new List(); foreach (KeyValuePair choice in _choices) { list.Add($"{choice.Key}={choice.Value}"); } File.WriteAllLines(GetSavePath(_currentCharacter), list); } private static string GetSavePath(string characterName) { return Path.Combine(SaveDir, characterName + ".cfg"); } public static string MakeSlotKey(ItemData item) { string arg = (((Object)(object)item.m_dropPrefab != (Object)null) ? ((Object)item.m_dropPrefab).name : item.m_shared.m_name); return $"{arg}_{item.m_gridPos.x}_{item.m_gridPos.y}"; } } }