using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("ValheimArmorColors")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("ValheimArmorColors")] [assembly: AssemblyTitle("ValheimArmorColors")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ValheimArmorColors { public static class ArmorColorConfig { private static ConfigFile _cfg; public const string DefaultColor = "0,0,0,0"; public static void Init(ConfigFile cfg) { _cfg = cfg; } public static string MakeKey(string charKey, string itemName) { return charKey + "::" + itemName; } public static Color GetColor(string charKey, string itemName) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) ConfigEntry val = _cfg.Bind("ItemColors", MakeKey(charKey, itemName), "0,0,0,0", (ConfigDescription)null); return Parse(val.Value); } public static void SetColor(string charKey, string itemName, Color color) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) ConfigEntry val = _cfg.Bind("ItemColors", MakeKey(charKey, itemName), "0,0,0,0", (ConfigDescription)null); val.Value = Serialize(color); } public static void ClearColor(string charKey, string itemName) { ConfigEntry val = _cfg.Bind("ItemColors", MakeKey(charKey, itemName), "0,0,0,0", (ConfigDescription)null); val.Value = "0,0,0,0"; } public static Color Parse(string value) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) string[] array = value.Split(new char[1] { ',' }); if (array.Length < 3) { return Color.clear; } float num = TryParse(array[0]); float num2 = TryParse(array[1]); float num3 = TryParse(array[2]); float num4 = ((array.Length >= 4) ? TryParse(array[3]) : 255f); return new Color(num / 255f, num2 / 255f, num3 / 255f, num4 / 255f); } public static string Serialize(Color c) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) return $"{Mathf.RoundToInt(c.r * 255f)}," + $"{Mathf.RoundToInt(c.g * 255f)}," + $"{Mathf.RoundToInt(c.b * 255f)}," + $"{Mathf.RoundToInt(c.a * 255f)}"; } private static float TryParse(string s) { float result; return float.TryParse(s.Trim(), out result) ? Mathf.Clamp(result, 0f, 255f) : 255f; } } [BepInPlugin("com.yourname.valheim.armorcolors", "ArmorColors", "1.0.0")] [BepInProcess("valheim.exe")] public class ArmorColorsPlugin : BaseUnityPlugin { public const string PluginGUID = "com.yourname.valheim.armorcolors"; public const string PluginName = "ArmorColors"; public const string PluginVersion = "1.0.0"; internal static ManualLogSource Log; private Harmony _harmony; private void Awake() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown try { Log = ((BaseUnityPlugin)this).Logger; _harmony = new Harmony("com.yourname.valheim.armorcolors"); _harmony.PatchAll(); ArmorColorConfig.Init(((BaseUnityPlugin)this).Config); ((Component)this).gameObject.AddComponent(); ((Component)this).gameObject.AddComponent(); Log.LogInfo((object)"ArmorColors loaded. Numpad * = color picker, Numpad 0 = debug dump."); } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"[ArmorColorsPlugin] Failed to initialise: {arg}"); } } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } public static class ArmorStandSync { private static readonly BindingFlags Flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private const string ZdoPrefix = "ArmorColor_"; private static readonly string[] SlotNames = new string[5] { "helmet", "chest", "leg", "shoulder", "utility" }; private static readonly string[] LegacySlotNames = new string[5] { "helmet", "chest", "legs", "cape", "utility" }; private static readonly string[] ItemFields = new string[5] { "m_helmetItem", "m_chestItem", "m_legItem", "m_shoulderItem", "m_utilityItem" }; public static void SetStandColor(ZNetView znv, string slot, Color color) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)znv == (Object)null) && znv.IsValid()) { znv.GetZDO().Set("ArmorColor_" + slot, ColorUtility.ToHtmlStringRGBA(color)); } } public static bool TryGetStandColor(ZNetView znv, string slot, out Color color) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) color = Color.clear; if ((Object)(object)znv == (Object)null || !znv.IsValid()) { return false; } string text = znv.GetZDO().GetString("ArmorColor_" + slot, ""); if (string.IsNullOrEmpty(text)) { return false; } return ColorUtility.TryParseHtmlString("#" + text, ref color); } public static void ClearStandColor(ZNetView znv, string slot) { if (!((Object)(object)znv == (Object)null) && znv.IsValid()) { znv.GetZDO().Set("ArmorColor_" + slot, ""); } } public static void ApplyStandTints(VisEquipment ve, ZNetView znv) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)znv == (Object)null || !znv.IsValid()) { return; } string charKey = $"stand_{znv.GetZDO().m_uid}"; Type typeFromHandle = typeof(VisEquipment); for (int i = 0; i < SlotNames.Length; i++) { if ((TryGetStandColor(znv, SlotNames[i], out var color) && color.a != 0f) || (TryGetStandColor(znv, LegacySlotNames[i], out color) && color.a != 0f)) { string text = typeFromHandle.GetField(ItemFields[i], Flags)?.GetValue(ve) as string; if (!string.IsNullOrEmpty(text)) { ArmorColorConfig.SetColor(charKey, text, color); } } } } } public class ArmorTintManager : MonoBehaviour { private class TexState { public readonly Dictionary Originals = new Dictionary(); public readonly Dictionary Tinted = new Dictionary(); public readonly Dictionary RendererMats = new Dictionary(); public string LastChestItem = null; public void Clear(MonoBehaviour owner) { foreach (Material[] value2 in RendererMats.Values) { if (value2 == null) { continue; } Material[] array = value2; foreach (Material val in array) { if ((Object)(object)val == (Object)null || !val.HasProperty("_MainTex")) { continue; } Texture texture = val.GetTexture("_MainTex"); Texture2D val2 = (Texture2D)(object)((texture is Texture2D) ? texture : null); if ((Object)(object)val2 != (Object)null && ((Object)val2).name.StartsWith("tinted_")) { string key = ((Object)val2).name.Substring("tinted_".Length); if (Originals.TryGetValue(key, out Texture2D value) && Object.op_Implicit((Object)(object)value)) { val.SetTexture("_MainTex", (Texture)(object)value); } } } } RendererMats.Clear(); foreach (Texture2D value3 in Originals.Values) { if (Object.op_Implicit((Object)(object)value3)) { owner.StartCoroutine(DestroyNextFrame((Object)(object)value3)); } } foreach (Texture2D value4 in Tinted.Values) { if (Object.op_Implicit((Object)(object)value4)) { owner.StartCoroutine(DestroyNextFrame((Object)(object)value4)); } } Originals.Clear(); Tinted.Clear(); LastChestItem = null; } private static IEnumerator DestroyNextFrame(Object obj) { yield return null; if (Object.op_Implicit(obj)) { Object.Destroy(obj); } } } private static readonly BindingFlags Flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private static readonly (string nameField, string instanceField, bool single)[] Slots = new(string, string, bool)[6] { ("m_helmetItem", "m_helmetItemInstance", true), ("m_chestItem", "m_chestItemInstances", false), ("m_legItem", "m_legItemInstances", false), ("m_shoulderItem", "m_shoulderItemInstances", false), ("m_utilityItem", "m_utilityItemInstances", false), ("m_trinketItem", "m_trinketItemInstances", false) }; private readonly Dictionary _texStates = new Dictionary(); private readonly Dictionary _equipHashes = new Dictionary(); private ArmorStand[] _cachedStands; private GameObject[] _cachedCompanions; private int _scanTimer = 0; private string _lastCharName = null; public static ArmorTintManager Instance { get; private set; } private void Awake() { Instance = this; } private void OnEnable() { _lastCharName = null; } private void OnDestroy() { foreach (TexState value in _texStates.Values) { value.Clear((MonoBehaviour)(object)this); } _texStates.Clear(); if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } private TexState GetTexState(VisEquipment ve) { int instanceID = ((Object)ve).GetInstanceID(); if (!_texStates.TryGetValue(instanceID, out TexState value)) { value = (_texStates[instanceID] = new TexState()); } return value; } private void LateUpdate() { //IL_03d5: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { string playerName = localPlayer.GetPlayerName(); if (!string.IsNullOrEmpty(playerName)) { if (playerName != _lastCharName) { VisEquipment component = ((Component)localPlayer).GetComponent(); if ((Object)(object)component != (Object)null) { int instanceID = ((Object)component).GetInstanceID(); if (_texStates.TryGetValue(instanceID, out TexState value)) { value.Clear((MonoBehaviour)(object)this); _texStates.Remove(instanceID); } _equipHashes.Remove(instanceID); } _lastCharName = playerName; } VisEquipment component2 = ((Component)localPlayer).GetComponent(); if ((Object)(object)component2 != (Object)null) { ProcessVisEquipment(component2, ((Humanoid)localPlayer).GetInventory(), playerName); } } } _scanTimer++; if (_scanTimer >= 60) { _scanTimer = 0; _cachedStands = Object.FindObjectsOfType(); List list = new List(); ZNetView[] array = Object.FindObjectsOfType(); foreach (ZNetView val in array) { if ((Object)(object)val != (Object)null && ((Object)((Component)val).gameObject).name == "HC_Companion(Clone)") { list.Add(((Component)val).gameObject); } } _cachedCompanions = list.ToArray(); HashSet hashSet = new HashSet(); if ((Object)(object)localPlayer != (Object)null) { VisEquipment component3 = ((Component)localPlayer).GetComponent(); if ((Object)(object)component3 != (Object)null) { hashSet.Add(((Object)component3).GetInstanceID()); } } if (_cachedStands != null) { ArmorStand[] cachedStands = _cachedStands; foreach (ArmorStand val2 in cachedStands) { if (!((Object)(object)val2 == (Object)null)) { VisEquipment componentInChildren = ((Component)val2).GetComponentInChildren(); if ((Object)(object)componentInChildren != (Object)null) { hashSet.Add(((Object)componentInChildren).GetInstanceID()); } } } } if (_cachedCompanions != null) { GameObject[] cachedCompanions = _cachedCompanions; foreach (GameObject val3 in cachedCompanions) { if (!((Object)(object)val3 == (Object)null)) { VisEquipment component4 = val3.GetComponent(); if ((Object)(object)component4 != (Object)null) { hashSet.Add(((Object)component4).GetInstanceID()); } } } } List list2 = new List(); foreach (int key in _texStates.Keys) { if (!hashSet.Contains(key)) { list2.Add(key); } } foreach (int item in list2) { _texStates[item].Clear((MonoBehaviour)(object)this); _texStates.Remove(item); _equipHashes.Remove(item); } } if (_cachedStands != null) { ArmorStand[] cachedStands2 = _cachedStands; foreach (ArmorStand val4 in cachedStands2) { if ((Object)(object)val4 == (Object)null) { continue; } ZNetView component5 = ((Component)val4).GetComponent(); if (!((Object)(object)component5 == (Object)null) && component5.IsValid()) { VisEquipment componentInChildren2 = ((Component)val4).GetComponentInChildren(); if (!((Object)(object)componentInChildren2 == (Object)null)) { ArmorStandSync.ApplyStandTints(componentInChildren2, component5); ProcessVisEquipment(componentInChildren2, null, $"stand_{component5.GetZDO().m_uid}"); } } } } if (_cachedCompanions == null) { return; } GameObject[] cachedCompanions2 = _cachedCompanions; foreach (GameObject val5 in cachedCompanions2) { if ((Object)(object)val5 == (Object)null) { continue; } ZNetView component6 = val5.GetComponent(); if (!((Object)(object)component6 == (Object)null) && component6.IsValid()) { VisEquipment component7 = val5.GetComponent(); if (!((Object)(object)component7 == (Object)null)) { CompanionSync.SyncToConfig(component6); ProcessVisEquipment(component7, null, CompanionSync.GetCharKey(component6)); } } } } private void ProcessVisEquipment(VisEquipment ve, Inventory inv, string charName) { //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_04d4: Unknown result type (might be due to invalid IL or missing references) //IL_04d9: Unknown result type (might be due to invalid IL or missing references) //IL_04db: Unknown result type (might be due to invalid IL or missing references) //IL_04f1: Unknown result type (might be due to invalid IL or missing references) //IL_0468: Unknown result type (might be due to invalid IL or missing references) //IL_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_02a5: Unknown result type (might be due to invalid IL or missing references) //IL_02ff: Unknown result type (might be due to invalid IL or missing references) //IL_032d: Unknown result type (might be due to invalid IL or missing references) Type typeFromHandle = typeof(VisEquipment); int instanceID = ((Object)ve).GetInstanceID(); bool flag = inv != null; string equipmentHash = GetEquipmentHash(ve, typeFromHandle); if (!_equipHashes.TryGetValue(instanceID, out string value) || equipmentHash != value) { if (_texStates.TryGetValue(instanceID, out TexState value2)) { value2.Clear((MonoBehaviour)(object)this); } _texStates[instanceID] = new TexState(); _equipHashes[instanceID] = equipmentHash; } TexState texState = GetTexState(ve); Dictionary dictionary = new Dictionary(); (string, string, bool)[] slots = Slots; for (int i = 0; i < slots.Length; i++) { (string, string, bool) tuple = slots[i]; string item = tuple.Item1; string item2 = tuple.Item2; bool item3 = tuple.Item3; string text = typeFromHandle.GetField(item, Flags)?.GetValue(ve) as string; if (string.IsNullOrEmpty(text)) { continue; } Color tint = GetTint(inv, charName, text); if (tint.a == 0f) { continue; } List list = new List(); if (item3) { object? obj = typeFromHandle.GetField(item2, Flags)?.GetValue(ve); GameObject val = (GameObject)((obj is GameObject) ? obj : null); if ((Object)(object)val != (Object)null) { list.Add(val); } } else if (typeFromHandle.GetField(item2, Flags)?.GetValue(ve) is List collection) { list.AddRange(collection); } foreach (GameObject item4 in list) { if ((Object)(object)item4 == (Object)null) { continue; } Renderer[] componentsInChildren = item4.GetComponentsInChildren(true); foreach (Renderer val2 in componentsInChildren) { bool flag2 = ((object)val2).GetType().Name == "ParticleSystemRenderer"; Material[] value3; if (flag && !flag2 && HasCreatureShader(val2)) { int instanceID2 = ((Object)val2).GetInstanceID(); if (!texState.RendererMats.TryGetValue(instanceID2, out value3)) { value3 = val2.materials; texState.RendererMats[instanceID2] = value3; } } else { value3 = val2.materials; } Material[] array = value3; foreach (Material val3 in array) { if ((Object)(object)val3 == (Object)null) { continue; } if (flag2) { if (val3.HasProperty("_Color")) { val3.color = tint; } continue; } if (val3.HasProperty("_Color")) { val3.color = tint; } if (flag) { Shader shader = val3.shader; if (((shader != null) ? ((Object)shader).name : null) == "Custom/Creature") { TintMaterialTex(val3, "_MainTex", tint, texState); } } string key = StripSuffix(((Object)val3).name); if (!dictionary.ContainsKey(key)) { dictionary[key] = tint; } } } } } if (dictionary.Count == 0) { return; } object? obj2 = typeFromHandle.GetField("m_visual", Flags)?.GetValue(ve); GameObject val4 = (GameObject)((obj2 is GameObject) ? obj2 : null); if ((Object)(object)val4 != (Object)null) { Renderer[] componentsInChildren2 = val4.GetComponentsInChildren(true); foreach (Renderer val5 in componentsInChildren2) { if (((object)val5).GetType().Name == "ParticleSystemRenderer") { continue; } Material[] sharedMaterials = val5.sharedMaterials; foreach (Material val6 in sharedMaterials) { if (!((Object)(object)val6 == (Object)null) && dictionary.TryGetValue(StripSuffix(((Object)val6).name), out var value4) && val6.HasProperty("_Color")) { val6.color = value4; } } } } if (!flag) { return; } string text2 = typeFromHandle.GetField("m_chestItem", Flags)?.GetValue(ve) as string; if (!string.IsNullOrEmpty(text2)) { Color tint2 = GetTint(inv, charName, text2); if (tint2.a > 0f) { TintChestTex(ve, tint2, texState); } } } private Color GetTint(Inventory inv, string charName, string itemName) { //IL_0021: 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_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) ItemData val = ((inv != null) ? FindItemInInventory(inv, itemName) : null); if (val != null && ItemColorSync.TryGetItemColor(val, out var color)) { return color; } if (charName != null) { return ArmorColorConfig.GetColor(charName, itemName); } return Color.clear; } private static bool HasCreatureShader(Renderer r) { Material[] sharedMaterials = r.sharedMaterials; foreach (Material val in sharedMaterials) { if ((Object)(object)val != (Object)null) { Shader shader = val.shader; if (((shader != null) ? ((Object)shader).name : null) == "Custom/Creature") { return true; } } } return false; } private void TintChestTex(VisEquipment ve, Color tint, TexState state) { //IL_0189: Unknown result type (might be due to invalid IL or missing references) object? obj = typeof(VisEquipment).GetField("m_bodyModel", Flags)?.GetValue(ve); SkinnedMeshRenderer val = (SkinnedMeshRenderer)((obj is SkinnedMeshRenderer) ? obj : null); if ((Object)(object)val == (Object)null) { return; } string text = (typeof(VisEquipment).GetField("m_chestItem", Flags)?.GetValue(ve) as string) ?? ""; if (text != state.LastChestItem) { Material[] materials = ((Renderer)val).materials; foreach (Material val2 in materials) { if ((Object)(object)val2 == (Object)null || !val2.HasProperty("_ChestTex")) { continue; } Texture texture = val2.GetTexture("_ChestTex"); Texture2D val3 = (Texture2D)(object)((texture is Texture2D) ? texture : null); if (!((Object)(object)val3 == (Object)null) && ((Object)val3).name.StartsWith("tinted_")) { string key = ((Object)val3).name.Substring("tinted_".Length); if (state.Originals.TryGetValue(key, out Texture2D value) && Object.op_Implicit((Object)(object)value)) { val2.SetTexture("_ChestTex", (Texture)(object)value); } } } state.Clear((MonoBehaviour)(object)this); state.LastChestItem = text; } Material[] materials2 = ((Renderer)val).materials; foreach (Material mat in materials2) { TintMaterialTex(mat, "_ChestTex", tint, state); } } private void TintMaterialTex(Material mat, string texProp, Color tint, TexState state) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) if (!mat.HasProperty(texProp) || tint == Color.white) { return; } Texture texture = mat.GetTexture(texProp); Texture2D val = (Texture2D)(object)((texture is Texture2D) ? texture : null); if ((Object)(object)val == (Object)null || string.IsNullOrEmpty(((Object)val).name)) { return; } string text = ColorUtility.ToHtmlStringRGBA(tint); string text2 = ((Object)val).name; if (text2.StartsWith("tinted_")) { string text3 = text2.Substring("tinted_".Length); if (!state.Originals.ContainsKey(text3)) { return; } string key = text3 + "|" + text; if (state.Tinted.TryGetValue(key, out Texture2D value) && Object.op_Implicit((Object)(object)value) && (Object)(object)mat.GetTexture(texProp) == (Object)(object)value) { return; } text2 = text3; } if (!state.Originals.ContainsKey(text2)) { try { Texture2D val2 = GpuBlit(val); ((Object)val2).name = text2; state.Originals[text2] = val2; } catch (Exception ex) { ArmorColorsPlugin.Log.LogError((object)("[ArmorTintManager] GpuBlit failed '" + text2 + "': " + ex.Message)); return; } } string key2 = text2 + "|" + text; if (!state.Tinted.TryGetValue(key2, out Texture2D value2)) { if (!state.Originals.TryGetValue(text2, out Texture2D value3)) { return; } try { value2 = TintTexture(value3, tint); ((Object)value2).name = "tinted_" + text2; state.Tinted[key2] = value2; } catch (Exception ex2) { ArmorColorsPlugin.Log.LogError((object)("[ArmorTintManager] TintTexture failed: " + ex2.Message)); return; } } mat.SetTexture(texProp, (Texture)(object)value2); } private static Texture2D GpuBlit(Texture2D source) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_0057: Unknown result type (might be due to invalid IL or missing references) RenderTexture temporary = RenderTexture.GetTemporary(((Texture)source).width, ((Texture)source).height, 0, (RenderTextureFormat)0); RenderTexture active = RenderTexture.active; Graphics.Blit((Texture)(object)source, temporary); RenderTexture.active = temporary; Texture2D val = new Texture2D(((Texture)source).width, ((Texture)source).height, (TextureFormat)5, false); val.ReadPixels(new Rect(0f, 0f, (float)((Texture)source).width, (float)((Texture)source).height), 0, 0); val.Apply(); RenderTexture.active = active; RenderTexture.ReleaseTemporary(temporary); return val; } private static Texture2D TintTexture(Texture2D source, Color tint) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004c: 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_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) Texture2D val = GpuBlit(source); Color[] pixels = val.GetPixels(); float num = 0.299f * tint.r + 0.587f * tint.g + 0.114f * tint.b; for (int i = 0; i < pixels.Length; i++) { Color val2 = pixels[i]; float num2 = 0.299f * val2.r + 0.587f * val2.g + 0.114f * val2.b; float num3 = ((num > 0.001f) ? (num2 / num) : 0f); pixels[i] = new Color(Mathf.Clamp01(tint.r * num3), Mathf.Clamp01(tint.g * num3), Mathf.Clamp01(tint.b * num3), val2.a); } val.SetPixels(pixels); val.Apply(); return val; } private static string StripSuffix(string name) { int num = name.IndexOf(" (Instance)"); return (num >= 0) ? name.Substring(0, num) : name; } private static string GetEquipmentHash(VisEquipment ve, Type veType) { StringBuilder stringBuilder = new StringBuilder(); string[] array = new string[6] { "m_helmetItem", "m_chestItem", "m_legItem", "m_shoulderItem", "m_utilityItem", "m_trinketItem" }; foreach (string name in array) { string value = (veType.GetField(name, Flags)?.GetValue(ve) as string) ?? ""; stringBuilder.Append(value).Append('|'); } stringBuilder.Append(((Object)ve).GetInstanceID()); return stringBuilder.ToString(); } private static ItemData FindItemInInventory(Inventory inv, string itemName) { if (inv == null) { return null; } foreach (ItemData allItem in inv.GetAllItems()) { if ((Object)(object)allItem.m_dropPrefab != (Object)null && ((Object)allItem.m_dropPrefab).name.Equals(itemName, StringComparison.OrdinalIgnoreCase)) { return allItem; } } return null; } } public class ColorPickerUI : MonoBehaviour { private struct EquippedItem { public string SlotLabel; public string ItemName; public string DisplayName; public string SlotKey; } private bool _visible = false; private Rect _windowRect = new Rect(0f, 0f, 380f, 560f); private bool _windowPositioned = false; private KeyCode _toggleKey = (KeyCode)268; private List _items = new List(); private int _selectedIndex = -1; private string _lastEquipHash = ""; private ZNetView _targetCompanion = null; private VisEquipment _targetCompanionVE = null; private string _targetCompanionName = ""; private Color _editColor = Color.white; private Color _savedColor = Color.white; private string _hexInput = "FFFFFFFF"; private bool _hexDirty = false; private GUIStyle _selectedStyle; private GUIStyle _swatchStyle; private GUIStyle _hexFieldStyle; private GUIStyle _headerStyle; private Texture2D _selectedTex; private Texture2D _swatchTex; private static readonly BindingFlags Flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private static readonly MethodInfo _updateVisualsMethod = typeof(VisEquipment).GetMethod("UpdateLodgroup", Flags); private static readonly (string label, string field)[] SlotDefs = new(string, string)[6] { ("Helmet", "m_helmetItem"), ("Chest", "m_chestItem"), ("Legs", "m_legItem"), ("Cape", "m_shoulderItem"), ("Utility", "m_utilityItem"), ("Trinket", "m_trinketItem") }; private void Update() { //IL_0003: Unknown result type (might be due to invalid IL or missing references) try { if (Input.GetKeyDown(_toggleKey)) { _visible = !_visible; if (_visible) { _windowPositioned = false; RefreshEquippedItems(); } } if (_visible) { string equipHash = GetEquipHash(); if (equipHash != _lastEquipHash) { RefreshEquippedItems(); } } } catch (Exception arg) { ArmorColorsPlugin.Log.LogError((object)$"[ColorPickerUI.Update] {arg}"); } } private void OnGUI() { //IL_00f7: 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_010e: Expected O, but got Unknown //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) if (!_visible) { return; } if (!_windowPositioned) { ((Rect)(ref _windowRect)).x = (float)Screen.width / 2f - ((Rect)(ref _windowRect)).width / 2f; ((Rect)(ref _windowRect)).y = (float)Screen.height / 2f - ((Rect)(ref _windowRect)).height / 2f; _windowPositioned = true; } try { if (_selectedStyle == null) { BuildStyles(); } string text = (((Object)(object)Player.m_localPlayer != (Object)null) ? VisEquipmentPatch.GetCharacterName(Player.m_localPlayer) : ""); string text2 = (((Object)(object)_targetCompanion != (Object)null) ? (" ⚔ Coloring: " + _targetCompanionName) : (string.IsNullOrEmpty(text) ? " ⚔ Armor Colors" : (" ⚔ " + text + "'s Armor Colors"))); _windowRect = GUI.Window(0, _windowRect, new WindowFunction(DrawWindow), text2); } catch (Exception arg) { ArmorColorsPlugin.Log.LogError((object)$"[ColorPickerUI.OnGUI] {arg}"); _visible = false; } } private void OnDestroy() { if ((Object)(object)_selectedTex != (Object)null) { Object.Destroy((Object)(object)_selectedTex); } if ((Object)(object)_swatchTex != (Object)null) { Object.Destroy((Object)(object)_swatchTex); } } private void DrawWindow(int id) { //IL_0688: Unknown result type (might be due to invalid IL or missing references) //IL_02b5: Unknown result type (might be due to invalid IL or missing references) //IL_02bb: Invalid comparison between Unknown and I4 //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: 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_02c2: Unknown result type (might be due to invalid IL or missing references) //IL_02c9: Invalid comparison between Unknown and I4 //IL_0361: Unknown result type (might be due to invalid IL or missing references) //IL_0366: Unknown result type (might be due to invalid IL or missing references) //IL_03a0: Unknown result type (might be due to invalid IL or missing references) //IL_03dc: Unknown result type (might be due to invalid IL or missing references) //IL_042d: Unknown result type (might be due to invalid IL or missing references) //IL_0469: Unknown result type (might be due to invalid IL or missing references) //IL_04c8: Unknown result type (might be due to invalid IL or missing references) //IL_04f4: Unknown result type (might be due to invalid IL or missing references) //IL_0520: Unknown result type (might be due to invalid IL or missing references) //IL_054c: Unknown result type (might be due to invalid IL or missing references) //IL_0568: Unknown result type (might be due to invalid IL or missing references) //IL_056b: Unknown result type (might be due to invalid IL or missing references) //IL_02a0: Unknown result type (might be due to invalid IL or missing references) //IL_02a2: Unknown result type (might be due to invalid IL or missing references) //IL_057d: Unknown result type (might be due to invalid IL or missing references) //IL_057f: Unknown result type (might be due to invalid IL or missing references) //IL_0586: Unknown result type (might be due to invalid IL or missing references) //IL_0303: Unknown result type (might be due to invalid IL or missing references) //IL_0305: Unknown result type (might be due to invalid IL or missing references) GUILayout.Space(6f); GUILayout.Label("EQUIPPED ITEMS", _headerStyle, Array.Empty()); GUILayout.Space(2f); if (_items.Count == 0) { GUILayout.Label(" No armor equipped.", Array.Empty()); } else { Player localPlayer = Player.m_localPlayer; string charKey = (((Object)(object)_targetCompanion != (Object)null) ? CompanionSync.GetCharKey(_targetCompanion) : (((Object)(object)localPlayer != (Object)null) ? VisEquipmentPatch.GetCharacterName(localPlayer) : "")); for (int i = 0; i < _items.Count; i++) { EquippedItem equippedItem = _items[i]; GUIStyle val = (GUIStyle)((i == _selectedIndex) ? ((object)_selectedStyle) : ((object)GUI.skin.button)); Color color = ArmorColorConfig.GetColor(charKey, equippedItem.ItemName); string text = ((color.a > 0f) ? "● " : "○ "); if (GUILayout.Button(text + "[" + equippedItem.SlotLabel + "] " + equippedItem.DisplayName, val, Array.Empty())) { SelectItem(i); } } } GUILayout.Space(10f); if (_selectedIndex >= 0 && _selectedIndex < _items.Count) { GUILayout.Label("EDITING: " + _items[_selectedIndex].DisplayName.ToUpper(), _headerStyle, Array.Empty()); GUILayout.Space(6f); GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label("HEX", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(36f) }); GUILayout.Label("#", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(12f) }); GUI.SetNextControlName("HexField"); string text2 = GUILayout.TextField(_hexInput, 8, _hexFieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) }); if (text2 != _hexInput) { _hexInput = text2.ToUpper(); _hexDirty = true; Color editColor = default(Color); if ((text2.Length == 6 || text2.Length == 8) && ColorUtility.TryParseHtmlString("#" + text2, ref editColor)) { _editColor = editColor; _hexDirty = false; } } if ((int)Event.current.type == 4 && (int)Event.current.keyCode == 13 && GUI.GetNameOfFocusedControl() == "HexField") { Color editColor2 = default(Color); if (ColorUtility.TryParseHtmlString("#" + _hexInput, ref editColor2)) { _editColor = editColor2; _hexDirty = false; } Event.current.Use(); } GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); GUILayout.Space(8f); GUILayout.Label("PREVIEW", _headerStyle, Array.Empty()); GUILayout.Space(2f); GUILayout.BeginHorizontal(Array.Empty()); Color color2 = GUI.color; GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(160f) }); GUILayout.Label("New", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(160f) }); GUI.color = _editColor; GUILayout.Box(GUIContent.none, _swatchStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(160f), GUILayout.Height(50f) }); GUI.color = color2; GUILayout.EndVertical(); GUILayout.Space(8f); GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(160f) }); GUILayout.Label("Saved", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(160f) }); GUI.color = _savedColor; GUILayout.Box(GUIContent.none, _swatchStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(160f), GUILayout.Height(50f) }); GUI.color = color2; GUILayout.EndVertical(); GUILayout.EndHorizontal(); GUILayout.Space(8f); GUILayout.Label("SLIDERS", _headerStyle, Array.Empty()); GUILayout.Space(2f); SliderRow("R", _editColor.r, new Color(1f, 0f, 0f), out var newValue); SliderRow("G", _editColor.g, new Color(0f, 1f, 0f), out var newValue2); SliderRow("B", _editColor.b, new Color(0f, 0f, 1f), out var newValue3); SliderRow("A", _editColor.a, new Color(1f, 1f, 1f), out var newValue4); Color val2 = default(Color); ((Color)(ref val2))..ctor(newValue, newValue2, newValue3, newValue4); if (val2 != _editColor) { _editColor = val2; _hexInput = ColorUtility.ToHtmlStringRGBA(_editColor); _hexDirty = false; } GUILayout.Space(10f); GUILayout.BeginHorizontal(Array.Empty()); if (GUILayout.Button("Apply", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) })) { ApplyColor(); } if (GUILayout.Button("Reset to Default", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) })) { ResetColor(); } GUILayout.EndHorizontal(); } GUILayout.FlexibleSpace(); GUILayout.Space(4f); GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label("Numpad * to toggle", GUI.skin.box, Array.Empty()); if (GUILayout.Button("Refresh", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) })) { RefreshEquippedItems(); } GUILayout.EndHorizontal(); GUI.DragWindow(new Rect(0f, 0f, 10000f, 24f)); } private void RefreshEquippedItems() { //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) _items.Clear(); _selectedIndex = -1; _targetCompanion = null; _targetCompanionVE = null; _targetCompanionName = ""; Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } float num = 5f; ZNetView[] array = Object.FindObjectsOfType(); foreach (ZNetView val in array) { if (!((Object)(object)val == (Object)null) && val.IsValid() && !(((Object)((Component)val).gameObject).name != "HC_Companion(Clone)")) { float num2 = Vector3.Distance(((Component)localPlayer).transform.position, ((Component)val).transform.position); if (num2 < num) { num = num2; _targetCompanion = val; _targetCompanionVE = ((Component)val).GetComponent(); _targetCompanionName = val.GetZDO().GetString("HC_Name", ((Object)((Component)val).gameObject).name); } } } VisEquipment obj; if ((Object)(object)_targetCompanion != (Object)null && (Object)(object)_targetCompanionVE != (Object)null) { obj = _targetCompanionVE; string charKey = CompanionSync.GetCharKey(_targetCompanion); ArmorColorsPlugin.Log.LogInfo((object)("[ColorPickerUI] Targeting companion " + _targetCompanionName)); } else { obj = ((Component)localPlayer).GetComponent(); string charKey = VisEquipmentPatch.GetCharacterName(localPlayer); if (charKey == null) { return; } } Type typeFromHandle = typeof(VisEquipment); (string, string)[] slotDefs = SlotDefs; for (int j = 0; j < slotDefs.Length; j++) { (string, string) tuple = slotDefs[j]; string item = tuple.Item1; string item2 = tuple.Item2; string text = typeFromHandle.GetField(item2, Flags)?.GetValue(obj) as string; if (!string.IsNullOrEmpty(text)) { _items.Add(new EquippedItem { SlotLabel = item, ItemName = text, DisplayName = Prettify(text), SlotKey = item2.Replace("m_", "").Replace("Item", "") }); } } ArmorColorsPlugin.Log.LogInfo((object)$"[ColorPickerUI] Found {_items.Count} equipped item(s)."); _lastEquipHash = GetEquipHash(); } private void SelectItem(int index) { //IL_005a: 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) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) _selectedIndex = index; Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { string text = (((Object)(object)_targetCompanion != (Object)null) ? CompanionSync.GetCharKey(_targetCompanion) : VisEquipmentPatch.GetCharacterName(localPlayer)); if (text != null) { _editColor = ArmorColorConfig.GetColor(text, _items[index].ItemName); _savedColor = _editColor; _hexInput = ColorUtility.ToHtmlStringRGBA(_editColor); _hexDirty = false; } } } private void ApplyColor() { //IL_0088: 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_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_013f: 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_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || _selectedIndex < 0) { return; } string itemName = _items[_selectedIndex].ItemName; string slotKey = _items[_selectedIndex].SlotKey; if ((Object)(object)_targetCompanion != (Object)null && (Object)(object)_targetCompanionVE != (Object)null) { string charKey = CompanionSync.GetCharKey(_targetCompanion); ArmorColorConfig.SetColor(charKey, itemName, _editColor); CompanionSync.SetColor(_targetCompanion, slotKey, _editColor); _updateVisualsMethod?.Invoke(_targetCompanionVE, null); ArmorColorsPlugin.Log.LogInfo((object)("[ColorPickerUI] Applied " + slotKey + " to companion " + _targetCompanionName)); } else { string characterName = VisEquipmentPatch.GetCharacterName(localPlayer); if (characterName == null) { return; } ArmorColorConfig.SetColor(characterName, itemName, _editColor); ItemData val = FindEquippedItem(localPlayer, itemName); if (val != null) { ItemColorSync.SetItemColor(val, _editColor); } ItemColorSync.BroadcastColor(localPlayer, itemName, _editColor); ApplyToNearbyStand(slotKey, _editColor); _updateVisualsMethod?.Invoke(((Component)localPlayer).GetComponent(), null); ArmorColorsPlugin.Log.LogInfo((object)("[ColorPickerUI] Saved color for " + characterName + "::" + itemName)); } _savedColor = _editColor; } private void ResetColor() { //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012e: 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) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || _selectedIndex < 0) { return; } string itemName = _items[_selectedIndex].ItemName; string slotKey = _items[_selectedIndex].SlotKey; if ((Object)(object)_targetCompanion != (Object)null && (Object)(object)_targetCompanionVE != (Object)null) { string charKey = CompanionSync.GetCharKey(_targetCompanion); ArmorColorConfig.ClearColor(charKey, itemName); CompanionSync.SetColor(_targetCompanion, slotKey, Color.clear); _updateVisualsMethod?.Invoke(_targetCompanionVE, null); } else { string characterName = VisEquipmentPatch.GetCharacterName(localPlayer); if (characterName == null) { return; } ArmorColorConfig.ClearColor(characterName, itemName); ItemData val = FindEquippedItem(localPlayer, itemName); if (val != null) { ItemColorSync.ClearItemColor(val); } ItemColorSync.BroadcastReset(localPlayer, itemName); ApplyToNearbyStand(slotKey, Color.clear); _updateVisualsMethod?.Invoke(((Component)localPlayer).GetComponent(), null); } _editColor = Color.white; _savedColor = Color.white; _hexInput = "FFFFFFFF"; } private static void ApplyToNearbyStand(string slotKey, Color color) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } ArmorStand val = null; float num = 5f; ArmorStand[] array = Object.FindObjectsOfType(); foreach (ArmorStand val2 in array) { float num2 = Vector3.Distance(((Component)localPlayer).transform.position, ((Component)val2).transform.position); if (num2 < num) { num = num2; val = val2; } } if ((Object)(object)val == (Object)null) { return; } ZNetView component = ((Component)val).GetComponent(); if ((Object)(object)component == (Object)null || !component.IsValid()) { return; } if (color.a == 0f) { ArmorStandSync.ClearStandColor(component, slotKey); } else { ArmorStandSync.SetStandColor(component, slotKey, color); } string charKey = $"stand_{component.GetZDO().m_uid}"; VisEquipment componentInChildren = ((Component)val).GetComponentInChildren(); if (!((Object)(object)componentInChildren != (Object)null)) { return; } string text = typeof(VisEquipment).GetField("m_" + slotKey + "Item", Flags)?.GetValue(componentInChildren) as string; if (!string.IsNullOrEmpty(text)) { if (color.a == 0f) { ArmorColorConfig.ClearColor(charKey, text); } else { ArmorColorConfig.SetColor(charKey, text, color); } } } private static void SliderRow(string label, float value, Color labelColor, out float newValue) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) GUILayout.BeginHorizontal(Array.Empty()); Color contentColor = GUI.contentColor; GUI.contentColor = labelColor; GUILayout.Label(label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(16f) }); GUI.contentColor = contentColor; newValue = GUILayout.HorizontalSlider(value, 0f, 1f, Array.Empty()); GUILayout.Label(Mathf.RoundToInt(newValue * 255f).ToString("D3"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(32f) }); GUILayout.EndHorizontal(); } private void BuildStyles() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Expected O, but got Unknown //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Expected O, but got Unknown //IL_0115: Unknown result type (might be due to invalid IL or missing references) _selectedTex = MakeTex(new Color(0.2f, 0.5f, 1f, 0.7f)); _selectedStyle = new GUIStyle(GUI.skin.button) { fontStyle = (FontStyle)1 }; _selectedStyle.normal.background = _selectedTex; _selectedStyle.hover.background = _selectedTex; _swatchTex = MakeTex(Color.white); GUIStyle val = new GUIStyle(GUI.skin.box); val.normal.background = _swatchTex; _swatchStyle = val; _hexFieldStyle = new GUIStyle(GUI.skin.textField) { fontSize = 14, fontStyle = (FontStyle)1, alignment = (TextAnchor)3 }; _headerStyle = new GUIStyle(GUI.skin.label) { fontStyle = (FontStyle)1, fontSize = 10 }; _headerStyle.normal.textColor = new Color(0.7f, 0.85f, 1f); } private static Texture2D MakeTex(Color col) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Expected O, but got Unknown //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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_002b: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(2, 2); val.SetPixels((Color[])(object)new Color[4] { col, col, col, col }); val.Apply(); return val; } private string GetEquipHash() { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return ""; } VisEquipment component = ((Component)localPlayer).GetComponent(); StringBuilder stringBuilder = new StringBuilder(); Type typeFromHandle = typeof(VisEquipment); (string, string)[] slotDefs = SlotDefs; for (int i = 0; i < slotDefs.Length; i++) { string item = slotDefs[i].Item2; string value = (typeFromHandle.GetField(item, Flags)?.GetValue(component) as string) ?? ""; stringBuilder.Append(value).Append('|'); } return stringBuilder.ToString(); } private static ItemData FindEquippedItem(Player player, string itemName) { foreach (ItemData allItem in ((Humanoid)player).GetInventory().GetAllItems()) { if ((Object)(object)allItem.m_dropPrefab != (Object)null && ((Object)allItem.m_dropPrefab).name.Equals(itemName, StringComparison.OrdinalIgnoreCase)) { return allItem; } } return null; } private static string Prettify(string raw) { if (string.IsNullOrEmpty(raw)) { return raw; } StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append(raw[0]); for (int i = 1; i < raw.Length; i++) { if (char.IsUpper(raw[i]) && !char.IsUpper(raw[i - 1])) { stringBuilder.Append(' '); } stringBuilder.Append(raw[i]); } return stringBuilder.ToString(); } } public static class CompanionSync { private static readonly BindingFlags BF = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private const string ZdoPrefix = "ArmorColor_"; private static readonly string[] Slots = new string[5] { "helmet", "chest", "leg", "shoulder", "utility" }; public static void SetColor(ZNetView znv, string slot, Color color) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)znv == (Object)null) && znv.IsValid()) { znv.GetZDO().Set("ArmorColor_" + slot, ColorUtility.ToHtmlStringRGBA(color)); } } public static bool TryGetColor(ZNetView znv, string slot, out Color color) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) color = Color.white; if ((Object)(object)znv == (Object)null || !znv.IsValid()) { return false; } string text = znv.GetZDO().GetString("ArmorColor_" + slot, ""); if (string.IsNullOrEmpty(text)) { return false; } return ColorUtility.TryParseHtmlString("#" + text, ref color); } public unsafe static string GetCharKey(ZNetView znv) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)znv == (Object)null || !znv.IsValid()) { return null; } ZDOID uid = znv.GetZDO().m_uid; return "companion_" + ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString(); } public static void SyncToConfig(ZNetView znv) { //IL_0089: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)znv == (Object)null || !znv.IsValid()) { return; } string charKey = GetCharKey(znv); VisEquipment component = ((Component)znv).GetComponent(); if ((Object)(object)component == (Object)null) { return; } Dictionary slotItems = GetSlotItems(component); string[] slots = Slots; foreach (string text in slots) { if (slotItems.TryGetValue(text, out var value) && !string.IsNullOrEmpty(value) && TryGetColor(znv, text, out var color)) { ArmorColorConfig.SetColor(charKey, value, color); } } } public static Dictionary GetSlotItems(VisEquipment ve) { Type typeFromHandle = typeof(VisEquipment); Dictionary dictionary = new Dictionary(); dictionary["helmet"] = (typeFromHandle.GetField("m_helmetItem", BF)?.GetValue(ve) as string) ?? ""; dictionary["chest"] = (typeFromHandle.GetField("m_chestItem", BF)?.GetValue(ve) as string) ?? ""; dictionary["leg"] = (typeFromHandle.GetField("m_legItem", BF)?.GetValue(ve) as string) ?? ""; dictionary["shoulder"] = (typeFromHandle.GetField("m_shoulderItem", BF)?.GetValue(ve) as string) ?? ""; dictionary["utility"] = (typeFromHandle.GetField("m_utilityItem", BF)?.GetValue(ve) as string) ?? ""; return dictionary; } } public static class ItemColorSync { [HarmonyPatch(typeof(Player), "Awake")] public static class PlayerAwakePatch { [HarmonyPostfix] private static void Postfix(Player __instance) { ZNetView component = ((Component)__instance).GetComponent(); if ((Object)(object)component == (Object)null) { return; } component.Register("ArmorColors_Sync", (Action)delegate(long sender, string payload) { //IL_008c: Unknown result type (might be due to invalid IL or missing references) try { if (!((Object)(object)__instance == (Object)(object)Player.m_localPlayer)) { string[] array = payload.Split(new char[1] { '|' }); if (array.Length == 2) { string itemName = array[0]; string text = array[1]; string playerName = __instance.GetPlayerName(); Color color = default(Color); if (text == "RESET") { ArmorColorConfig.ClearColor(playerName, itemName); } else if (ColorUtility.TryParseHtmlString("#" + text, ref color)) { ArmorColorConfig.SetColor(playerName, itemName, color); } VisEquipment component2 = ((Component)__instance).GetComponent(); typeof(VisEquipment).GetMethod("UpdateLodgroup", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.Invoke(component2, null); } } } catch (Exception ex) { ArmorColorsPlugin.Log.LogError((object)("[ItemColorSync] RPC error: " + ex.Message)); } }); } } private const string CustomDataKey = "ArmorColor"; private const string RpcName = "ArmorColors_Sync"; public static bool TryGetItemColor(ItemData item, out Color color) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) color = Color.white; if (item?.m_customData == null) { return false; } if (!item.m_customData.TryGetValue("ArmorColor", out var value)) { return false; } return ColorUtility.TryParseHtmlString("#" + value, ref color); } public static void SetItemColor(ItemData item, Color color) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) if (item?.m_customData != null) { item.m_customData["ArmorColor"] = ColorUtility.ToHtmlStringRGBA(color); } } public static void ClearItemColor(ItemData item) { item?.m_customData?.Remove("ArmorColor"); } public static void BroadcastColor(Player player, string itemName, Color color) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) ZNetView component = ((Component)player).GetComponent(); if (!((Object)(object)component == (Object)null) && component.IsValid()) { component.InvokeRPC(ZNetView.Everybody, "ArmorColors_Sync", new object[1] { itemName + "|" + ColorUtility.ToHtmlStringRGBA(color) }); } } public static void BroadcastReset(Player player, string itemName) { ZNetView component = ((Component)player).GetComponent(); if (!((Object)(object)component == (Object)null) && component.IsValid()) { component.InvokeRPC(ZNetView.Everybody, "ArmorColors_Sync", new object[1] { itemName + "|RESET" }); } } } public static class VisEquipmentPatch { public static string GetCharacterName(Player player) { string playerName = player.GetPlayerName(); return string.IsNullOrEmpty(playerName) ? null : playerName; } } }