Please disclose if any significant portion of your mod was created 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 Armoire v1.1.4
Advize_Armoire.dll
Decompiled a month agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using SoftReferenceableAssets; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.TextCore; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("Advize_Armoire")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Valheim Game Modification")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("8424dd46-f4b9-4fae-873e-59bc805d8112")] [assembly: AssemblyFileVersion("1.1.4.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.4.0")] [module: UnverifiableCode] [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 Advize_Armoire { [BepInPlugin("advize.Armoire", "Armoire", "1.1.4")] public sealed class Armoire : BaseUnityPlugin { public const string PluginID = "advize.Armoire"; public const string PluginName = "Armoire"; public const string Version = "1.1.4"; internal void Awake() { Runtime.MakeAllAssetsLoadable(); Logger.Sources.Add((ILogSource)(object)StaticMembers.ModLogger); StaticMembers.config = new ModConfig(((BaseUnityPlugin)this).Config); StaticMembers.assetBundle = StaticMembers.LoadAssetBundle("armoire"); StaticMembers.guiPrefab = StaticMembers.assetBundle.LoadAsset<GameObject>("ArmoireGUI"); StaticMembers.armoireSlot = StaticMembers.assetBundle.LoadAsset<GameObject>("ArmoireSlot"); StaticMembers.armoirePiecePrefab = StaticMembers.assetBundle.LoadAsset<GameObject>("ArmoirePiece"); Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "advize.Armoire"); } } public class ArmoireDoor : MonoBehaviour, Hoverable, Interactable { [Header("Transform References")] public Transform playerAttachPoint; public Transform cameraPosition; public GameObject equipmentAttachPoint; private const string AttachAnimation = "onGround"; private const float UseDistance = 2f; private static Gradient _hoverGradient; private static readonly StringBuilder _hoverText = new StringBuilder(128); private static float _lastPercentage = -1f; private static string _lastUseText = null; private static string _cachedHoverText = null; internal static List<EffectList> SoundEffects = new List<EffectList>(); private ZNetView _nview; private Animator _animator; private uint _lastDataRevision = uint.MaxValue; private static Gradient HoverGradient => _hoverGradient ?? InitializeGradient(); internal bool CanInteract { get { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) AnimatorStateInfo currentAnimatorStateInfo = _animator.GetCurrentAnimatorStateInfo(0); return ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).IsTag("openable"); } } public void Awake() { _nview = ((Component)this).GetComponent<ZNetView>(); if (Object.op_Implicit((Object)(object)_nview) && _nview.IsValid()) { _animator = ((Component)this).GetComponentInChildren<Animator>(); _nview.Register("UseArmoire", (Action<long>)RPC_UseArmoire); ((MonoBehaviour)this).InvokeRepeating("UpdateState", 0f, 5f); } } private void RPC_UseArmoire(long uid) { if (CanInteract) { int @int = _nview.GetZDO().GetInt(ZDOVars.s_state, 0); _nview.GetZDO().Set(ZDOVars.s_state, 1 - @int, false); UpdateState(); } } private void UpdateState() { if (_nview.IsValid()) { ZDO zdo = _nview.m_zdo; if (zdo != null && zdo.DataRevision != _lastDataRevision) { _lastDataRevision = zdo.DataRevision; SetState(zdo.GetInt(ZDOVars.s_state, 0)); } } } private void SetState(int state) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) if (_animator.GetInteger("state") != state) { SoundEffects[state].Create(((Component)this).transform.position, ((Component)this).transform.rotation, (Transform)null, 1f, -1); _animator.SetInteger("state", state); } } public void ResetState() { //IL_002a: Unknown result type (might be due to invalid IL or missing references) _nview.InvokeRPC("UseArmoire", Array.Empty<object>()); playerAttachPoint.localRotation = Quaternion.Euler(0f, 0f, 0f); } public string GetHoverText() { //IL_0060: Unknown result type (might be due to invalid IL or missing references) if (ArmoireUIController.IsArmoirePanelActive()) { return string.Empty; } float num = Mathf.Clamp01((float)AppearanceTracker.UnlockedPercentage); bool num2 = !Mathf.Approximately(num, _lastPercentage); string text = Localization.instance.Localize("[<color=yellow><b>$KEY_Use</b></color>] $piece_use"); bool flag = text != _lastUseText; if (!num2 && !flag) { return _cachedHoverText; } _lastPercentage = num; _lastUseText = text; string value = ColorUtility.ToHtmlStringRGB(HoverGradient.Evaluate(num)); _hoverText.Clear(); _hoverText.Append(GetHoverName()).Append('\n'); _hoverText.Append("Collected: <color=#").Append(value).Append('>') .Append(AppearanceTracker.TotalUnlocked) .Append('/') .Append(AppearanceTracker.TotalCollectable) .Append("</color>\n"); _hoverText.Append(text); _cachedHoverText = _hoverText.ToString(); return _cachedHoverText; } public string GetHoverName() { return "Armoire"; } public bool Interact(Humanoid character, bool hold, bool alt) { //IL_003d: 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) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: 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_00c4: Unknown result type (might be due to invalid IL or missing references) StaticMembers.Dbgl("Interacted with armoire", forceLog: false, (LogLevel)16); if (hold || !CanInteract) { return false; } Player val = (Player)(object)((character is Player) ? character : null); if (val == null || !InUsingDistance((Humanoid)(object)val) || ((Character)val).IsEncumbered()) { return false; } Player closestPlayer = Player.GetClosestPlayer(playerAttachPoint.position, 0.1f); if (Object.op_Implicit((Object)(object)closestPlayer) && (Object)(object)closestPlayer != (Object)(object)Player.m_localPlayer) { ((Character)Player.m_localPlayer).Message((MessageType)2, "$msg_blocked", 0, (Sprite)null); return false; } if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false)) { return true; } AnimatorStateInfo currentAnimatorStateInfo = _animator.GetCurrentAnimatorStateInfo(0); if (!((AnimatorStateInfo)(ref currentAnimatorStateInfo)).IsName("opened")) { ((Character)val).AttachStart(playerAttachPoint, (GameObject)null, false, false, false, "onGround", default(Vector3), cameraPosition); ArmoireUIController.ToggleArmoirePanel(this); equipmentAttachPoint.SetActive(true); _nview.ClaimOwnership(); } _nview.InvokeRPC("UseArmoire", Array.Empty<object>()); return true; } public bool UseItem(Humanoid user, ItemData item) { return false; } private static Gradient InitializeGradient() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Expected O, but got Unknown //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_003c: 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_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: 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_0072: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) _hoverGradient = new Gradient(); _hoverGradient.SetKeys((GradientColorKey[])(object)new GradientColorKey[5] { new GradientColorKey(Color.red, 0f), new GradientColorKey(new Color(1f, 0.6470588f, 0f), 0.3f), new GradientColorKey(Color.yellow, 0.6f), new GradientColorKey(Color.green, 0.9f), new GradientColorKey(Color.cyan, 1f) }, Array.Empty<GradientAlphaKey>()); return _hoverGradient; } private bool InUsingDistance(Humanoid human) { //IL_0006: 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) return Vector3.Distance(((Component)human).transform.position, playerAttachPoint.position) < 2f; } } [HarmonyPatch] internal static class VersionHandshake { private static readonly List<ZRpc> ValidatedPeers = new List<ZRpc>(); private static string ConnectionError = string.Empty; private static bool ClientVersionValidated = false; private static void RPC_ArmoireVersionCheck(ZRpc rpc, ZPackage pkg) { string text = pkg.ReadString(); bool flag = ZNet.instance.IsServer(); StaticMembers.Dbgl("Version check, local: 1.1.4, remote: " + text, forceLog: false, (LogLevel)16); if (text != "1.1.4") { ConnectionError = "Armoire Installed: 1.1.4\n Needed: " + text; if (flag) { StaticMembers.Dbgl("Peer (" + rpc.m_socket.GetHostName() + ") has incompatible version, disconnecting...", forceLog: true, (LogLevel)4); rpc.Invoke("Error", new object[1] { 3 }); } } else if (flag) { StaticMembers.Dbgl("Adding peer (" + rpc.m_socket.GetHostName() + ") to validated list", forceLog: false, (LogLevel)16); ValidatedPeers.Add(rpc); } else { StaticMembers.Dbgl("Received same version from server!", forceLog: false, (LogLevel)16); ClientVersionValidated = true; } } [HarmonyPatch(typeof(ZNet), "OnNewConnection")] [HarmonyPrefix] private static void InitiateVersionHandshake(ZNetPeer peer) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown string text = "ArmoireVersionCheck"; StaticMembers.Dbgl("Registering version RPC handler", forceLog: false, (LogLevel)16); peer.m_rpc.Register<ZPackage>(text, (Action<ZRpc, ZPackage>)RPC_ArmoireVersionCheck); StaticMembers.Dbgl("Invoking version check", forceLog: false, (LogLevel)16); ZPackage val = new ZPackage(); val.Write("1.1.4"); peer.m_rpc.Invoke(text, new object[1] { val }); } [HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")] [HarmonyPrefix] private static bool EnforceValidationStatus(ZRpc rpc, ref ZNet __instance) { //IL_0084: Unknown result type (might be due to invalid IL or missing references) bool flag = __instance.IsServer(); if (ValidatedPeers.Contains(rpc) || (!flag && ClientVersionValidated)) { return true; } ConnectionError = "No <color=\"red\">Armoire</color> version received"; if (flag) { StaticMembers.Dbgl("Peer (" + rpc.m_socket.GetHostName() + ") never sent version or couldn't due to previous disconnect, disconnecting", forceLog: true, (LogLevel)4); rpc.Invoke("Error", new object[1] { 3 }); } else { StaticMembers.Dbgl("No version number received, mod may not be installed on server", forceLog: true, (LogLevel)4); Game.instance.Logout(true, true); ZNet.m_connectionStatus = (ConnectionStatus)3; } return false; } [HarmonyPatch(typeof(ZNet), "Disconnect")] [HarmonyPrefix] private static void InvalidateDisconnectingPeer(ZNetPeer peer, ref ZNet __instance) { if (__instance.IsServer()) { StaticMembers.Dbgl("Peer (" + peer.m_rpc.m_socket.GetHostName() + ") disconnected, removing from validated list", forceLog: false, (LogLevel)16); ValidatedPeers.Remove(peer.m_rpc); } else { ClientVersionValidated = false; } } [HarmonyPatch(typeof(FejdStartup), "ShowConnectError")] [HarmonyPostfix] private static void ShowConnectionError(FejdStartup __instance) { if (__instance.m_connectionFailedPanel.activeSelf) { TMP_Text connectionFailedError = __instance.m_connectionFailedError; connectionFailedError.text = connectionFailedError.text + "\n" + ConnectionError; } } } public class ArmoireInputMonitor : MonoBehaviour { private Button button; private Toggle toggle; public GameObject hint; public string zInputKey; public KeyCode keyCode; public void Start() { button = ((Component)this).GetComponent<Button>(); toggle = ((Component)this).GetComponent<Toggle>(); GameObject obj = hint; if (obj != null) { obj.SetActive(false); } } public void Update() { GameObject obj = hint; if (obj != null) { obj.SetActive(IsInteractive()); } if (ButtonPressed()) { if (Object.op_Implicit((Object)(object)button)) { ((Selectable)button).Select(); button.OnSubmit((BaseEventData)null); } if (Object.op_Implicit((Object)(object)toggle)) { ((Selectable)toggle).Select(); toggle.OnSubmit((BaseEventData)null); } } } private bool ButtonPressed() { //IL_0025: 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) if (IsBlocked()) { return false; } if (string.IsNullOrEmpty(zInputKey) || !ZInput.GetButtonDown(zInputKey)) { if ((int)keyCode != 0) { return ZInput.GetKeyDown(keyCode, false); } return false; } return true; } private bool IsBlocked() { if (Object.op_Implicit((Object)(object)Console.instance)) { return Console.IsVisible(); } return false; } private bool IsInteractive() { if (!Object.op_Implicit((Object)(object)button) || ((Selectable)button).interactable) { if (Object.op_Implicit((Object)(object)toggle)) { return ((Selectable)toggle).interactable; } return true; } return false; } } public class ArmoireInputHandler : MonoBehaviour, IPointerClickHandler, IEventSystemHandler, ISelectHandler, IDeselectHandler { public UnityEvent onRightClick; public UnityEvent<bool> onSelectChange; public void OnPointerClick(PointerEventData eventData) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)eventData.button == 1) { UnityEvent obj = onRightClick; if (obj != null) { obj.Invoke(); } } } public void OnSelect(BaseEventData eventData) { onSelectChange?.Invoke(true); } public void OnDeselect(BaseEventData eventData) { onSelectChange?.Invoke(false); } public void RemoveAllListeners() { ((UnityEventBase)((Component)this).GetComponent<Button>().onClick).RemoveAllListeners(); ((UnityEventBase)onRightClick).RemoveAllListeners(); ((UnityEventBase)onSelectChange).RemoveAllListeners(); } } public class ArmoireUI : MonoBehaviour { [CompilerGenerated] private sealed class <DeferredSetCurrentSelected>d__51 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public ArmoireUI <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DeferredSetCurrentSelected>d__51(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { int num = <>1__state; ArmoireUI armoireUI = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; ((Selectable)armoireUI.currentAppearanceButton).Select(); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <LerpScrollView>d__46 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public ArmoireUI <>4__this; public float duration; public float target; private float <start>5__2; private float <time>5__3; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <LerpScrollView>d__46(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { int num = <>1__state; ArmoireUI armoireUI = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; <start>5__2 = armoireUI.scrollRect.verticalNormalizedPosition; <time>5__3 = 0f; break; case 1: <>1__state = -1; break; } if (<time>5__3 < duration) { <time>5__3 += Time.deltaTime; float num2 = <time>5__3 / duration; armoireUI.scrollRect.verticalNormalizedPosition = Mathf.Lerp(<start>5__2, target, Mathf.SmoothStep(0f, 1f, num2)); <>2__current = null; <>1__state = 1; return true; } armoireUI.scrollRect.verticalNormalizedPosition = target; return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private const int OutfitSlotCount = 3; [Header("GameObject References")] public GameObject slotsPanel; public GameObject scrollView; public GameObject outfitsPanel; public GameObject scrollViewContent; public GameObject outfitNumBG; [Header("Button References")] public List<Button> slotButtons; public Button currentAppearanceButton; public Button hideSlotButton; public Toggle toggleHidden; public Button outfitsButton; public Button cancelButton; public List<Button> cycleOutfitButtons; public Button saveOutfitButton; public Button loadOutfitButton; public Button deleteOutfitButton; [Header("Image References")] public Image panelBorder; public Image verticalScrollbar; public List<Image> panelBackgrounds; public List<Image> childIcons; public List<Image> hintKeyBKG; [Header("Misc References")] public ScrollRect scrollRect; public UITooltip currentAppearanceButtonTooltip; [Header("Runtime State")] private readonly List<GameObject> generatedScrollViewButtons = new List<GameObject>(); private TextMeshProUGUI _acquiredAppearanceText; private Button _currentlySelectedButton; private AppearanceSlotType _lastSlotTypeSelected; private int _currentOutfitIndex; private Coroutine scrollLerpRoutine; public void LateUpdate() { KeyHints.instance.m_barberHints.SetActive(true); KeyHints.instance.m_combatHints.SetActive(false); if (ArmoireUIController.HandleEscapeOrCancelInput()) { return; } if (ZInput.GamepadActive && ZInput.GetButtonDown("JoyButtonX") && Object.op_Implicit((Object)(object)_currentlySelectedButton) && !scrollView.activeSelf) { AppearanceSlotButtonRightClicked(slotButtons.FindIndex((Button x) => (Object)(object)x == (Object)(object)_currentlySelectedButton)); } if (ZInput.GetKey((KeyCode)324, false) || ZInput.IsGamepadActive()) { ControlAttachedPlayer(); } } public void OnEnable() { StaticMembers.Dbgl("Enabled", forceLog: false, (LogLevel)16); _currentlySelectedButton = null; ((Selectable)cancelButton).Select(); } private void AppearanceSlotButtonClicked(int slotIndex) { BuildScrollableGrid((AppearanceSlotType)slotIndex); ShowScrollView(); } private void AppearanceSlotButtonRightClicked(int slotIndex) { UpdateAppearanceSlot((AppearanceSlotType)slotIndex, string.Empty, 0, hidden: false); } private void UpdateAppearanceSlotButtonSelection(bool isSelected, int slotIndex) { _currentlySelectedButton = (isSelected ? slotButtons[slotIndex] : null); } private void HideSlotButtonClick() { UpdateAppearanceSlot(_lastSlotTypeSelected, string.Empty, 0, hidden: true); HideScrollView(); } private void UnlockedAppearanceOnClick(int buttonIndex, int variant) { UpdateAppearanceSlot(_lastSlotTypeSelected, ((Object)generatedScrollViewButtons[buttonIndex]).name, variant, hidden: false); HideScrollView(); } private void ToggleHiddenClicked(bool showAllAppearances) { StaticMembers.config.ShowAllAppearances = showAllAppearances; RebuildScrollableGrid(); } private void CycleOutfitButtonClicked(int direction) { _currentOutfitIndex = (_currentOutfitIndex + direction + 3) % 3; UpdateOutfitLabel(); UpdateOutfitState(); UpdateOutfitIcons(); } private void UpdateOutfitLabel() { ((TMP_Text)((Component)outfitNumBG.transform.GetChild(0)).GetComponent<TextMeshProUGUI>()).text = $"Outfit {_currentOutfitIndex + 1}"; } private void UpdateOutfitState() { //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown if (Player.m_localPlayer.m_customData.TryGetValue(GetOutfitKey(), out var value)) { StaticMembers.Dbgl($"Data in outfit slot {_currentOutfitIndex + 1}", forceLog: false, (LogLevel)16); UpdateOutfitButtonStates(enabled: true, new Color32(byte.MaxValue, (byte)161, (byte)60, byte.MaxValue)); AppearanceData.LoadAppearanceData(new ZPackage(value), StaticMembers.OutfitOverrides[_currentOutfitIndex]); } else { StaticMembers.Dbgl($"No data in outfit slot {_currentOutfitIndex + 1}", forceLog: false, (LogLevel)16); UpdateOutfitButtonStates(enabled: false, new Color32((byte)128, (byte)128, (byte)128, byte.MaxValue)); } } private void UpdateOutfitIcons() { UpdateItemSlotIcons(StaticMembers.OutfitOverrides[_currentOutfitIndex]); } private void CancelButtonClicked() { if (scrollView.activeSelf) { HideScrollView(); } else if (outfitsPanel.activeSelf) { HideOutfitsPanel(); } else { ArmoireUIController.cancelButtonWasClicked = true; } } private void SaveOutfitButtonClicked() { AppearanceData.SaveAppearanceData(GetOutfitKey()); UpdateOutfitState(); UpdateItemSlotIcons(StaticMembers.ActiveOverrides); } private void LoadOutfitButtonClicked() { StaticMembers.ActiveOverrides = PluginUtils.CloneOverrides(StaticMembers.OutfitOverrides[_currentOutfitIndex]); ((Humanoid)Player.m_localPlayer).SetupEquipment(); } private void DeleteOutfitButtonClicked() { StaticMembers.OutfitOverrides[_currentOutfitIndex].Values.ToList().ForEach(delegate(AppearanceSlot slot) { slot.ResetSlot(); }); Player.m_localPlayer.m_customData.Remove(GetOutfitKey()); UpdateItemSlotIcons(StaticMembers.OutfitOverrides[_currentOutfitIndex]); } private void UpdateScrollViewButtonSelection(bool selected, GameObject go) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: 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) ((Component)go.transform.Find("selected")).gameObject.SetActive(selected); if (selected && !ZInput.GetMouseButton(0)) { RectTransform component = go.GetComponent<RectTransform>(); Rect rect = scrollRect.content.rect; float height = ((Rect)(ref rect)).height; rect = scrollRect.viewport.rect; float height2 = ((Rect)(ref rect)).height; float num = Mathf.Clamp01((0f - component.anchoredPosition.y - height2 / 2f) / (height - height2)); float target = 1f - num; if (scrollLerpRoutine != null) { ((MonoBehaviour)this).StopCoroutine(scrollLerpRoutine); } scrollLerpRoutine = ((MonoBehaviour)this).StartCoroutine(LerpScrollView(target)); } } [IteratorStateMachine(typeof(<LerpScrollView>d__46))] private IEnumerator LerpScrollView(float target, float duration = 0.15f) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <LerpScrollView>d__46(0) { <>4__this = this, target = target, duration = duration }; } internal void UpdateAppearanceSlot(AppearanceSlotType itemCategory, string itemName, int itemVariant, bool hidden) { StaticMembers.Dbgl("UpdateAppearanceSlot", forceLog: false, (LogLevel)16); AppearanceSlot appearanceSlot = StaticMembers.ActiveOverrides[itemCategory]; appearanceSlot.ItemName = itemName; appearanceSlot.ItemVariant = itemVariant; appearanceSlot.Hidden = hidden; UpdateItemIcon(itemCategory, StaticMembers.ActiveOverrides); ((Humanoid)Player.m_localPlayer).SetupEquipment(); AppearanceData.SaveAppearanceData("Armoire_Appearances"); } public void UpdateItemSlotIcons(Dictionary<AppearanceSlotType, AppearanceSlot> overrides) { Array.ForEach(StaticMembers.ActiveOverrides.Keys.ToArray(), delegate(AppearanceSlotType itemCategory) { UpdateItemIcon(itemCategory, overrides); }); } public void UpdateItemIcon(AppearanceSlotType itemCategory, Dictionary<AppearanceSlotType, AppearanceSlot> overrides) { AppearanceSlot appearanceSlot = overrides[itemCategory]; string itemName = appearanceSlot.ItemName; int itemVariant = appearanceSlot.ItemVariant; bool hidden = appearanceSlot.Hidden; Sprite val = (hidden ? UIResources.GetSprite("mapicon_hildir") : (string.IsNullOrEmpty(itemName) ? null : UIResources.GetItemIcon(itemName, itemVariant))); Transform child = ((Component)slotButtons[(int)itemCategory]).transform.GetChild(0); GameObject obj = ((child.childCount > 0) ? ((Component)child.GetChild(0)).gameObject : null); ((Component)child).GetComponent<Image>().sprite = val; ((Component)child).gameObject.SetActive(Object.op_Implicit((Object)(object)val) || hidden); string topic = ((!Object.op_Implicit((Object)(object)val)) ? "" : (hidden ? "Slot Hidden" : ZNetScene.instance.GetPrefab(itemName).GetComponent<ItemDrop>().m_itemData.m_shared.m_name)); ((Component)slotButtons[(int)itemCategory]).GetComponent<UITooltip>().m_topic = topic; if (obj != null) { obj.SetActive(hidden); } } private void ShowScrollView() { ToggleScrollView(); ((MonoBehaviour)this).StartCoroutine(DeferredSetCurrentSelected()); } [IteratorStateMachine(typeof(<DeferredSetCurrentSelected>d__51))] private IEnumerator DeferredSetCurrentSelected() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DeferredSetCurrentSelected>d__51(0) { <>4__this = this }; } private void HideScrollView() { ToggleScrollView(); ((Selectable)slotButtons[(int)_lastSlotTypeSelected]).Select(); DestroyScrollableGrid(); } private void ToggleScrollView() { bool flag = !scrollView.activeSelf; scrollView.SetActive(flag); slotsPanel.SetActive(!flag); ToggleExtraneousButtons(); } private void ShowOutfitsPanel() { ToggleOutfitsPanel(); ((Selectable)cancelButton).Select(); } private void HideOutfitsPanel() { ToggleOutfitsPanel(); UpdateItemSlotIcons(StaticMembers.ActiveOverrides); ((Selectable)outfitsButton).Select(); } private void ToggleOutfitsPanel() { bool flag = !outfitsPanel.activeSelf; outfitsPanel.SetActive(flag); Image obj = panelBackgrounds[1]; ((Behaviour)obj).enabled = !flag; ((Component)((Component)obj).transform.GetChild(0)).gameObject.SetActive(!flag); foreach (Button slotButton in slotButtons) { ((Selectable)slotButton).interactable = !((Selectable)slotButton).interactable; ((Component)((Component)slotButton).transform.Find("LabelBG")).gameObject.SetActive(!flag); } if (flag) { UpdateOutfitState(); UpdateOutfitIcons(); } ToggleExtraneousButtons(); } private string GetOutfitKey() { return $"Armoire_Outfit{_currentOutfitIndex + 1}"; } private void UpdateOutfitButtonStates(bool enabled, Color32 color) { //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) ((Selectable)loadOutfitButton).interactable = enabled; ((Graphic)((Component)((Component)loadOutfitButton).transform.GetChild(0)).GetComponent<Image>()).color = Color32.op_Implicit(color); ((Selectable)deleteOutfitButton).interactable = enabled; } internal void ToggleExtraneousButtons(bool forceReset = false) { ((Selectable)outfitsButton).interactable = forceReset || !((Selectable)outfitsButton).interactable; for (int i = 0; i < 2; i++) { bool active = (forceReset ? (i == 0) : (!((Component)((Component)cancelButton).transform.GetChild(i)).gameObject.activeSelf)); ((Component)((Component)cancelButton).transform.GetChild(i)).gameObject.SetActive(active); } } private void BuildScrollableGrid(AppearanceSlotType slotType) { //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Expected O, but got Unknown _lastSlotTypeSelected = slotType; AppearanceSlot appearanceSlot = StaticMembers.ActiveOverrides[slotType]; string itemName = appearanceSlot.ItemName; int itemVariant = appearanceSlot.ItemVariant; ((Component)hideSlotButton).gameObject.SetActive(appearanceSlot.CanBeHidden); Transform child = ((Component)currentAppearanceButton).transform.GetChild(0); Sprite val = (string.IsNullOrEmpty(itemName) ? null : UIResources.GetItemIcon(itemName, itemVariant)); currentAppearanceButtonTooltip.m_topic = (Object.op_Implicit((Object)(object)val) ? ZNetScene.instance.GetPrefab(itemName).GetComponent<ItemDrop>().m_itemData.m_shared.m_name : "No Override Selected"); ((Component)child).gameObject.SetActive(Object.op_Implicit((Object)(object)val)); if (Object.op_Implicit((Object)(object)val)) { ((Component)child).GetComponent<Image>().sprite = val; } int num = 0; foreach (KeyValuePair<ItemDrop, int> item in StaticMembers.UnlockedAppearances[slotType]) { for (int i = 0; i < item.Value; i++) { GameObject armoireSlotButton2 = CreateArmoireSlot(((Object)item.Key).name, i); int closureIndex = num; int closureIndex2 = i; ((UnityEvent)armoireSlotButton2.GetComponent<Button>().onClick).AddListener((UnityAction)delegate { UnlockedAppearanceOnClick(closureIndex, closureIndex2); }); armoireSlotButton2.GetComponent<ArmoireInputHandler>().onSelectChange.AddListener((UnityAction<bool>)delegate(bool isSelected) { UpdateScrollViewButtonSelection(isSelected, armoireSlotButton2); }); generatedScrollViewButtons.Add(armoireSlotButton2); num++; } } if (StaticMembers.config.ShowAllAppearances) { foreach (KeyValuePair<ItemDrop, int> item2 in StaticMembers.GetLockedAppearances()[slotType]) { for (int j = 0; j < item2.Value; j++) { GameObject armoireSlotButton = CreateArmoireSlot(((Object)item2.Key).name, j, locked: true); armoireSlotButton.GetComponent<ArmoireInputHandler>().onSelectChange.AddListener((UnityAction<bool>)delegate(bool isSelected) { UpdateScrollViewButtonSelection(isSelected, armoireSlotButton); }); generatedScrollViewButtons.Add(armoireSlotButton); } } } for (int k = 0; k < generatedScrollViewButtons.Count; k++) { if (!(((Object)generatedScrollViewButtons[k]).name != itemName)) { generatedScrollViewButtons[k + itemVariant].SetActive(false); break; } } ((TMP_Text)_acquiredAppearanceText).text = $"{AppearanceTracker.Unlocked(slotType)} / {AppearanceTracker.Total(slotType)}"; } internal void DestroyScrollableGrid() { StaticMembers.Dbgl("Destroying scrollable grid (buttons and listeners)", forceLog: false, (LogLevel)16); foreach (GameObject generatedScrollViewButton in generatedScrollViewButtons) { generatedScrollViewButton.GetComponent<ArmoireInputHandler>().RemoveAllListeners(); Object.Destroy((Object)(object)generatedScrollViewButton); } generatedScrollViewButtons.Clear(); } internal void RebuildScrollableGrid() { DestroyScrollableGrid(); BuildScrollableGrid(_lastSlotTypeSelected); } private GameObject CreateArmoireSlot(string prefabName, int variant, bool locked = false) { //IL_00c1: 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) Sprite itemIcon = UIResources.GetItemIcon(prefabName, variant); GameObject obj = Object.Instantiate<GameObject>(StaticMembers.armoireSlot, scrollViewContent.transform); ((Object)obj).name = prefabName; UITooltip component = obj.GetComponent<UITooltip>(); component.m_topic = (locked ? "???" : ZNetScene.instance.GetPrefab(prefabName).GetComponent<ItemDrop>().m_itemData.m_shared.m_name); component.m_text = ((!locked || StaticMembers.config.ShowUndiscoveredHoverDetails) ? ("</i><size=90%>" + prefabName + ((variant > 0) ? $"\nVariant: {variant}" : "") + "<i>") : ""); Image component2 = ((Component)obj.transform.GetChild(0)).GetComponent<Image>(); component2.sprite = itemIcon; ((Graphic)component2).color = (locked ? Color.black : Color.white); obj.SetActive(true); return obj; } private void ControlAttachedPlayer() { //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: 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_0017: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: 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_0112: Unknown result type (might be due to invalid IL or missing references) //IL_011e: 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_003c: 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_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: 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_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0088: 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_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) if (Hud.InRadial()) { return; } Vector2 val; if (ZInput.IsGamepadActive()) { val = Vector2.zero; if (!ZInput.GetButton("JoyRotate")) { float joyRightStickX = ZInput.GetJoyRightStickX(true); float joyRightStickY = ZInput.GetJoyRightStickY(true); Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(joyRightStickX, 0f - joyRightStickY); if (PlayerController.cameraDirectionLock != Vector2.zero && val2 != PlayerController.cameraDirectionLock) { PlayerController.cameraDirectionLock = Vector2.zero; } if (PlayerController.cameraDirectionLock == Vector2.zero) { float num = 110f * Time.deltaTime * PlayerController.m_gamepadSens; val = val2 * num; } } if (PlayerController.m_invertCameraX) { val.x *= -1f; } if (PlayerController.m_invertCameraY) { val.y *= -1f; } } else { val = ZInput.GetMouseDelta() * PlayerController.m_mouseSens * 2f; if (PlayerController.m_invertMouse) { val.y *= -1f; } } Player.m_localPlayer.SetMouseLook(val); Transform attachPoint = Player.m_localPlayer.GetAttachPoint(); attachPoint.localRotation *= Quaternion.Euler(0f, 0f - val.x, 0f); } internal void Initialize() { SetupPanelPosition(); SetupTooltipFonts(); SetupLabelFonts(); SetupPanelSprites(); SetupSlotButtonSprites(); SetupCycleOutfitButtonSprites(); SetupOutfitButtonSprites(); SetupMiscIcons(); SetupScrollViewSprites(); SetupToggleHidden(); SetupExtraneousButtonSprites(); SetupSpriteStates(); SetupButtonListeners(); } private void SetupPanelPosition() { StaticMembers.config.UpdateUIPanelPosition(null, null); } private void SetupTooltipFonts() { Transform child = ((Component)this).GetComponentsInChildren<UITooltip>().First().m_tooltipPrefab.transform.GetChild(0); string[] array = new string[2] { "Topic", "Text" }; foreach (string text in array) { TextMeshProUGUI component = ((Component)child.Find(text)).GetComponent<TextMeshProUGUI>(); ((TMP_Text)component).font = UIResources.GetFontAsset("Valheim-AveriaSerifLibre"); ((TMP_Text)component).fontMaterial = UIResources.GetMaterial("Valheim-AveriaSerifLibre - Outline"); } } private void SetupLabelFonts() { TextMeshProUGUI[] componentsInChildren = ((Component)this).GetComponentsInChildren<TextMeshProUGUI>(true); foreach (TextMeshProUGUI obj in componentsInChildren) { ((TMP_Text)obj).font = UIResources.GetFontAsset("Valheim-AveriaSerifLibre"); ((TMP_Text)obj).fontMaterial = UIResources.GetMaterial("Valheim-AveriaSerifLibre - Outline"); ((TMP_Text)obj).fontStyle = (FontStyles)0; ((TMP_Text)obj).fontWeight = (FontWeight)400; ((TMP_Text)obj).fontFeatures = new List<OTL_FeatureTag>(1) { (OTL_FeatureTag)1801810542 }; } } private void SetupPanelSprites() { panelBorder.sprite = UIResources.GetSprite("panel_interior_bkg_128"); panelBackgrounds.ForEach(delegate(Image bg) { bg.sprite = UIResources.GetSprite("panel_bkg_128"); }); } private void SetupSlotButtonSprites() { foreach (Button slotButton in slotButtons) { ((Component)slotButton).GetComponent<Image>().sprite = UIResources.GetSprite("panel_bkg"); ((Component)((Component)slotButton).transform.Find("LabelBG")).GetComponent<Image>().sprite = UIResources.GetSprite("button_disabled"); } } private void SetupCycleOutfitButtonSprites() { foreach (Button cycleOutfitButton in cycleOutfitButtons) { ((Component)cycleOutfitButton).GetComponent<Image>().sprite = UIResources.GetSprite("button"); } outfitNumBG.GetComponent<Image>().sprite = UIResources.GetSprite("button_disabled"); } private void SetupOutfitButtonSprites() { SetupOutfitButton(saveOutfitButton, "file_local"); SetupOutfitButton(loadOutfitButton, "winddirection"); SetupOutfitButton(deleteOutfitButton, "mapicon_checked"); } private void SetupOutfitButton(Button button, string iconSprite) { ((Component)button).GetComponent<Image>().sprite = UIResources.GetSprite("button"); ((Component)((Component)button).transform.GetChild(0)).GetComponent<Image>().sprite = UIResources.GetSprite(iconSprite); ((Component)((Component)button).transform.GetChild(1)).GetComponent<Image>().sprite = UIResources.GetSprite("button_disabled"); } private void SetupMiscIcons() { childIcons.ForEach(delegate(Image i) { i.sprite = UIResources.GetSprite("mapicon_checked"); }); hintKeyBKG.ForEach(delegate(Image i) { i.sprite = UIResources.GetSprite("key_base"); }); } private void SetupScrollViewSprites() { SetupScrollButton(currentAppearanceButton, "item_background_sunken", "selection_frame"); SetupScrollButton(hideSlotButton, "item_background_sunken", "selection_frame", "mapicon_hildir", "mapicon_checked"); verticalScrollbar.sprite = UIResources.GetSprite("panel_interior_bkg_128"); ((Component)((Component)verticalScrollbar).transform.GetChild(0).GetChild(0)).GetComponent<Image>().sprite = UIResources.GetSprite("crafting_panel_bkg"); StaticMembers.armoireSlot.GetComponent<Image>().sprite = UIResources.GetSprite("item_background_sunken"); ((Component)StaticMembers.armoireSlot.transform.GetChild(1)).GetComponent<Image>().sprite = UIResources.GetSprite("selection_frame"); } private void SetupScrollButton(Button button, string bgSprite, string frameSprite, string iconSprite = null, string iconChildSprite = null) { ((Component)button).GetComponent<Image>().sprite = UIResources.GetSprite(bgSprite); ((Component)((Component)button).transform.GetChild(1)).GetComponent<Image>().sprite = UIResources.GetSprite(frameSprite); if (iconSprite != null) { Transform child = ((Component)button).transform.GetChild(0); ((Component)child).GetComponent<Image>().sprite = UIResources.GetSprite(iconSprite); if (iconChildSprite != null) { ((Component)child.GetChild(0)).GetComponent<Image>().sprite = UIResources.GetSprite(iconChildSprite); } } } private void SetupToggleHidden() { Transform child = ((Component)toggleHidden).transform.GetChild(2); ((Component)child).GetComponent<Image>().sprite = UIResources.GetSprite("button_small"); ((Component)child.GetChild(0)).GetComponent<Image>().sprite = UIResources.GetSprite("checkbox_marker_filtered"); toggleHidden.isOn = StaticMembers.config.ShowAllAppearances; _acquiredAppearanceText = ((Component)((Component)toggleHidden).transform.GetChild(0)).GetComponent<TextMeshProUGUI>(); } private void SetupExtraneousButtonSprites() { ((Component)outfitsButton).GetComponent<Image>().sprite = UIResources.GetSprite("button"); ((Component)cancelButton).GetComponent<Image>().sprite = UIResources.GetSprite("button"); } private void SetupSpriteStates() { //IL_0002: 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_004d: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) SpriteState val = default(SpriteState); ((SpriteState)(ref val)).highlightedSprite = UIResources.GetSprite("button_highlight"); ((SpriteState)(ref val)).pressedSprite = UIResources.GetSprite("button_pressed"); ((SpriteState)(ref val)).selectedSprite = UIResources.GetSprite("button_highlight"); ((SpriteState)(ref val)).disabledSprite = UIResources.GetSprite("button_disabled"); SpriteState spriteState = val; List<Button> list = cycleOutfitButtons; List<Button> list2 = new List<Button>(5 + list.Count); list2.AddRange(list); list2.Add(outfitsButton); list2.Add(cancelButton); list2.Add(saveOutfitButton); list2.Add(loadOutfitButton); list2.Add(deleteOutfitButton); foreach (Button item in list2) { ((Selectable)item).spriteState = spriteState; } } internal void SetupButtonListeners() { SetupSlotPanelButtonListeners(); SetupScrollViewButtonListeners(); SetupToggleHiddenListener(); SetupExtraneousButtonListeners(); SetupOutfitPanelButtonListeners(); } private void SetupSlotPanelButtonListeners() { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown for (int i = 0; i < slotButtons.Count; i++) { int index = i; Button obj = slotButtons[i]; ((UnityEvent)obj.onClick).AddListener((UnityAction)delegate { AppearanceSlotButtonClicked(index); }); ArmoireInputHandler component = ((Component)obj).GetComponent<ArmoireInputHandler>(); component.onRightClick.AddListener((UnityAction)delegate { AppearanceSlotButtonRightClicked(index); }); component.onSelectChange.AddListener((UnityAction<bool>)delegate(bool isSelected) { UpdateAppearanceSlotButtonSelection(isSelected, index); }); } } private void SetupScrollViewButtonListeners() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown SetupScrollViewButton(currentAppearanceButton, new UnityAction(HideScrollView)); SetupScrollViewButton(hideSlotButton, new UnityAction(HideSlotButtonClick)); } private void SetupScrollViewButton(Button button, UnityAction clickAction) { ((UnityEvent)button.onClick).AddListener(clickAction); ((Component)button).GetComponent<ArmoireInputHandler>().onSelectChange.AddListener((UnityAction<bool>)delegate(bool isSelected) { UpdateScrollViewButtonSelection(isSelected, ((Component)button).gameObject); }); } private void SetupToggleHiddenListener() { ((UnityEvent<bool>)(object)toggleHidden.onValueChanged).AddListener((UnityAction<bool>)ToggleHiddenClicked); } private void SetupExtraneousButtonListeners() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown ((UnityEvent)cancelButton.onClick).AddListener(new UnityAction(CancelButtonClicked)); ((UnityEvent)outfitsButton.onClick).AddListener(new UnityAction(ShowOutfitsPanel)); } private void SetupOutfitPanelButtonListeners() { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Expected O, but got Unknown //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Expected O, but got Unknown int num = -1; foreach (Button cycleOutfitButton in cycleOutfitButtons) { int closureDirection = num; ((UnityEvent)cycleOutfitButton.onClick).AddListener((UnityAction)delegate { CycleOutfitButtonClicked(closureDirection); }); num = Math.Abs(num); } ((UnityEvent)saveOutfitButton.onClick).AddListener(new UnityAction(SaveOutfitButtonClicked)); ((UnityEvent)loadOutfitButton.onClick).AddListener(new UnityAction(LoadOutfitButtonClicked)); ((UnityEvent)deleteOutfitButton.onClick).AddListener(new UnityAction(DeleteOutfitButtonClicked)); } } internal static class ArmoireUIController { private static ArmoireDoor lastUsedArmoire = null; private static Quaternion oldLookYaw = Quaternion.identity; private static float oldLookPitch; private static Vector3 oldLookDir = default(Vector3); internal static bool cancelButtonWasClicked = false; internal static ArmoireUI ArmoireUIInstance { get; set; } internal static void CreateArmoireUI(Transform hudroot) { StaticMembers.Dbgl("Creating ArmoireUI", forceLog: false, (LogLevel)16); (ArmoireUIInstance = Object.Instantiate<GameObject>(StaticMembers.guiPrefab, hudroot, false).GetComponent<ArmoireUI>()).Initialize(); } internal static void DestroyArmoireUI() { StaticMembers.Dbgl("Destroying ArmoireUI", forceLog: false, (LogLevel)16); Object.Destroy((Object)(object)ArmoireUIInstance); } internal static bool IsArmoirePanelValid() { return Object.op_Implicit((Object)(object)ArmoireUIInstance); } internal static bool TryGetArmoirePanel(out ArmoireUI armoireUI) { armoireUI = ArmoireUIInstance; return armoireUI != null; } internal static bool IsArmoirePanelActive() { if (IsArmoirePanelValid()) { return ((Component)ArmoireUIInstance).gameObject.activeSelf; } return false; } private static void HideArmoirePanel() { ((Component)ArmoireUIInstance).gameObject.SetActive(false); ArmoireUIInstance.DestroyScrollableGrid(); } private static void ShowArmoireUI() { ((Component)ArmoireUIInstance).gameObject.SetActive(true); ArmoireUIInstance.slotsPanel.SetActive(true); ArmoireUIInstance.scrollView.SetActive(false); } internal static void ToggleArmoirePanel(ArmoireDoor openedArmoire = null) { if (IsArmoirePanelActive()) { CloseArmoirePanel(); } else { OpenArmoirePanel(openedArmoire); } } private static void CloseArmoirePanel() { //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_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) HideArmoirePanel(); if (Object.op_Implicit((Object)(object)lastUsedArmoire)) { lastUsedArmoire.ResetState(); Player localPlayer = Player.m_localPlayer; ((Character)localPlayer).m_lookYaw = oldLookYaw; localPlayer.m_lookPitch = oldLookPitch; ((Character)localPlayer).m_lookDir = oldLookDir; localPlayer.ResetAttachCameraPoint(); ((Character)localPlayer).AttachStop(); lastUsedArmoire = null; } } private static void OpenArmoirePanel(ArmoireDoor openedArmoire) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) ShowArmoireUI(); if (Object.op_Implicit((Object)(object)openedArmoire)) { lastUsedArmoire = openedArmoire; Player localPlayer = Player.m_localPlayer; oldLookYaw = ((Character)localPlayer).m_lookYaw; oldLookPitch = localPlayer.m_lookPitch; oldLookDir = ((Character)localPlayer).m_lookDir; localPlayer.m_lookPitch = -20f; ((Character)localPlayer).UpdateEyeRotation(); ((Character)localPlayer).m_lookDir = ((Character)localPlayer).m_eye.forward; } } internal static bool HandleEscapeOrCancelInput() { if (cancelButtonWasClicked) { cancelButtonWasClicked = false; ArmoireDoor armoireDoor = lastUsedArmoire; if (armoireDoor != null && armoireDoor.CanInteract) { ToggleArmoirePanel(); return true; } } if (!Object.op_Implicit((Object)(object)lastUsedArmoire)) { ArmoireUIInstance.ToggleExtraneousButtons(forceReset: true); ToggleArmoirePanel(); return true; } return false; } } internal sealed class ModConfig { private readonly ConfigFile ConfigFile; private readonly ConfigEntry<bool> enableOverrides; private readonly ConfigEntry<bool> showAllAppearances; private readonly ConfigEntry<string> disabledAppearanceNames; private readonly ConfigEntry<bool> excludeDLCItems; private readonly ConfigEntry<bool> showUndiscoveredHoverDetails; private readonly ConfigEntry<bool> enableDebugMessages; private readonly ConfigEntry<bool> allowDragging; private readonly ConfigEntry<Vector2> uiPosition; internal bool EnableOverrides { get { return enableOverrides.Value; } set { ((ConfigEntryBase)enableOverrides).BoxedValue = value; } } internal bool ShowAllAppearances { get { return showAllAppearances.Value; } set { ((ConfigEntryBase)showAllAppearances).BoxedValue = value; } } internal HashSet<string> DisabledAppearanceNames { get { HashSet<string> hashSet = new HashSet<string>(); string[] array = disabledAppearanceNames.Value.Split(new char[1] { ',' }); foreach (string item in array) { hashSet.Add(item); } return hashSet; } } internal bool ExcludeDLCItems => excludeDLCItems.Value; internal bool ShowUndiscoveredHoverDetails => showUndiscoveredHoverDetails.Value; internal bool EnableDebugMessages => enableDebugMessages.Value; internal bool AllowDragging => allowDragging.Value; internal Vector2 UIPosition { get { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return uiPosition.Value; } set { //IL_0006: Unknown result type (might be due to invalid IL or missing references) ((ConfigEntryBase)uiPosition).BoxedValue = value; } } internal ModConfig(ConfigFile configFile) { //IL_016e: Unknown result type (might be due to invalid IL or missing references) ConfigFile = configFile; configFile.SaveOnConfigSet = false; enableOverrides = ConfigFile.Bind<bool>("General", "EnableOverrides", true, "Enables overriding of appearances on local player."); showAllAppearances = ConfigFile.Bind<bool>("General", "ShowAllAppearances", true, "Enables display of all unlockable appearances."); disabledAppearanceNames = ConfigFile.Bind<string>("General", "DisabledAppearanceNames", "ShieldKnight,ShieldIronSquare,CapeTest,PickaxeStone, SledgeCheat, SwordCheat", "To disable specific appearances from being totalled as locked/unlocked, list their prefab names here separated by a comma. Names are case-sensitive."); excludeDLCItems = ConfigFile.Bind<bool>("General", "ExcludeDLCItems", true, "Excludes DLC items (OdinCape, HelmetOdin) from being totalled as locked/unlocked."); showUndiscoveredHoverDetails = ConfigFile.Bind<bool>("General", "ShowUndiscoveredHoverDetails", false, "Shows/hides additional details in undiscovered appearance tooltips."); enableDebugMessages = ConfigFile.Bind<bool>("General", "EnableDebugMessages", false, "Enable mod debug messages in console."); enableOverrides.SettingChanged += delegate { Player localPlayer2 = Player.m_localPlayer; if (localPlayer2 != null) { ((Humanoid)localPlayer2).SetupEquipment(); } }; excludeDLCItems.SettingChanged += delegate { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { AppearanceCategorizer.RecalculateAppearances(localPlayer); } if (ArmoireUIController.TryGetArmoirePanel(out var armoireUI) && armoireUI.scrollView.activeSelf) { armoireUI.RebuildScrollableGrid(); } }; allowDragging = ConfigFile.Bind<bool>("UIPosition", "AllowDragging", false, "If set to true, the ArmoireUI panel can be moved by holding left ctrl then clicking and dragging."); uiPosition = ConfigFile.Bind<Vector2>("UIPosition", "UIPosition", new Vector2(290f, 0f), "X,Y position of Armoire UI Panel from center-left anchor."); uiPosition.SettingChanged += UpdateUIPanelPosition; configFile.Save(); configFile.SaveOnConfigSet = true; } internal void UpdateUIPanelPosition(object sender, EventArgs e) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (ArmoireUIController.TryGetArmoirePanel(out var armoireUI)) { ((Component)armoireUI).GetComponent<RectTransform>().anchoredPosition = uiPosition.Value; } } } internal static class AppearanceCategorizer { private static readonly HashSet<ItemType> RelevantTypes = new HashSet<ItemType> { (ItemType)6, (ItemType)7, (ItemType)11, (ItemType)17, (ItemType)18, (ItemType)24, (ItemType)4, (ItemType)5, (ItemType)3, (ItemType)14 }; private static readonly HashSet<ItemType> ArmorTypes = new HashSet<ItemType> { (ItemType)6, (ItemType)7, (ItemType)11, (ItemType)17, (ItemType)18, (ItemType)24 }; internal static void CategorizeAppearances(Player player) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) IEnumerable<ItemDrop> enumerable = from item in GetAllItemsByTypes(RelevantTypes) where item.m_itemData.m_shared.m_icons.Length != 0 && !StaticMembers.config.DisabledAppearanceNames.Contains(((Object)item).name) && (!StaticMembers.config.ExcludeDLCItems || string.IsNullOrEmpty(item.m_itemData.m_shared.m_dlc)) select item; Dictionary<AppearanceSlotType, List<ItemDrop>> dictionary = new Dictionary<AppearanceSlotType, List<ItemDrop>>(); foreach (ItemDrop item in enumerable) { ItemType itemType = item.m_itemData.m_shared.m_itemType; SkillType skillType = item.m_itemData.m_shared.m_skillType; AddToCategory(dictionary, MapAppearanceSlot(itemType, skillType), item); } Dictionary<AppearanceSlotType, List<ItemDrop>> source = dictionary.ToDictionary((KeyValuePair<AppearanceSlotType, List<ItemDrop>> kvp) => kvp.Key, (KeyValuePair<AppearanceSlotType, List<ItemDrop>> kvp) => kvp.Value.Where((ItemDrop item) => player.m_knownMaterial.Contains(item.m_itemData.m_shared.m_name)).ToList()); StaticMembers.AllAppearances = dictionary.ToDictionary((KeyValuePair<AppearanceSlotType, List<ItemDrop>> kvp) => kvp.Key, (KeyValuePair<AppearanceSlotType, List<ItemDrop>> kvp) => BuildIconCountMap(kvp.Value)); StaticMembers.UnlockedAppearances = source.ToDictionary((KeyValuePair<AppearanceSlotType, List<ItemDrop>> kvp) => kvp.Key, (KeyValuePair<AppearanceSlotType, List<ItemDrop>> kvp) => BuildIconCountMap(kvp.Value)); } private static void AddToCategory(Dictionary<AppearanceSlotType, List<ItemDrop>> dict, AppearanceSlotType? slotType, ItemDrop item) { if (slotType.HasValue) { AppearanceSlotType valueOrDefault = slotType.GetValueOrDefault(); if (!dict.ContainsKey(valueOrDefault)) { dict[valueOrDefault] = new List<ItemDrop>(); } dict[valueOrDefault].Add(item); } } private static AppearanceSlotType? MapAppearanceSlot(ItemType type, SkillType skill) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007b: 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) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Expected I4, but got Unknown //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Invalid comparison between Unknown and I4 //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Expected I4, but got Unknown //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Invalid comparison between Unknown and I4 //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Invalid comparison between Unknown and I4 //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Invalid comparison between Unknown and I4 //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Invalid comparison between Unknown and I4 //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Invalid comparison between Unknown and I4 //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Invalid comparison between Unknown and I4 //IL_0103: 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_013b: Expected I4, but got Unknown //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Invalid comparison between Unknown and I4 //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Invalid comparison between Unknown and I4 //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Invalid comparison between Unknown and I4 //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Invalid comparison between Unknown and I4 //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Invalid comparison between Unknown and I4 ItemType val; if (ArmorTypes.Contains(type)) { val = type; if ((int)val <= 11) { if ((int)val == 6) { return AppearanceSlotType.Helmet; } if ((int)val == 7) { return AppearanceSlotType.Chest; } if ((int)val == 11) { return AppearanceSlotType.Legs; } } else { if ((int)val == 17) { return AppearanceSlotType.Shoulder; } if ((int)val != 18) { if ((int)val == 24) { return AppearanceSlotType.Trinket; } } else if ((int)skill == 1) { return AppearanceSlotType.Utility; } } return null; } val = type; switch (val - 3) { default: { if ((int)val != 14) { break; } AppearanceSlotType? result; switch (skill - 1) { case 6: result = AppearanceSlotType.TwoHandedAxe; break; case 2: result = AppearanceSlotType.TwoHandedClub; break; case 0: result = AppearanceSlotType.TwoHandedSword; break; case 3: result = AppearanceSlotType.Polearm; break; case 11: result = AppearanceSlotType.Pickaxe; break; case 8: case 9: result = AppearanceSlotType.Staff; break; case 1: result = AppearanceSlotType.Knife; break; case 10: result = AppearanceSlotType.Fist; break; default: result = null; break; } return result; } case 0: return (skill - 1) switch { 6 => AppearanceSlotType.OneHandedAxe, 2 => AppearanceSlotType.OneHandedClub, 0 => AppearanceSlotType.OneHandedSword, 1 => AppearanceSlotType.Knife, 4 => AppearanceSlotType.Spear, _ => null, }; case 1: return ((int)skill == 8) ? new AppearanceSlotType?(AppearanceSlotType.Bow) : (((int)skill != 14) ? null : new AppearanceSlotType?(AppearanceSlotType.Crossbow)); case 2: if ((int)skill == 6) { return AppearanceSlotType.Shield; } break; } return null; } private static List<ItemDrop> GetAllItemsByTypes(HashSet<ItemType> types) { return (from go in ObjectDB.instance.m_items select go.GetComponent<ItemDrop>() into item where Object.op_Implicit((Object)(object)item) && types.Contains(item.m_itemData.m_shared.m_itemType) select item).ToList(); } private static Dictionary<ItemDrop, int> BuildIconCountMap(List<ItemDrop> items) { return items.ToDictionary((ItemDrop item) => item, (ItemDrop item) => item.m_itemData.m_shared.m_icons.Length); } internal static void RecalculateAppearances(Player player) { CategorizeAppearances(player); AppearanceTracker.UpdateTotal(); } } internal sealed class AppearanceData { private static readonly Version MinimumSupported = new Version("1.0.0"); internal static void LoadAppearanceData(ZPackage package, Dictionary<AppearanceSlotType, AppearanceSlot> overrides) { try { StaticMembers.Dbgl("Loading player armoire data...", forceLog: false, (LogLevel)16); string text = package.ReadString(); if (!Version.TryParse(text, out Version result)) { StaticMembers.Dbgl("Invalid version format: " + text, forceLog: true, (LogLevel)4); return; } if (result < MinimumSupported) { StaticMembers.Dbgl("Unsupported armoire data version: " + text, forceLog: true, (LogLevel)4); return; } int num = package.ReadInt(); for (int i = 0; i < num; i++) { if (Enum.TryParse<AppearanceSlotType>(package.ReadString(), out var result2) && overrides.TryGetValue(result2, out var value)) { value.ItemName = package.ReadString(); value.ItemVariant = package.ReadInt(); if (value.CanBeHidden) { value.Hidden = package.ReadBool(); } } } StaticMembers.Dbgl("...player armoire data loading complete", forceLog: false, (LogLevel)16); } catch (Exception ex) { StaticMembers.Dbgl("Error loading appearance data: " + ex.Message, forceLog: true, (LogLevel)2); } } internal static void SaveAppearanceData(string dataKey) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write("1.1.4"); val.Write(StaticMembers.ActiveOverrides.Count); foreach (KeyValuePair<AppearanceSlotType, AppearanceSlot> activeOverride in StaticMembers.ActiveOverrides) { val.Write(activeOverride.Key.ToString()); val.Write(activeOverride.Value.ItemName); val.Write(activeOverride.Value.ItemVariant); if (activeOverride.Value.CanBeHidden) { val.Write(activeOverride.Value.Hidden); } } Player.m_localPlayer.m_customData[dataKey] = val.GetBase64(); StaticMembers.Dbgl("Saved player armoire data", forceLog: false, (LogLevel)16); } } public sealed class AppearanceSlot { private Func<SharedData, bool> IsValidForSlot = slotCriteria ?? ((Func<SharedData, bool>)((SharedData valid) => false)); public string ItemName = string.Empty; public int ItemVariant; public bool Hidden; public bool CanBeHidden; public AppearanceSlot(Func<SharedData, bool> slotCriteria = null, bool canBeHidden = false) { CanBeHidden = canBeHidden; base..ctor(); } public void ResetSlot() { ItemName = string.Empty; ItemVariant = 0; Hidden = false; } public AppearanceSlot(AppearanceSlot other) : this(other.IsValidForSlot, other.CanBeHidden) { ItemName = other.ItemName; ItemVariant = other.ItemVariant; Hidden = other.Hidden; } public bool IsMatch(SharedData sd) { return IsValidForSlot(sd); } } public enum AppearanceSlotType { Helmet, Chest, Legs, Shoulder, Utility, Trinket, Bow, Crossbow, Shield, OneHandedAxe, OneHandedClub, OneHandedSword, Knife, Spear, TwoHandedAxe, TwoHandedClub, TwoHandedSword, Polearm, Pickaxe, Staff, Fist } internal static class AppearanceTracker { internal static int TotalUnlocked { get; set; } internal static int TotalCollectable { get; set; } internal static double UnlockedPercentage { get { if (TotalCollectable != 0) { return (double)TotalUnlocked / (double)TotalCollectable; } return 0.0; } } internal static int Unlocked(AppearanceSlotType slotType) { return StaticMembers.UnlockedAppearances[slotType].Values.Sum(); } internal static int Total(AppearanceSlotType slotType) { return StaticMembers.AllAppearances[slotType].Values.Sum(); } internal static void UpdateTotal() { TotalUnlocked = StaticMembers.UnlockedAppearances.Values.Sum((Dictionary<ItemDrop, int> dict) => dict.Values.Sum()); TotalCollectable = StaticMembers.AllAppearances.Values.Sum((Dictionary<ItemDrop, int> dict) => dict.Values.Sum()); StaticMembers.Dbgl($"UnlockedAppearances Count: {TotalUnlocked}", forceLog: false, (LogLevel)16); StaticMembers.Dbgl($"AllAppearances Count: {TotalCollectable}", forceLog: false, (LogLevel)16); } } internal static class PluginUtils { internal static AppearanceSlot FindMatchingSlot(SharedData sd) { return StaticMembers.ActiveOverrides.Values.FirstOrDefault((AppearanceSlot slot) => slot.IsMatch(sd)); } internal static AppearanceSlotType? GetSlotTypeForItemDrop(ItemDrop item) { foreach (KeyValuePair<AppearanceSlotType, Dictionary<ItemDrop, int>> allAppearance in StaticMembers.AllAppearances) { if (allAppearance.Value.ContainsKey(item)) { return allAppearance.Key; } } return null; } internal static Dictionary<AppearanceSlotType, AppearanceSlot> CloneOverrides(Dictionary<AppearanceSlotType, AppearanceSlot> source) { return source.ToDictionary((KeyValuePair<AppearanceSlotType, AppearanceSlot> entry) => entry.Key, (KeyValuePair<AppearanceSlotType, AppearanceSlot> entry) => new AppearanceSlot(entry.Value)); } } [HarmonyPatch(typeof(PlayerProfile), "LoadPlayerData")] internal static class LoadDataPatches { private static void Postfix(Player player) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown if (player.m_customData.TryGetValue("Armoire_Appearances", out var value)) { StaticMembers.Dbgl("Armoire_Appearances key found in player.m_customData", forceLog: false, (LogLevel)16); AppearanceData.LoadAppearanceData(new ZPackage(value), StaticMembers.ActiveOverrides); } else { StaticMembers.ActiveOverrides.Values.ToList().ForEach(delegate(AppearanceSlot slot) { slot.ResetSlot(); }); } if (ArmoireUIController.IsArmoirePanelValid()) { StaticMembers.Dbgl("UI is initialized, updating item slot icons", forceLog: false, (LogLevel)16); ArmoireUIController.ArmoireUIInstance.UpdateItemSlotIcons(StaticMembers.ActiveOverrides); } else { StaticMembers.Dbgl("UI isn't initialized, can't update item slot icons", forceLog: false, (LogLevel)16); } ((Humanoid)player).SetupEquipment(); AppearanceCategorizer.RecalculateAppearances(player); } } [HarmonyPatch] internal static class UIPatches { [HarmonyPatch(typeof(Hud))] private static class HUDPatches { [HarmonyPatch("Awake")] private static void Postfix(Hud __instance) { ArmoireUIController.CreateArmoireUI(__instance.m_rootObject.transform); } [HarmonyPatch("OnDestroy")] private static void Prefix() { ArmoireUIController.DestroyArmoireUI(); } } [HarmonyPatch(typeof(UnifiedPopup), "IsVisible")] private static class UnifiedPopupIsVisiblePatch { private static bool Prefix(ref bool __result) { if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && ArmoireUIController.IsArmoirePanelActive()) { __result = true; return false; } return true; } } } [HarmonyPatch(typeof(ZNetScene), "Awake")] internal static class PieceInitPatches { private static bool isInitialized; private static void Postfix(ZNetScene __instance) { //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Invalid comparison between Unknown and I4 __instance.m_prefabs.Add(StaticMembers.armoirePiecePrefab); __instance.m_namedPrefabs.Add(__instance.GetPrefabHash(StaticMembers.armoirePiecePrefab), StaticMembers.armoirePiecePrefab); PieceTable buildPieces = __instance.GetPrefab("Hammer").GetComponent<ItemDrop>().m_itemData.m_shared.m_buildPieces; if (!buildPieces.m_pieces.Contains(StaticMembers.armoirePiecePrefab)) { StaticMembers.Dbgl("piece is not in build table, adding", forceLog: false, (LogLevel)16); buildPieces.m_pieces.Add(StaticMembers.armoirePiecePrefab); } if (!isInitialized) { if ((int)SystemInfo.graphicsDeviceType != 4) { InitializeArmoirePiece(__instance); } isInitialized = true; } } private static void InitializeArmoirePiece(ZNetScene instance) { GameObject prefab = instance.GetPrefab("wood_door"); Door component = prefab.GetComponent<Door>(); Piece component2 = prefab.GetComponent<Piece>(); WearNTear component3 = prefab.GetComponent<WearNTear>(); Piece component4 = StaticMembers.armoirePiecePrefab.GetComponent<Piece>(); WearNTear component5 = StaticMembers.armoirePiecePrefab.GetComponent<WearNTear>(); ArmoireDoor.SoundEffects.Add(component.m_closeEffects); ArmoireDoor.SoundEffects.Add(component.m_openEffects); component5.m_destroyedEffect.m_effectPrefabs = component3.m_destroyedEffect.m_effectPrefabs; component5.m_hitEffect.m_effectPrefabs = component3.m_hitEffect.m_effectPrefabs; component4.m_placeEffect = component2.m_placeEffect; component4.m_craftingStation = component2.m_craftingStation; string[] array = new string[3] { "Wood", "Tin", "Bronze" }; for (int i = 0; i < array.Length; i++) { component4.m_resources[i].m_resItem = ObjectDB.instance.GetItemPrefab(array[i]).GetComponent<ItemDrop>(); } Material[] materials = CreateArmoireMaterials(); Array.ForEach(new string[3] { "DoorLeft", "DoorRight", "Wardrobe" }, delegate(string child) { ((Renderer)((Component)StaticMembers.armoirePiecePrefab.transform.Find(child)).GetComponent<MeshRenderer>()).sharedMaterials = materials; }); Transform val = StaticMembers.armoirePiecePrefab.transform.Find("EquipmentAttachPoints"); ReplaceMesh(instance, "ShieldIronBuckler", "attach/model (1)", val.GetChild(0).GetChild(0)); ReplaceMesh(instance, "SpearElderbark", "attach/default", val.GetChild(1).GetChild(0)); ReplaceMesh(instance, "Bow", "attach/default", val.GetChild(1).GetChild(1)); ReplaceSkinnedMesh(instance, "HelmetOdin", "attach_skin/hood", val.GetChild(2).GetChild(0).GetChild(0)); ReplaceSkinnedMesh(instance, "CapeOdin", "attach_skin/cape1", val.GetChild(2).GetChild(1).GetChild(0)); } private static Material[] CreateArmoireMaterials() { //IL_000f: 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_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_003a: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected O, but got Unknown AssetID val = default(AssetID); AssetID.TryParse("f6de4704e075b4095ae641aed283b641", ref val); SoftReference<Shader> val2 = default(SoftReference<Shader>); val2..ctor(val); val2.Load(); Material val3 = new Material(val2.Asset) { mainTexture = (Texture)(object)UIResources.GetTexture("woodtower_d") }; val3.SetInt("_Cull", 0); val3.SetFloat("_TwoSidedNormals", 1f); Material val4 = new Material(val2.Asset) { mainTexture = (Texture)(object)UIResources.GetTexture("DarkWoodBeams_d") }; return (Material[])(object)new Material[2] { val3, val4 }; } private static void ReplaceMesh(ZNetScene scene, string prefabName, string path, Transform target) { Transform val = scene.GetPrefab(prefabName).transform.Find(path); ((Component)target).GetComponent<MeshFilter>().sharedMesh = ((Component)val).GetComponent<MeshFilter>().sharedMesh; ((Renderer)((Component)target).GetComponent<MeshRenderer>()).sharedMaterials = ((Renderer)((Component)val).GetComponent<MeshRenderer>()).sharedMaterials; } private static void ReplaceSkinnedMesh(ZNetScene scene, string prefabName, string path, Transform target) { SkinnedMeshRenderer component = ((Component)scene.GetPrefab(prefabName).transform.Find(path)).GetComponent<SkinnedMeshRenderer>(); SkinnedMeshRenderer component2 = ((Component)target).GetComponent<SkinnedMeshRenderer>(); component2.sharedMesh = component.sharedMesh; ((Renderer)component2).sharedMaterials = ((Renderer)component).sharedMaterials; } } [HarmonyPatch(typeof(Player), "AddKnownItem")] internal static class DiscoverItemPatches { private static Sprite _armoireIcon; private static Sprite ArmoireIcon => _armoireIcon ?? (_armoireIcon = StaticMembers.armoirePiecePrefab.GetComponent<Piece>().m_icon); [HarmonyTranspiler] private static IEnumerable<CodeInstruction> AddKnownItemPatch(IEnumerable<CodeInstruction> instructions) { //IL_0002: 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_003b: Expected O, but got Unknown //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Expected O, but got Unknown //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown return new CodeMatcher(instructions, (ILGenerator)null).Start().MatchStartForward((CodeMatch[])(object)new CodeMatch[2] { new CodeMatch((OpCode?)OpCodes.Callvirt, (object)AccessTools.Method(typeof(HashSet<string>), "Contains", (Type[])null, (Type[])null), (string)null), new CodeMatch((OpCode?)OpCodes.Brtrue, (object)null, (string)null) }).ThrowIfInvalid("Could not patch Player.AddKnownItem()!") .Advance(2) .InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[2] { new CodeInstruction(OpCodes.Ldarg_1, (object)null), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(DiscoverItemPatches), "UnlockNewAppearance", (Type[])null, (Type[])null)) }) .InstructionEnumeration(); } private static void UnlockNewAppearance(ItemData discoveredItem) { StaticMembers.Dbgl("New item discovered: " + discoveredItem.m_shared.m_name, forceLog: false, (LogLevel)16); ItemDrop component = discoveredItem.m_dropPrefab.GetComponent<ItemDrop>(); AppearanceSlotType? slotTypeForItemDrop = PluginUtils.GetSlotTypeForItemDrop(component); if (slotTypeForItemDrop.HasValue) { MessageHud.instance.QueueUnlockMsg(ArmoireIcon, "<color=#00FFFF>Appearance Unlocked!</color>", discoveredItem.m_shared.m_name); StaticMembers.UnlockedAppearances[slotTypeForItemDrop.Value][component] = component.m_itemData.m_shared.m_icons.Length; AppearanceTracker.UpdateTotal(); } } } [HarmonyPatch] internal static class EquipmentPatches { [HarmonyPatch(typeof(VisEquipment))] private static class VisEquipmentPatches { private enum OverrideTarget { LeftItem, RightItem } private static readonly Dictionary<string, (AppearanceSlotType slot, Func<Player, ItemData> targetedItem)> SimpleItemMap = new Dictionary<string, (AppearanceSlotType, Func<Player, ItemData>)> { { "SetHelmetItem", (AppearanceSlotType.Helmet, (Player player) => ((Humanoid)player).m_helmetItem) }, { "SetChestItem", (AppearanceSlotType.Chest, (Player player) => ((Humanoid)player).m_chestItem) }, { "SetLegItem", (AppearanceSlotType.Legs, (Player player) => ((Humanoid)player).m_legItem) }, { "SetUtilityItem", (AppearanceSlotType.Utility, (Player player) => ((Humanoid)player).m_utilityItem) }, { "SetTrinketItem", (AppearanceSlotType.Trinket, (Player player) => ((Humanoid)player).m_trinketItem) } }; [HarmonyPatch("SetHelmetItem")] [HarmonyPatch("SetChestItem")] [HarmonyPatch("SetLegItem")] [HarmonyPatch("SetUtilityItem")] [HarmonyPatch("SetTrinketItem")] [HarmonyPrefix] private static void SetSimpleItem(VisEquipment __instance, MethodBase __originalMethod, ref string name) { if (SimpleItemMap.TryGetValue(__originalMethod.Name, out (AppearanceSlotType, Func<Player, ItemData>) value)) { TryOverrideItem(__instance, ref name, value.Item2, value.Item1); } } [HarmonyPatch("SetShoulderItem")] [HarmonyPrefix] private static void SetShoulderItem(VisEquipment __instance, ref string name, ref int variant) { TryOverrideItemWithVariant(__instance, ref name, ref variant, (Player p) => ((Humanoid)p).m_shoulderItem, AppearanceSlotType.Shoulder); } [HarmonyPatch("SetLeftItem")] [HarmonyPrefix] private static void SetLeftItem(VisEquipment __instance, ref string name, ref int variant) { TryOverrideMatchingItem(__instance, ref name, ref variant, (Player p) => ((Humanoid)p).m_leftItem, OverrideTarget.LeftItem); } [HarmonyPatch("SetLeftBackItem")] [HarmonyPrefix] private static void SetLeftBackItem(VisEquipment __instance, ref string name, ref int variant) { TryOverrideMatchingItem(__instance, ref name, ref variant, (Player p) => ((Humanoid)p).m_hiddenLeftItem); } [HarmonyPatch("SetRightItem")] [HarmonyPrefix] private static void SetRightItem(VisEquipment __instance, ref string name) { int variant = 0; TryOverrideMatchingItem(__instance, ref name, ref variant, (Player p) => ((Humanoid)p).m_rightItem, OverrideTarget.RightItem); } [HarmonyPatch("SetRightBackItem")] [HarmonyPrefix] private static void SetRightBackItem(VisEquipment __instance, ref string name) { int variant = 0; TryOverrideMatchingItem(__instance, ref name, ref variant, (Player p) => ((Humanoid)p).m_hiddenRightItem); } private static bool ShouldOverrideAppearance(VisEquipment instance) { if (StaticMembers.config.EnableOverrides) { GameObject gameObject = ((Component)instance).gameObject; Player localPlayer = Player.m_localPlayer; if (!((Object)(object)gameObject == (Object)(object)((localPlayer != null) ? ((Component)localPlayer).gameObject : null))) { return !Object.op_Implicit((Object)(object)ZNetScene.instance); } return true; } return false; } private static void TryOverrideItem(VisEquipment instance, ref string name, Func<Player, ItemData> targetedItem, AppearanceSlotType slotType) { Player arg = default(Player); if (ShouldOverrideAppearance(instance) && ((Component)instance).TryGetComponent<Player>(ref arg) && targetedItem(arg) != null) { AppearanceSlot appearanceSlot = StaticMembers.ActiveOverrides[slotType]; if (!string.IsNullOrEmpty(appearanceSlot.ItemName) || appearanceSlot.Hidden) { name = appearanceSlot.ItemName; } } } private static void TryOverrideItemWithVariant(VisEquipment instance, ref string name, ref int variant, Func<Player, ItemData> targetedItem, AppearanceSlotType slotType) { Player arg = default(Player); if (ShouldOverrideAppearance(instance) && ((Component)instance).TryGetComponent<Player>(ref arg) && targetedItem(arg) != null) { AppearanceSlot appearanceSlot = StaticMembers.ActiveOverrides[slotType]; if (!string.IsNullOrEmpty(appearanceSlot.ItemName) || appearanceSlot.Hidden) { name = appearanceSlot.ItemName; variant = appearanceSlot.ItemVariant; } } } private static void TryOverrideMatchingItem(VisEquipment instance, ref string name, ref int variant, Func<Player, ItemData> targetedItem, OverrideTarget? target = null) { Player arg = default(Player); if (!ShouldOverrideAppearance(instance) || !((Component)instance).TryGetComponent<Player>(ref arg)) { return; } ItemData val = targetedItem(arg); if (val != null) { AppearanceSlot appearanceSlot = PluginUtils.FindMatchingSlot(val.m_shared); bool flag = !string.IsNullOrEmpty(appearanceSlot?.ItemName); if (flag) { name = appearanceSlot.ItemName; variant = appearanceSlot.ItemVariant; } if (target == OverrideTarget.LeftItem) { overriddenLeftItem = (flag ? name : ""); } else if (target.GetValueOrDefault() == OverrideTarget.RightItem) { overriddenRightItem = (flag ? name : ""); } } } } [HarmonyPatch(typeof(Humanoid))] private static class MiscEquipmentPatches { [HarmonyPatch("SetupAnimationState")] [HarmonyPostfix] private static void FixAnimationState(Humanoid __instance) { //IL_0072: Unknown result type (might be due to invalid IL or missing references) string text = ((__instance.m_leftItem != null) ? overriddenLeftItem : ((__instance.m_rightItem != null) ? overriddenRightItem : null)); if (string.IsNullOrEmpty(text)) { return; } GameObject prefab = ZNetScene.instance.GetPrefab(text); ItemDrop val = ((prefab != null) ? prefab.GetComponent<ItemDrop>() : null); if (!((Object)(object)val == (Object)null)) { SharedData shared = val.m_itemData.m_shared; if (!string.IsNullOrEmpty(PluginUtils.FindMatchingSlot(shared)?.ItemName)) { __instance.SetAnimationState(shared.m_animationState); } } } } internal static string overriddenLeftItem = ""; internal static string overriddenRightItem = ""; } internal static class StaticMembers { internal static ManualLogSource ModLogger = new ManualLogSource(" Armoire"); internal static ModConfig config; internal static AssetBundle assetBundle; internal static GameObject guiPrefab = null; internal static GameObject armoireSlot = null; internal static GameObject armoirePiecePrefab = null; internal static readonly Dictionary<LogLevel, Action<string>> logActions = new Dictionary<LogLevel, Action<string>> { { (LogLevel)1, (Action<string>)ModLogger.LogFatal }, { (LogLevel)2, (Action<string>)ModLogger.LogError }, { (LogLevel)4, (Action<string>)ModLogger.LogWarning }, { (LogLevel)8, (Action<string>)ModLogger.LogMessage }, { (LogLevel)16, (Action<string>)ModLogger.LogInfo }, { (LogLevel)32, (Action<string>)ModLogger.LogDebug } }; internal static Dictionary<AppearanceSlotType, AppearanceSlot> ActiveOverrides = new Dictionary<AppearanceSlotType, AppearanceSlot> { { AppearanceSlotType.Helmet, new AppearanceSlot(null, canBeHidden: true) }, { AppearanceSlotType.Chest, new AppearanceSlot(null, canBeHidden: true) }, { AppearanceSlotType.Legs, new AppearanceSlot(null, canBeHidden: true) }, { AppearanceSlotType.Shoulder, new AppearanceSlot(null, canBeHidden: true) }, { AppearanceSlotType.Utility, new AppearanceSlot(null, canBeHidden: true) }, { AppearanceSlotType.Trinket, new AppearanceSlot(null, canBeHidden: true) }, { AppearanceSlotType.Bow, new AppearanceSlot((SharedData candidate) => (int)candidate.m_itemType == 4 && (int)candidate.m_skillType == 8) }, { AppearanceSlotType.Crossbow, new AppearanceSlot((SharedData candidate) => (int)candidate.m_itemType == 4 && (int)candidate.m_skillType == 14) }, { AppearanceSlotType.Shield, new AppearanceSlot((SharedData candidate) => (int)candidate.m_itemType == 5 && (int)candidate.m_skillType == 6) }, { AppearanceSlotType.OneHandedAxe, new AppearanceSlot((SharedData candidate) => (int)candidate.m_itemType == 3 && (int)candidate.m_skillType == 7) }, { AppearanceSlotType.OneHandedClub, new AppearanceSlot((SharedData candidate) => (int)candidate.m_itemType == 3 && (int)candidate.m_skillType == 3) }, { AppearanceSlotType.OneHandedSword, new AppearanceSlot((SharedData candidate) => (int)candidate.m_itemType == 3 && (int)candidate.m_skillType == 1) }, { AppearanceSlotType.Knife, new AppearanceSlot(delegate(SharedData candidate) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: 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) //IL_0009: Invalid comparison between Unknown and I4 //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Invalid comparison between Unknown and I4 ItemType itemType = candidate.m_itemType; return (((int)itemType == 3 || (int)itemType == 14) ? true : false) && (int)candidate.m_skillType == 2; }) }, { AppearanceSlotType.Spear, new AppearanceSlot((SharedData candidate) => (int)candidate.m_itemType == 3 && (int)candidate.m_skillType == 5) }, { AppearanceSlotType.TwoHandedAxe, new AppearanceSlot((SharedData candidate) => (int)candidate.m_itemType == 14 && (int)candidate.m_skillType == 7) }, { AppearanceSlotType.TwoHandedClub, new AppearanceSlot((SharedData candidate) => (int)candidate.m_itemType == 14 && (int)candidate.m_skillType == 3) }, { AppearanceSlotType.TwoHandedSword, new AppearanceSlot((SharedData candidate) => (int)candidate.m_itemType == 14 && (int)candidate.m_skillType == 1) }, { AppearanceSlotType.Polearm, new AppearanceSlot((SharedData candidate) => (int)candidate.m_itemType == 14 && (int)candidate.m_skillType == 4) }, { AppearanceSlotType.Pickaxe, new AppearanceSlot((SharedData candidate) => (int)candidate.m_itemType == 14 && (int)candidate.m_skillType == 12) }, { AppearanceSlotType.Staff, new AppearanceSlot(delegate(SharedData candidate) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Invalid comparison between Unknown and I4 bool flag = (int)candidate.m_itemType == 14; if (flag) { SkillType skillType = candidate.m_skillType; bool flag2 = skillType - 9 <= 1; flag = flag2; } return flag; }) }, { AppearanceSlotType.Fist, new AppearanceSlot((SharedData candidate) => (int)candidate.m_itemType == 14 && (int)candidate.m_skillType == 11) } }; internal static List<Dictionary<AppearanceSlotType, AppearanceSlot>> OutfitOverrides = (from _ in Enumerable.Range(0, 3) select PluginUtils.CloneOverrides(ActiveOverrides)).ToList(); internal static Dictionary<AppearanceSlotType, Dictionary<ItemDrop, int>> AllAppearances = new Dictionary<AppearanceSlotType, Dictionary<ItemDrop, int>>(); internal static Dictionary<AppearanceSlotType, Dictionary<ItemDrop, int>> UnlockedAppearances = new Dictionary<AppearanceSlotType, Dictionary<ItemDrop, int>>(); internal static Dictionary<AppearanceSlotType, Dictionary<ItemDrop, int>> GetLockedAppearances() { Dictionary<ItemDrop, int> unlocked; return AllAppearances.ToDictionary((KeyValuePair<AppearanceSlotType, Dictionary<ItemDrop, int>> kvp) => kvp.Key, (KeyValuePair<AppearanceSlotType, Dictionary<ItemDrop, int>> kvp) => (!UnlockedAppearances.TryGetValue(kvp.Key, out unlocked)) ? new Dictionary<ItemDrop, int>(kvp.Value) : kvp.Value.Where((KeyValuePair<ItemDrop, int> pair) => !unlocked.ContainsKey(pair.Key)).ToDictionary((KeyValuePair<ItemDrop, int> pair) => pair.Key, (KeyValuePair<ItemDrop, int> pair) => pair.Value)); } internal static AssetBundle LoadAssetBundle(string fileName) { return AssetBundle.LoadFromStream(Assembly.GetExecutingAssembly().GetManifestResourceStream("Advize_Armoire.Assets." + fileName)); } internal static void Dbgl(string message, bool forceLog = false, LogLevel level = 16) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (forceLog || config.EnableDebugMessages) { logActions[level](message); } } } public class ArmoireUIDragHandler : MonoBehaviour, IDragHandler, IEventSystemHandler, IEndDragHandler { public RectTransform panelTransform; private Vector2 _lastUpdatedPosition; private bool _hasBeenDragged; public void OnDrag(PointerEventData eventData) { //IL_0028: 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) //IL_0033: 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) //IL_0049: Unknown result type (might be due to invalid IL or missing references) if (StaticMembers.config.AllowDragging && ZInput.GetKey((KeyCode)306, true)) { _hasBeenDragged = true; RectTransform obj = panelTransform; obj.anchoredPosition += eventData.delta; _lastUpdatedPosition = panelTransform.anchoredPosition; } } public void OnEndDrag(PointerEventData eventData) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (_hasBeenDragged) { StaticMembers.config.UIPosition = _lastUpdatedPosition; _hasBeenDragged = false; } } } public static class UIResources { public static readonly ResourceCache<Sprite> SpriteCache = new ResourceCache<Sprite>(); public static readonly ResourceCache<Material> MaterialCache = new ResourceCache<Material>(); public static readonly ResourceCache<Texture2D> TextureCache = new ResourceCache<Texture2D>(); public static readonly Dictionary<string, Font> FontCache = new Dictionary<string, Font>(); public static readonly Dictionary<string, TMP_FontAsset> FontAssetCache = new Dictionary<string, TMP_FontAsset>(); public static Sprite GetSprite(string spriteName) { return SpriteCache.GetResource(spriteName); } public static Material GetMaterial(string materialName) { return MaterialCache.GetResource(materialName); } public static Texture2D GetTexture(string textureName) { return TextureCache.GetResource(textureName); } public static Sprite GetItemIcon(string prefabName, int variant = 0) { string resourceName = $"{prefabName}.{variant}"; Sprite resource = SpriteCache.GetResource(resourceName); if (Object.op_Implicit((Object)(object)resource)) { return resource; } GameObject prefab = ZNetScene.instance.GetPrefab(prefabName); ItemDrop val = default(ItemDrop); if (Object.op_Implicit((Object)(object)prefab) && prefab.TryGetComponent<ItemDrop>(ref val)) { ItemData itemData = val.m_itemData; if (itemData != null && itemData.m_shared?.m_icons?.Length > variant) { Sprite val2 = val.m_itemData.m_shared.m_icons[variant]; if (Object.op_Implicit((Object)(object)val2)) { SpriteCache.SetResource(resourceName, val2); return val2; } } } return null; } public static TMP_FontAsset GetFontAsset(string fontName) { if (!FontAssetCache.TryGetValue(fontName, out var value)) { value = ((IEnumerable<TMP_FontAsset>)Resources.FindObjectsOfTypeAll<TMP_FontAsset>()).FirstOrDefault((Func<TMP_FontAsset, bool>)((TMP_FontAsset x) => ((Object)x).name == fontName)); FontAssetCache[fontName] = value; } return value; } } public sealed class ResourceCache<T> where T : Object { private readonly Dictionary<string, T> _cache = new Dictionary<string, T>(); public T GetResource(string resourceName) { if (!_cache.TryGetValue(resourceName, out var value)) { value = Resources.FindObjectsOfTypeAll<T>().FirstOrDefault((T x) => ((Object)x).name == resourceName); _cache[resourceName] = value; } return value; } public void SetResource(string resourceName, T resource) { _cache[resourceName] = resource; } } }