Decompiled source of ShieldRestyler v1.0.0

ShieldRestyler.dll

Decompiled 2 days ago
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<KeyboardShortcut> 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<KeyboardShortcut>("General", "OpenStylerKey", new KeyboardShortcut((KeyCode)96, Array.Empty<KeyCode>()), "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<string> 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<RectTransform>();
					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<string, List<string>> Variants = new Dictionary<string, List<string>>
		{
			{
				"ShieldWood",
				new List<string> { "Plain", "Iron Rivets", "Sun Cross", "Spirals" }
			},
			{
				"ShieldWoodTower",
				new List<string> { "Plain", "Diamond", "Cross", "Banded" }
			},
			{
				"ShieldBoneTower",
				new List<string> { "Ribbed", "Skull Face", "Spine Cross", "Jagged" }
			},
			{
				"ShieldBronze",
				new List<string> { "Plain", "Concentric Rings", "Sun Boss", "Etched Rim" }
			},
			{
				"ShieldBronzeBuckler",
				new List<string> { "Plain", "Punched", "Riveted", "Embossed" }
			},
			{
				"ShieldIron",
				new List<string> { "Plain", "Banded", "Studded", "Engraved", "Worn" }
			},
			{
				"ShieldIronTower",
				new List<string> { "Plain", "Flanged", "Cross Guard", "Spiked", "Runic" }
			},
			{
				"ShieldIronBuckler",
				new List<string> { "Smooth", "Hammered", "Punched", "Etched" }
			},
			{
				"ShieldSilver",
				new List<string> { "Plain", "Moon Crest", "Wolf Howl", "Frost Rune", "Dragon Fang", "Blizzard" }
			},
			{
				"ShieldBlackmetal",
				new List<string> { "Plain", "Serpent Eye", "Fuling Glyph", "Death Mark", "Tar Splash", "Runed", "Warlord" }
			},
			{
				"ShieldBlackmetalTower",
				new List<string> { "Plain", "Spiked", "Rune Wall", "Glyph Crest", "War Chief", "Obsidian" }
			},
			{
				"ShieldCarapace",
				new List<string> { "Natural", "Polished", "Cracked", "Runed", "Seeker Glyph" }
			},
			{
				"ShieldCarapaceBuckler",
				new List<string> { "Natural", "Polished", "Cracked", "Runed" }
			},
			{
				"ShieldFlametal",
				new List<string> { "Ember", "Scorched", "Molten", "Ash Rune", "Cinder Crest", "Inferno" }
			},
			{
				"ShieldFlametalTower",
				new List<string> { "Ember", "Scorched", "Molten", "Ash Rune", "Cinder Crest", "Inferno", "Volcanic" }
			}
		};

		public static bool HasVariants(string prefabName)
		{
			return Variants.ContainsKey(prefabName);
		}

		public static List<string> GetVariants(string prefabName)
		{
			List<string> 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<string, int> _choices = new Dictionary<string, int>();

		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<string> list = new List<string>();
			foreach (KeyValuePair<string, int> 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}";
		}
	}
}