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 ZenCompass v1.7.1
plugins/ZenCompass.dll
Decompiled 4 days 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.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; using JetBrains.Annotations; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.UI; using Zen; using Zen.Lib; using Zen.Lib.Config; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("ZenCompass")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+30eedb50f391effa7d70882034a06e62b71de2e7")] [assembly: AssemblyProduct("ZenCompass")] [assembly: AssemblyTitle("ZenCompass")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.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.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] [Microsoft.CodeAnalysis.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] [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 ZenCompass { internal class Compass { [HarmonyPatch] private static class InventoryWatcher { [UsedImplicitly] private static IEnumerable<MethodBase> TargetMethods() { return new <>z__ReadOnlyArray<MethodBase>(new MethodBase[3] { AccessTools.DeclaredMethod(typeof(Player), "OnInventoryChanged", (Type[])null, (Type[])null), AccessTools.DeclaredMethod(typeof(Humanoid), "EquipItem", (Type[])null, (Type[])null), AccessTools.DeclaredMethod(typeof(Humanoid), "UnequipItem", (Type[])null, (Type[])null) }); } [UsedImplicitly] private static void Postfix(Humanoid __instance) { if ((Object)(object)Player.m_localPlayer == (Object)(object)__instance) { _isInventoryChanged = true; } } } private float _northAngle; private float _lookingAngle; private float _headingAngle; private CompassConstants.ViewMode _viewMode = SmallOrLarge; private static bool _isInventoryChanged = true; private double _lastInvLookup; private const double InvLookupFrequency = 0.5; private ItemData? _inventoryItem; private readonly GameObject _root; private readonly GameObject _needle; private readonly GameObject _center; private readonly GameObject _heading; private readonly GameObject _looking; private readonly GameObject _glass; private readonly GameObject _mask; private readonly GameObject _ship; private readonly GameObject _ring; private readonly Sprite _ringSun; private readonly Image _lookingImage; private readonly Image _ringImage; private readonly Image _shipIndicatorUnder; private readonly Image _shipIndicatorOver; private readonly Transform _windRing; private readonly Image _windIcon; private readonly Transform? _originalPinRootParent; private double _radarEmptyTimestamp; private bool _isRadarEmptyForDuration; private bool _isRadarExpanded; private bool _isRadarShrunk; private int _radarPinCount; private bool _isDarkMode; private const double MalfunctionCheckFrequency = 2.0; private double _lastMalfunctionCheckTime; private bool _isMalfunction; private double _malfunctionTime; private Coroutine? _malfunctionDelayCoroutine; private readonly Dictionary<Biome, EnvSetup[]?> _malfunctionConditions = new Dictionary<Biome, EnvSetup[]>(); public Vector3 North => new Vector3(0f, 0f, _northAngle); public Vector3 Looking => new Vector3(0f, 0f, _lookingAngle); public Vector3 Heading => new Vector3(0f, 0f, _headingAngle); internal Transform transform => _root.transform; private static Transform SmallMap => Minimap.instance.m_mapSmall.transform; private bool IsCompass { get { if (!_inventoryItem.IsCompass()) { return !Configs.CraftToUse.Value; } return true; } } private bool IsSunstone => _inventoryItem.IsSunstone(); private bool IsCompassMalfunction { get { if (IsCompass) { return _isMalfunction; } return false; } } private bool IsSunstoneMalfunction { get { if (IsSunstone) { return _isMalfunction; } return false; } } private static bool InDungeon => ((Character)Player.m_localPlayer).InInterior(); private static CompassConstants.ViewMode SmallOrLarge { get { if (!Configs.ShrinkWhenEmpty.Value) { return CompassConstants.ViewMode.Large; } return CompassConstants.ViewMode.Small; } } internal Compass() { //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: 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_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Expected O, but got Unknown //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0332: Unknown result type (might be due to invalid IL or missing references) //IL_033c: Unknown result type (might be due to invalid IL or missing references) Minimap instance = Minimap.instance; ((Component)instance.m_smallMarker).gameObject.SetActive(false); ((Component)instance.m_windMarker).gameObject.SetActive(false); ((Component)instance.m_biomeNameSmall).gameObject.SetActive(false); ((Behaviour)((Component)instance.m_smallShipMarker).GetComponent<Image>()).enabled = false; ((Component)instance.m_pinNameRootSmall).gameObject.SetActive(false); ((Component)instance.m_smallRoot.transform.Find("Key tip")).gameObject.SetActive(false); ((Behaviour)instance.m_mapSmall.GetComponent<RectMask2D>()).enabled = false; ((Behaviour)instance.m_smallRoot.GetComponent<Image>()).enabled = false; ((Behaviour)instance.m_mapImageSmall).enabled = false; instance.m_mapSmall.transform.localScale = Vector2.op_Implicit(Vector2.one * 1.4f); instance.m_mapSmall.transform.localPosition = Vector2.op_Implicit(CompassConstants.PositionInit); _root = new GameObject("ZenCompass_Root"); _root.transform.SetParent(SmallMap, false); _root.transform.SetAsFirstSibling(); _root.transform.localScale = Vector3.one * 2f; _ship = Object.Instantiate<GameObject>(((Component)Minimap.instance.m_smallShipMarker).gameObject, _root.transform); _ship.transform.localScale = Vector3.one * 2f; _ship.SetActive(true); _looking = LoadCompassImage("compass_looking.png", _root); _center = LoadCompassImage("compass_center.png", _root); _needle = LoadCompassImage("compass_needle.png", _root); _heading = LoadCompassImage("compass_heading.png", _root); _glass = LoadCompassImage("compass_glass.png", _root); _mask = LoadCompassImage("compass_mask.png", _root); _ring = LoadCompassImage("compass_ring.png", _root); _ringSun = AssetIO.LoadSpriteFromResource((BaseUnityPlugin)(object)ZenMod<Plugin>.Instance, "compass_ring_time.png"); _ringImage = _ring.GetComponent<Image>(); _lookingImage = _looking.GetComponent<Image>(); _mask.AddComponent<Mask>().showMaskGraphic = false; _originalPinRootParent = ((Transform)Minimap.instance.m_pinRootSmall).parent; ((Transform)Minimap.instance.m_pinRootSmall).SetParent(_mask.transform); _shipIndicatorUnder = _ship.GetComponent<Image>(); _shipIndicatorOver = ((Component)((Transform)Hud.instance.m_shipWindIndicatorRoot).Find("Ship")).gameObject.GetComponent<Image>(); _windRing = ((Transform)Hud.instance.m_shipWindIndicatorRoot).Find("Circle"); ((Component)_windRing).gameObject.SetActive(false); _windIcon = Hud.instance.m_shipWindIcon; ((Component)_windIcon).transform.localScale = Vector3.one / 2f; Hud.instance.m_shipHudRoot.transform.SetAsLastSibling(); Configs.MalfunctionConditions.SettingChanged += delegate { ParseMalfunctionConditions(); }; ParseMalfunctionConditions(); } public void Shutdown() { //IL_0023: 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) Logging<Plugin>.Info("Unloading", 0); if (Object.op_Implicit((Object)(object)Minimap.instance)) { _root.transform.localScale = Vector3.one * 2f; ((Component)Minimap.instance.m_pinRootSmall).gameObject.SetActive(true); ((Transform)Minimap.instance.m_pinRootSmall).SetParent(_originalPinRootParent); Object.Destroy((Object)(object)_root); } } internal void Update() { if (Object.op_Implicit((Object)(object)Player.m_localPlayer)) { bool flag = PlayerExt.IsShipCaptain(Player.m_localPlayer); bool flag2 = ((Character)Player.m_localPlayer).IsAttachedToShip(); bool flag3 = ((Character)Player.m_localPlayer).IsRiding(); InventoryCheck(); MalfunctionCheck(); UpdateRadar(); UpdateConfigScale(); CheckViewMode(flag || flag2 || flag3); UpdateViewScale(); UpdateRotation(flag); UpdateStatusEffectsPosition(); UpdateShipIndicator(flag); UpdateWindVisibility(flag); UpdateSunPosition(); } } private void InventoryCheck() { if ((Configs.CraftToUse.Value || Configs.EquipToUse.Value) && _isInventoryChanged && !(Time.timeAsDouble < _lastInvLookup + 0.5)) { _inventoryItem = CompassItem.FindNavItem(((Humanoid)Player.m_localPlayer).GetInventory()); _lastInvLookup = Time.timeAsDouble; _isInventoryChanged = false; } } private void MalfunctionCheck() { //IL_006b: 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_00b1: Unknown result type (might be due to invalid IL or missing references) //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_0194: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) bool flag = Player.m_localPlayer.m_teleporting || (double)Player.m_localPlayer.m_teleportCooldown < 2.0; if (Time.timeAsDouble < _lastMalfunctionCheckTime + 2.0 && !flag) { return; } _lastMalfunctionCheckTime = Time.timeAsDouble; Dictionary<Biome, EnvSetup[]?> conditions = _malfunctionConditions; Biome currentBiome = Player.m_localPlayer.GetCurrentBiome(); EnvSetup currentEnv = EnvMan.instance.GetCurrentEnvironment(); bool flag2 = conditions.Keys.Any((Biome biome) => ((Enum)biome).HasFlag((Enum)(object)currentBiome)); bool flag3 = CheckEnv((Biome)895) || CheckEnv(currentBiome); bool flag4 = Configs.MalfunctionEnabled.Value.AllowForItem(_inventoryItem); bool malfunction = flag4 && flag2 && flag3 && !((Character)Player.m_localPlayer).InGodMode(); bool flag5 = default(bool); InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(58, 6, ref flag5); if (flag5) { val.AppendLiteral("Malfunction? "); val.AppendFormatted<bool>(malfunction); val.AppendLiteral(", itemAllow? "); val.AppendFormatted<bool>(flag4); val.AppendLiteral(" Biome: "); val.AppendFormatted<Biome>(currentBiome); val.AppendLiteral(" Env: "); val.AppendFormatted(currentEnv.m_name); val.AppendLiteral(" InBiome: "); val.AppendFormatted<bool>(flag2); val.AppendLiteral(" InEnv: "); val.AppendFormatted<bool>(flag3); } Logging<Plugin>.Debug(val, 0); if (malfunction != _isMalfunction && _malfunctionDelayCoroutine == null) { _malfunctionDelayCoroutine = Timing.Delay((MonoBehaviour)(object)ZenMod<Plugin>.Instance, Configs.MalfunctionTransitionDelay.Value, (Action)delegate { _isMalfunction = malfunction; _malfunctionTime = (malfunction ? Time.timeAsDouble : 0.0); _malfunctionDelayCoroutine = null; }); } bool CheckEnv(Biome biome) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) if (conditions.TryGetValue(biome, out EnvSetup[] value)) { return value?.Any((EnvSetup env) => env.m_name == currentEnv?.m_name) ?? true; } return false; } } private void ParseMalfunctionConditions() { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: 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_00eb: Unknown result type (might be due to invalid IL or missing references) List<EnvSetup> environments = EnvMan.instance.m_environments; _malfunctionConditions.Clear(); foreach (var (text, text2) in IEnumerableExt.AsTuple<string, string>(Configs.MalfunctionConditions.Value.ToDictionary(':'))) { try { Biome key = (Biome)Enum.Parse(typeof(Biome), text); if (text2 == "All") { _malfunctionConditions[key] = null; continue; } string[] weatherNames = text2.Split(new char[1] { '|' }); if (!weatherNames.All((string w) => environments.Any((EnvSetup e) => e.m_name == w))) { throw new Exception("Invalid weather"); } _malfunctionConditions[key] = environments.FindAll((EnvSetup e) => weatherNames.Contains(e.m_name)).ToArray(); } catch (Exception ex) { Logging<Plugin>.Error((object)("Malformed config for malfunction condition: " + text + "=" + text2 + " " + ex.Message), (ushort)0); } } } private void CheckViewMode(bool isShipOrMount) { if (((Character)Player.m_localPlayer).IsDead()) { _viewMode = CompassConstants.ViewMode.None; return; } if (Configs.CraftToUse.Value && (_inventoryItem == null || (Configs.EquipToUse.Value && !_inventoryItem.IsEquipped()))) { _viewMode = CompassConstants.ViewMode.None; return; } if (InDungeon) { _viewMode = (Configs.AllowInDungeon.Value ? SmallOrLarge : CompassConstants.ViewMode.None); return; } if (Minimap.IsOpen()) { _viewMode = CompassConstants.ViewMode.Small; return; } int num = ((isShipOrMount && Plugin.IsZenMapLoaded) ? 1 : 0); if (_radarPinCount <= num) { if (_isRadarEmptyForDuration) { if (Time.timeAsDouble - _radarEmptyTimestamp > 5.0) { _viewMode = SmallOrLarge; } } else { _isRadarEmptyForDuration = true; _radarEmptyTimestamp = Time.timeAsDouble; } } else { _isRadarEmptyForDuration = false; _viewMode = CompassConstants.ViewMode.Large; } } private void UpdateRotation(bool isShipCaptain) { //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0176: 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_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) CompassConstants.Orientation orientation3; if (Configs.CraftToUse.Value) { CompassConstants.Orientation orientation = (Configs.Rotating.Value.AllowCompass() ? CompassConstants.Orientation.Rotating : CompassConstants.Orientation.Fixed); CompassConstants.Orientation orientation2 = (Configs.Rotating.Value.AllowSunstone() ? CompassConstants.Orientation.Rotating : CompassConstants.Orientation.Fixed); orientation3 = (_inventoryItem.IsCompass() ? orientation : orientation2); } else { orientation3 = (Configs.Rotating.Value.AllowCompass() ? CompassConstants.Orientation.Rotating : CompassConstants.Orientation.Fixed); } Minimap instance = Minimap.instance; instance.m_minZoom = 0.005f * (float)Configs.RadarRangePercent.Value / 100f; instance.m_smallZoom = Minimap.instance.m_minZoom; Quaternion rotation = ((Component)Camera.current).transform.rotation; Vector3 eulerAngles = ((Quaternion)(ref rotation)).eulerAngles; rotation = ((Component)Player.m_localPlayer).transform.rotation; Vector3 eulerAngles2 = ((Quaternion)(ref rotation)).eulerAngles; switch (isShipCaptain ? CompassConstants.Orientation.Rotating : orientation3) { case CompassConstants.Orientation.Fixed: _northAngle = 0f; _lookingAngle = 0f - eulerAngles.y; _headingAngle = 0f - eulerAngles2.y; break; case CompassConstants.Orientation.Rotating: _northAngle = eulerAngles.y; _lookingAngle = 0f; _headingAngle = eulerAngles.y - eulerAngles2.y; break; default: throw new ArgumentOutOfRangeException("orientation", orientation3, "Orientation unknown"); } SmallMap.eulerAngles = North; _looking.transform.eulerAngles = Looking; _ship.transform.eulerAngles = Heading; if (!_isMalfunction) { _needle.transform.eulerAngles = North; _heading.transform.eulerAngles = Heading; return; } float num = (float)(Time.timeAsDouble - _malfunctionTime); float num2 = _northAngle - Mathf.Sin(num * 0.25f) * 360f; float num3 = _headingAngle - Mathf.Sin(num * -0.5f) * 360f; _needle.transform.eulerAngles = new Vector3(0f, 0f, num2); _heading.transform.eulerAngles = new Vector3(0f, 0f, num3); } private void UpdateSunPosition() { //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0173: 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) bool flag = EnvMan.IsDaylight(); bool flag2 = ((Character)Player.m_localPlayer).InInterior(); bool flag3 = Configs.TrackSun.Value.AllowForItem(_inventoryItem) && !flag2; if (flag3) { if (EnvMan.IsNight()) { flag3 = Configs.TrackSunAtNight.Value.AllowForItem(_inventoryItem); } else if (!flag) { flag3 = Configs.TrackSunInDarkEnv.Value.AllowForItem(_inventoryItem); } } if (flag3) { _ringImage.overrideSprite = _ringSun; float num = EnvMan.instance.GetDayFraction() * -360f; if (Configs.RotatingSunRingIsTime.Value.AllowForItem(_inventoryItem)) { num -= _ring.transform.parent.eulerAngles.z; } else if (_isMalfunction) { num -= (float)(Math.Sin((Time.timeAsDouble - _malfunctionTime) * 0.04) * 180.0); } _ring.transform.localEulerAngles = new Vector3(0f, 0f, num); } else { _ringImage.overrideSprite = null; } if (_isDarkMode && flag && !flag2) { Color white = Color.white; AdjustAmbiance(white); _isDarkMode = false; } if ((!_isDarkMode && !flag) || flag2) { Color32 val = default(Color32); ((Color32)(ref val))..ctor((byte)0, (byte)127, byte.MaxValue, byte.MaxValue); AdjustAmbiance(Color32.op_Implicit(val)); _isDarkMode = true; } void AdjustAmbiance(Color targetColor) { //IL_001c: 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) Logging<Plugin>.Info("Adjusting ambiance", 0); float transitionDuration = EnvMan.instance.m_transitionDuration; ((Graphic)_ringImage).CrossFadeColor(targetColor, transitionDuration, false, false); ((Graphic)_lookingImage).CrossFadeColor(targetColor, transitionDuration, false, false); } } private void UpdateWindVisibility(bool isShipCaptain) { bool flag = Configs.TrackWind.Value.AllowForItem(_inventoryItem); bool enabled = isShipCaptain || (flag && _viewMode != 0 && !InDungeon && !IsCompassMalfunction); ((Behaviour)_windIcon).enabled = enabled; ((Component)_windRing).gameObject.SetActive(isShipCaptain); _ring.gameObject.SetActive(!isShipCaptain); } private void UpdateStatusEffectsPosition() { //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_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0050: 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) if (Configs.RepositionStatusEffects.Value) { float num = 84f * UI.ScaleFactor; float num2 = 70f * UI.ScaleFactor; Transform val = _root.transform; RectTransform statusEffectListRoot = Hud.instance.m_statusEffectListRoot; Vector3 position = ((Transform)statusEffectListRoot).position; position.x = val.position.x - val.localScale.x * num - num2; ((Transform)statusEffectListRoot).position = position; } } private void UpdateShipIndicator(bool isShipCaptain) { ((Behaviour)_shipIndicatorOver).enabled = isShipCaptain && _viewMode == CompassConstants.ViewMode.None; ((Behaviour)_shipIndicatorUnder).enabled = isShipCaptain && !((Behaviour)_shipIndicatorOver).enabled; Hud.instance.m_shipControlsRoot.SetActive(isShipCaptain); } private void UpdateRadar() { //IL_0052: 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_0058: 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_006c: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_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) //IL_0081: Unknown result type (might be due to invalid IL or missing references) RectTransform pinRootSmall = Minimap.instance.m_pinRootSmall; bool flag = Configs.RadarRangePercent.Value > 0 && !_isMalfunction && !InDungeon; _radarPinCount = 0; ((Component)pinRootSmall).gameObject.SetActive(flag); if (!flag) { return; } foreach (Transform item in (Transform)pinRootSmall) { item.localScale = Vector3.one * 1f; item.rotation = Quaternion.identity; Vector2 val2 = Vector2.op_Implicit(item.localPosition); if (((Vector2)(ref val2)).magnitude < 84f) { _radarPinCount++; } } } private static void UpdateConfigScale() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0037: 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_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) Minimap.instance.m_smallRoot.transform.localScale = Vector3.one * Configs.DisplayScale.Value; Hud.instance.m_shipHudRoot.transform.localScale = Vector3.one * Configs.DisplayScale.Value; Hud.instance.m_shipControlsRoot.transform.localScale = Vector3.one / Configs.DisplayScale.Value; } private void UpdateViewScale() { switch (_viewMode) { case CompassConstants.ViewMode.None: ShrinkCompass(1f); SetVisible(isVisible: false); break; case CompassConstants.ViewMode.Small: ShrinkCompass(1f); SetVisible(isVisible: true); break; case CompassConstants.ViewMode.Large: ExpandCompass(2f); SetVisible(isVisible: true); break; default: throw new ArgumentOutOfRangeException("_viewMode", _viewMode, "ViewMode Unknown"); } } private void ShrinkCompass(float scale) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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_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_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_0060: 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_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) Vector3 localScale = _root.transform.localScale; _isRadarShrunk = localScale.x <= scale + 0.005f; if (!_isRadarShrunk) { SmallMap.localPosition = SmallMap.localPosition.SmoothMove(Vector2.op_Implicit(CompassConstants.PositionShrink)); _root.transform.localScale = localScale.SmoothScale(scale); Transform obj = ((Component)_windIcon).transform; obj.localScale = obj.localScale.SmoothScale(scale - 0.3f); } } private void ExpandCompass(float scale) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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_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_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_0060: 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_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) Vector3 localScale = _root.transform.localScale; _isRadarExpanded = localScale.x >= scale - 0.005f; if (!_isRadarExpanded) { SmallMap.localPosition = SmallMap.localPosition.SmoothMove(Vector2.op_Implicit(CompassConstants.PositionInit)); _root.transform.localScale = localScale.SmoothScale(scale); Transform obj = ((Component)_windIcon).transform; obj.localScale = obj.localScale.SmoothScale(1f / scale); } } private void SetVisible(bool isVisible) { Minimap.instance.m_smallRoot.SetActive(isVisible); if (isVisible) { AdjustParts(); } void AdjustParts() { _heading.SetActive(Configs.ShowHeading.Value.AllowForItem(_inventoryItem)); _needle.SetActive(IsCompass && Configs.ShowNorthArrow.Value); bool flag = Configs.ShowCameraDir.Value.AllowForItem(_inventoryItem); _looking.SetActive(flag && !IsCompassMalfunction); } } private static GameObject LoadCompassImage(string resourceName, GameObject parent) { //IL_0010: 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_0027: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown GameObject val = new GameObject(resourceName.Replace(".png", "")); val.transform.SetParent(parent.transform, false); val.AddComponent<Image>().sprite = AssetIO.LoadSpriteFromResource((BaseUnityPlugin)(object)ZenMod<Plugin>.Instance, resourceName); return val; } } internal static class CompassConstants { internal enum ViewMode { None, Small, Large } internal enum Orientation { Fixed, Rotating } internal const float AnimTime = 0.05f; internal const float AnimErrMargin = 0.005f; internal const float ShrinkScale = 1f; internal const double ShrinkDelayWhenEmpty = 5.0; internal static readonly Vector2 PositionInit = Vector2.one * -138.59999f; internal static readonly Vector2 PositionShrink = PositionInit * 0.39999998f; private const float Margin = 15f; internal const float StatusEffectHudOffset = 70f; internal const float RenderScale = 1.4f; internal const float CompassScale = 2f; internal const float PinScale = 1f; internal const float RadarRange = 0.005f; internal const float ScanRadius = 84f; } internal static class CompassItem { public const string PrefabNameCompass = "ZenCompass"; public const string PrefabNameSunstone = "ZenSunstone"; private static GameObject? _prefabCompass; private static GameObject? _prefabSunstone; private const string ItemAttachName = "compass"; private static GameObject PrefabCompass { get { if (!Object.op_Implicit((Object)(object)_prefabCompass)) { return _prefabCompass = GlobalStatic.GetPrefab("ZenCompass", false); } return _prefabCompass; } } private static GameObject PrefabSunstone { get { if (!Object.op_Implicit((Object)(object)_prefabSunstone)) { return _prefabSunstone = GlobalStatic.GetPrefab("ZenSunstone", false); } return _prefabSunstone; } } [Obsolete("Instead use IsEquipped() in Zen.ModLib v1.10.13 or higher")] internal static bool IsEquipped(this ItemData? item) { return item?.m_equipped ?? false; } public static bool IsCompass(this ItemData? item) { return (Object)(object)((item != null) ? ItemDataExt.GetPrefab(item) : null) == (Object)(object)PrefabCompass; } public static bool IsSunstone(this ItemData? item) { return (Object)(object)((item != null) ? ItemDataExt.GetPrefab(item) : null) == (Object)(object)PrefabSunstone; } public static bool IsNavItem(this ItemData? item) { if (item == null) { return false; } GameObject prefab = ItemDataExt.GetPrefab(item); if (!((Object)(object)prefab == (Object)(object)PrefabCompass)) { return (Object)(object)prefab == (Object)(object)PrefabSunstone; } return true; } internal static Action AddCraftingItems() { //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) Sprite val = AssetIO.LoadSpriteFromResource((BaseUnityPlugin)(object)ZenMod<Plugin>.Instance, "compass_icon2.png"); Sprite icon = ItemDataExt.GetIcon(GlobalStatic.GetPrefab<ItemDrop>("FlametalOre", false)); CustomItem craftingItem; CustomItem craftingItem2; List<Action> configSync = new List<Action> { AddCraftingItem("ZenCompass", "ShieldFlametal", val, "$item_compass", "$item_compass_description", 0.3f, Configs.CraftingStationCompass, Configs.CraftingStationLevelCompass, Configs.CraftingMaterialsCompass, Configs.CraftingEnabledCompass, out craftingItem), AddCraftingItem("ZenSunstone", "FlametalOre", icon, "$item_sunstone", "$item_sunstone_description", 0.3f, Configs.CraftingStationSunstone, Configs.CraftingStationLevelSunstone, Configs.CraftingMaterialsSunstone, Configs.CraftingEnabledSunstone, out craftingItem2) }; CustomItemExt.ApplyTextureToPrefab(craftingItem, val.texture, 0.25f, Vector2.one * 2f, new Vector2(0.1f, -0.85f), "compass", true, (Color?)null); InitPrefabItem(craftingItem2, 0.25f); return delegate { CollectionExtensions.Do<Action>((IEnumerable<Action>)configSync, (Action<Action>)delegate(Action sync) { sync(); }); }; } private static void InitPrefabItem(CustomItem item, float scale3D) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) ((Object)item.ItemPrefab.transform.GetChild(0)).name = "compass"; Transform transform = ((Component)item.ItemPrefab.GetComponentInChildren<MeshRenderer>()).transform; transform.localScale *= scale3D; SharedData shared = item.ItemDrop.m_itemData.m_shared; shared.m_movementModifier = 0f; shared.m_useDurability = false; shared.m_canBeReparied = false; shared.m_maxQuality = 1; shared.m_value = 0; } private static Action AddCraftingItem(string prefabName, string basePrefabName, Sprite? icon, string label, string description, float weight, ConfigEntry<string> station, ConfigEntry<int> stationLevel, ConfigEntry<StringList> materials, ConfigEntry<bool> isEnabled, out CustomItem craftingItem) { //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_0074: 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_008f: Expected O, but got Unknown //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Expected O, but got Unknown ConfigEntry<bool> isEnabled2 = isEnabled; string prefabName2 = prefabName; string basePrefabName2 = basePrefabName; ConfigEntry<string> station2 = station; ConfigEntry<int> stationLevel2 = stationLevel; ConfigEntry<StringList> materials2 = materials; bool flag = default(bool); InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(30, 2, ref flag); if (flag) { val.AppendLiteral("Add crafting item: "); val.AppendFormatted(prefabName2); val.AppendLiteral(", based on "); val.AppendFormatted(basePrefabName2); } Logging<Plugin>.Info(val, 0); string text = prefabName2; string text2 = basePrefabName2; ItemConfig val2 = new ItemConfig(); val2.Name = label; val2.Description = description; val2.CraftingStation = station2.Value; val2.MinStationLevel = stationLevel2.Value; val2.Requirements = materials2.Value.ToRequirementConfigs(':'); val2.Icons = (Sprite[])(object)((!Object.op_Implicit((Object)(object)icon)) ? null : new Sprite[1] { icon }); val2.StackSize = 1; val2.Weight = weight; craftingItem = new CustomItem(text, text2, val2); SharedData shared = craftingItem.ItemDrop.m_itemData.m_shared; SetPrefabItemType(shared); ItemManager.Instance.AddItem(craftingItem); shared.m_variants = 0; shared.m_teleportable = true; CustomRecipe customRecipe = craftingItem.Recipe; return ConfigSync; void ConfigSync() { //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: 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) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) SetPrefabItemType(shared); bool flag2 = default(bool); if (Configs.CraftToUse.Value && isEnabled2.Value) { InterpolatedString<Plugin> val3 = new InterpolatedString<Plugin>(26, 2, ref flag2); if (flag2) { val3.AppendLiteral("Update recipe: "); val3.AppendFormatted(prefabName2); val3.AppendLiteral(", based on "); val3.AppendFormatted(basePrefabName2); } Logging<Plugin>.Info(val3, 0); Recipe recipe = customRecipe.Recipe; recipe.m_craftingStation = PrefabManagerExt.GetCraftingStation(PrefabManager.Instance, station2.Value); recipe.m_minStationLevel = stationLevel2.Value; recipe.m_resources = materials2.Value.ToRequirements(':'); } else { InterpolatedString<Plugin> val3 = new InterpolatedString<Plugin>(15, 1, ref flag2); if (flag2) { val3.AppendLiteral("Remove recipe: "); val3.AppendFormatted(prefabName2); } Logging<Plugin>.Info(val3, 0); ItemManager.Instance.RemoveRecipe(customRecipe); } } } private static void SetPrefabItemType(SharedData shared) { //IL_003a: 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) if (Configs.CraftToUse.Value && Configs.EquipToUse.Value) { shared.m_equipDuration = 1f; shared.m_itemType = (ItemType)18; } else { shared.m_equipDuration = 0f; shared.m_itemType = (ItemType)16; } } public static ItemData? FindNavItem(Inventory inventory) { //IL_0079: 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_00ac: Unknown result type (might be due to invalid IL or missing references) Logging<Plugin>.Info("Scan inventory for navigation item", 0); bool value = Configs.EquipToUse.Value; ItemData val = null; foreach (ItemData allItem in inventory.GetAllItems()) { if (allItem.IsNavItem()) { if (val == null || (allItem.IsCompass() && (!value || !val.m_equipped))) { val = allItem; } if (value && allItem.m_equipped) { val = allItem; } } } bool flag = default(bool); InterpolatedString<Plugin> val2 = new InterpolatedString<Plugin>(17, 1, ref flag); if (flag) { val2.AppendLiteral("Navigation item: "); val2.AppendFormatted(((val != null) ? ItemDataExt.GetName(val) : null) ?? "(None)"); } Logging<Plugin>.Info(val2, 0); return val; } } internal static class Configs { [Flags] public enum NavTool { None = 0, Compass = 1, Sunstone = 2 } internal enum DeathRule { Tombstone, Keep, Destroy } public static readonly ConfigEntry<float> DisplayScale; public static readonly ConfigEntry<bool> ShowNorthArrow; public static readonly ConfigEntry<NavTool> ShowCameraDir; public static readonly ConfigEntry<NavTool> ShowHeading; public static readonly ConfigEntry<NavTool> Rotating; public static readonly ConfigEntry<NavTool> RotatingSunRingIsTime; public static readonly ConfigEntry<NavTool> TrackSun; public static readonly ConfigEntry<NavTool> TrackWind; public static readonly ConfigEntry<bool> ShrinkWhenEmpty; public static readonly ConfigEntry<int> RadarRangePercent; public static readonly ConfigEntry<bool> AllowInDungeon; public static readonly ConfigEntry<StringList> MalfunctionConditions; public static readonly ConfigEntry<float> MalfunctionTransitionDelay; public static readonly ConfigEntry<NavTool> TrackSunAtNight; public static readonly ConfigEntry<NavTool> TrackSunInDarkEnv; public static readonly ConfigEntry<NavTool> MalfunctionEnabled; public static readonly ConfigEntry<bool> CraftToUse; public static readonly ConfigEntry<bool> EquipToUse; public static readonly ConfigEntry<bool> CraftingEnabledCompass; public static readonly ConfigEntry<string> CraftingStationCompass; public static readonly ConfigEntry<int> CraftingStationLevelCompass; public static readonly ConfigEntry<StringList> CraftingMaterialsCompass; public static readonly ConfigEntry<bool> CraftingEnabledSunstone; public static readonly ConfigEntry<string> CraftingStationSunstone; public static readonly ConfigEntry<int> CraftingStationLevelSunstone; public static readonly ConfigEntry<StringList> CraftingMaterialsSunstone; public static readonly ConfigEntry<DeathRule> PlayerDeath; public static readonly ConfigEntry<bool> AutoRemoveDeathPin; public static readonly ConfigEntry<KeyCode> ForceRemoveDeathPinKey; public static readonly ConfigEntry<bool> RepositionStatusEffects; public static readonly ConfigEntry<bool> RepositionShipPowerIndicator; public static bool IsNone(this NavTool self) { return self == NavTool.None; } public static bool AllowCompass(this NavTool self) { return (self & NavTool.Compass) == NavTool.Compass; } public static bool AllowSunstone(this NavTool self) { return (self & NavTool.Sunstone) == NavTool.Sunstone; } public static bool AllowForItem(this NavTool self, ItemData? item) { if (!CraftToUse.Value) { return self.AllowCompass(); } if (!item.IsCompass()) { return self.AllowSunstone(); } return self.AllowCompass(); } static Configs() { //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Expected O, but got Unknown //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Expected O, but got Unknown //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Expected O, but got Unknown //IL_0204: Expected O, but got Unknown //IL_0375: Unknown result type (might be due to invalid IL or missing references) //IL_037a: Unknown result type (might be due to invalid IL or missing references) //IL_0385: Expected O, but got Unknown //IL_0385: Unknown result type (might be due to invalid IL or missing references) //IL_0390: Expected O, but got Unknown //IL_0390: Unknown result type (might be due to invalid IL or missing references) //IL_039b: Expected O, but got Unknown //IL_039b: Unknown result type (might be due to invalid IL or missing references) //IL_03a6: Expected O, but got Unknown //IL_03b0: Expected O, but got Unknown //IL_0421: Unknown result type (might be due to invalid IL or missing references) //IL_0426: Unknown result type (might be due to invalid IL or missing references) //IL_0431: Expected O, but got Unknown //IL_043b: Expected O, but got Unknown DisplayScale = Config.Define<float>(false, "Appearance", "Display Scale", 1f, Config.AcceptRange<float>(0.5f, 2f), "Adjust the display scale of the compass. It has two display modes: Small and Large.\r\nIt will be small while there are no pins on the radar and large when there are pins.\r\nSet your scale preference with both scenarios in mind.\r\nAlso this compounds with the vanilla GUI scaling options found in the Settings."); ShowHeading = Config.Define<NavTool>(true, "Appearance", "Show Heading", NavTool.Compass, "Show the player's facing direction (gear-arrow)."); ShowNorthArrow = Config.Define<bool>(true, "Appearance", "Show North Arrow", true, "Show the north/south arrow on the compass."); ShowCameraDir = Config.Define<NavTool>(true, "Appearance", "Show Camera Direction", NavTool.Compass | NavTool.Sunstone, "Show the camera's looking direction."); TrackSun = Config.Define<NavTool>(true, "Appearance", "Track Sun", NavTool.Compass | NavTool.Sunstone, "Track the sun with an indicator icon along the outer ring.\r\nThe sun moves from east to west through the southern sky."); TrackWind = Config.Define<NavTool>(true, "Appearance", "Track Wind", NavTool.Compass | NavTool.Sunstone, "Track the wind direction with an indicator on the outer ring."); Rotating = Config.Define<NavTool>(true, "Appearance", "Rotating", NavTool.Sunstone, "Oriented such that up is always the direction you are looking.\r\n[Disabling this on the sunstone makes the sunstone behave like a compass since it's locked to the north/south orientaiton.\r\nThis option is only here for completeness, it is not recommended to disable it for sunstone]"); RotatingSunRingIsTime = Config.Define<NavTool>(true, "Appearance", "Rotating - Sun Ring Is Time", NavTool.Compass, "The sun ring moves idependently along the outer ring, ignoring axis rotation. Right is sunrise, left is sunset.\r\n[This option has no effect if " + ((ConfigEntryBase)Rotating).Definition.Key + " is disabled]"); ShrinkWhenEmpty = Config.Define<bool>(false, "Behavior", "Shrink When Empty", true, "Auto shrink the radar when there are no pins nearby."); RadarRangePercent = Config.Define<int>(true, "Behavior", "Radar Range Percent", 100, Config.AcceptRange<int>(0, 300), "How far to scan for pins, as percentage. Set to 0 to disable the radar function."); AllowInDungeon = Config.Define<bool>(true, "Behavior", "Allow In Dungeon", false, "Can be used inside dungeons."); string text = GeneralExtensions.Join<Biome>(Enum.GetValues(typeof(Biome)).Cast<Biome>().Except(new <>z__ReadOnlySingleElementList<Biome>((Biome)0)), (Func<Biome, string>)null, ", "); StringList val = new StringList(); ((List<string>)val).Add("All:" + Weather.MountainBlizzard); ((List<string>)val).Add($"{(object)(Biome)512}:All"); ((List<string>)val).Add($"{(object)(Biome)256}:{Weather.ThunderStorm}|{Weather.ClearThunderStorm}"); MalfunctionConditions = Config.Define<StringList>(true, "Behavior", "Malfunction Conditions", val, "List of Biome:Weather conditions that cause the compass to malfunction.\r\nLeave blank to disable the malfunction conditions.\r\nUse the keyword 'All' to apply to all biomes or weathers.\r\nOnly one biome per entry, but a given biome can have multiple weathers.\r\nUse | to separate multiple weathers, example:\r\nBiome:Weather1|Weather2|Weather3|...\r\nPossible biomes: [" + text + "]\r\nPossible weather: https://valheim.fandom.com/wiki/Environment#Weather"); MalfunctionTransitionDelay = Config.Define<float>(true, "Behavior", "Malfunction Transition Delay", 15f, Config.AcceptRange<float>(0f, 60f), "How many seconds to wait before transitioning to/from malfunction state once a condition is met.\r\nSet to 0 to for instant change.\r\nWhen entering a biome or a weather condition it can be helpful to wait a few seconds before malfunctioning\r\nThat way the environment can fully transition before the compass gives out. \r\nAlso it helps when on a biome line so it doesn't keep switching between malfunction and normal states."); MalfunctionEnabled = Config.Define<NavTool>(true, "Behavior", "Malfunction", NavTool.Compass | NavTool.Sunstone, "Malfunctions can happen in certain environmental conditions.\r\n[Changing this config value will not update instantly. " + ((ConfigEntryBase)MalfunctionTransitionDelay).Definition.Key + " time must expire first]"); TrackSunInDarkEnv = Config.Define<NavTool>(true, "Behavior", "Track Sun In Dark Env", NavTool.Compass | NavTool.Sunstone, "Sun position is tracked in dark environments such as poor weather or foggy atmosphere. "); TrackSunAtNight = Config.Define<NavTool>(true, "Behavior", "Track Sun At Night", NavTool.Compass, "The sun position is tracked at night.\r\n[This overrides " + ((ConfigEntryBase)TrackSunInDarkEnv).Definition.Key + ": Even if you can track the sun in poor weather, you can't track it at night.]"); CraftToUse = Config.Define<bool>(true, "Crafting", "Craft To Use", true, "The item must be in your inventory before it can be used.\r\n[Disable to make the compass always available; no crafting required]"); EquipToUse = Config.Define<bool>(true, "Crafting", "Equip To Use", true, "The item must be equipped before it can be used.\r\n[" + ((ConfigEntryBase)CraftToUse).Definition.Key + " must be true for this to have any effect]\r\n[logout required for changes to take effect]"); CraftingEnabledCompass = Config.Define<bool>(true, "Crafting", "Item Compass - Enabled", true, "The compass provides cardinal directions in the day or night. \r\nAdditionally it can be used to tell the time of day and track wind direction.\r\n[restart required for changes to take effect]"); CraftingStationCompass = Config.Define<string>(true, "Crafting", "Item Compass - Station", "ArtisanTable", CraftingStations.GetAcceptableValueList(), "The station required to craft the compass.\r\nNOTE: For an easier game you can change this to a level 5 Workbench\r\nThereby requiring Obsidian from the mountains, but no need to kill the Dragon or Bonemass.\r\nThe idea is to pair this mod with ZenMap and experience the first portion of the game with no compass.\r\n[restart required for changes to take effect]"); CraftingStationLevelCompass = Config.Define<int>(true, "Crafting", "Item Compass - Station Level", 1, Config.AcceptRange<int>(1, 5), "The station level required to craft the compass.\r\nNote: The Sunstone is available at an earlier stage of progression.\r\n[restart required for changes to take effect]"); StringList val2 = new StringList(); ((List<string>)val2).Add("ZenSunstone:1"); ((List<string>)val2).Add("FineWood:4"); ((List<string>)val2).Add("Crystal:2"); ((List<string>)val2).Add("IronNails:1"); CraftingMaterialsCompass = Config.Define<StringList>(true, "Crafting", "Item Compass - Materials", val2, "The materials required to craft the compass, an advanced navigation aid.\r\nThe idea is to pair this mod with ZenMap and experience the first portion of the game with no compass.\r\nFor an easier game: \r\n- Adjust the crafting station requirements.\r\n- Change the Iron Nail requirement to a Bronze Nail.\r\n- Remove the Crystal requirement and change it to BoneFragments:4\r\n[restart required for changes to take effect]"); CraftingEnabledSunstone = Config.Define<bool>(true, "Crafting", "Item Sunstone - Enabled", true, "A basic navigation aid. The Sunstone allows you to track the sun's position.\r\n[restart required for changes to take effect]"); CraftingStationSunstone = Config.Define<string>(true, "Crafting", "Item Sunstone - Station", "Stonecutter", CraftingStations.GetAcceptableValueList(), "The station required to craft the sunstone.\r\n[restart required for changes to take effect]"); CraftingStationLevelSunstone = Config.Define<int>(true, "Crafting", "Item Sunstone - Station Level", 1, Config.AcceptRange<int>(1, 5), "The station level required to craft the sunstone.\r\n[restart required for changes to take effect]"); StringList val3 = new StringList(); ((List<string>)val3).Add("Ruby:1"); CraftingMaterialsSunstone = Config.Define<StringList>(true, "Crafting", "Item Sunstone - Materials", val3, "The materials required to craft the sunstone.\r\n[restart required for changes to take effect]"); PlayerDeath = Config.Define<DeathRule>(true, "Crafting", "Player Death", DeathRule.Tombstone, "What happens to the crafted item when the player dies?"); AutoRemoveDeathPin = Config.Define<bool>(true, "Death Pins", "Auto Remove Death Pin", true, "Death pins will be automatically removed from the map & compass after looting the tombstone"); ForceRemoveDeathPinKey = Config.Define<KeyCode>(false, "Death Pins", "Key - Force Remove Death Pin", (KeyCode)127, "Normally you don't need this key. However, if you were away and someone looted your tombstone\r\nwhile your character was not there then it is possible that your Death Pin would persist even\r\nthough the tombstone was gone. In that scenario you can stand near your pin and press this key\r\nto manually cleanup your map & compass.\r\nNOTE: The ZenMap mod automatically tracks and removes death pins reliably 100% of the time\r\neven if you are far away or offline and someone else loots your tombstone it will still work."); RepositionStatusEffects = Config.Define<bool>(true, "Compatibility", "Resposition Status Effects", true, "Reposition the Status Effect icons to make room for the compass.\r\nDisable this for compatibility with other mods which reposition the Status Effects."); RepositionShipPowerIndicator = Config.Define<bool>(true, "Compatibility", "Reposition Ship Power Indicator", true, "Reposition ship power indicator HUD element (sails / rudder power)\r\nThis mod will by default position it just to the right of the wheel for easy viewing\r\nDisable this for compatibility with other mods which reposition the ship power HUD element"); } } [HarmonyPatch] internal static class DeathPinPatch { [HarmonyPatch(typeof(Player), "OnDeath")] private static class PlayerOnDeath { private static bool _isInvEmpty; [UsedImplicitly] private static void Prefix(Player __instance) { _isInvEmpty = ((Humanoid)__instance).GetInventory().NrOfItems() == 0; } [UsedImplicitly] private static void Postfix(Player __instance) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) if (_isInvEmpty) { RemoveDeathPinAt(((Component)__instance).transform.position); } } } private static void RemoveDeathPin(TombStone tombstone) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) RemoveDeathPinAt(((Component)tombstone).transform.position); } private static void RemoveDeathPinAt(Vector3 worldPosition, float radius = 5f) { //IL_0025: 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_0042: 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_003c: 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_0061: Invalid comparison between Unknown and I4 //IL_0073: 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_0090: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) if (!Configs.AutoRemoveDeathPin.Value) { return; } if (Plugin.IsZenMapLoaded) { Logging<Plugin>.Info("ZenMap is handling death pin cleanup", 0); return; } bool flag = default(bool); InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(29, 1, ref flag); if (flag) { val.AppendLiteral("Looking death pins on map at "); val.AppendFormatted<Vector3>(worldPosition); } Logging<Plugin>.Info(val, 0); PinData closestPin = Minimap.instance.GetClosestPin(worldPosition, radius, false); if (closestPin != null && (int)closestPin.m_type == 4) { Minimap.instance.RemovePin(closestPin); val = new InterpolatedString<Plugin>(25, 1, ref flag); if (flag) { val.AppendLiteral("Pin found and removed at "); val.AppendFormatted<Vector3>(worldPosition); } Logging<Plugin>.Info(val, 0); } else { Logging<Plugin>.Info("Pin not found.", 0); } } internal static void CheckForceRemoveButtonPress() { //IL_0012: 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) if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && ZInput.GetKeyDown(Configs.ForceRemoveDeathPinKey.Value, true)) { RemoveDeathPinAt(((Component)Player.m_localPlayer).transform.position); } } [HarmonyTranspiler] [HarmonyPatch(typeof(TombStone), "UpdateDespawn")] private static IEnumerable<CodeInstruction> TombStone_UpdateDespawn(IEnumerable<CodeInstruction> codes) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown //IL_0046: Unknown result type (might be due to invalid IL or missing references) Action<TombStone> action = RemoveDeathPin; CodeInstruction[] array = (CodeInstruction[])(object)new CodeInstruction[2] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Call, (object)action.Method) }; return new CodeMatcher(codes, (ILGenerator)null).End().Insert(array).InstructionEnumeration(); } } internal static class Extensions { internal static float Yaw(this Vector3 v) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return Utils.YawFromDirection(v); } public static Vector3 SmoothScale(this Vector3 v, float scale) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: 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_000c: Unknown result type (might be due to invalid IL or missing references) return v.SmoothMove(Vector3.one * scale); } public static Vector3 SmoothMove(this Vector3 orig, Vector3 target) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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_000f: Unknown result type (might be due to invalid IL or missing references) Vector3 zero = Vector3.zero; return Vector3.SmoothDamp(orig, target, ref zero, 0.05f); } } [HarmonyPatch] internal class Patches { [HarmonyPatch(typeof(Minimap), "SetMapMode")] private static class Minimap_SetMapMode { [UsedImplicitly] private static void Prefix(Minimap __instance, ref MapMode mode) { if (Game.m_noMap && (int)mode == 0) { mode = (MapMode)1; } } [UsedImplicitly] private static void Postfix(Minimap __instance, MapMode mode) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 //IL_000d: Unknown result type (might be due to invalid IL or missing references) if (Game.m_noMap && (int)mode == 1) { __instance.m_mode = (MapMode)0; } } } [HarmonyPatch(typeof(Minimap), "CenterMap")] private static class Minimap_CenterMap { [UsedImplicitly] private static void Prefix(Minimap __instance) { //IL_0008: 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) if (Game.m_noMap && (int)__instance.m_mode == 0) { __instance.m_mode = (MapMode)1; } } [UsedImplicitly] private static void Postfix(Minimap __instance) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 //IL_0012: Unknown result type (might be due to invalid IL or missing references) if (Game.m_noMap && (int)__instance.m_mode == 1) { __instance.m_mode = (MapMode)0; } } } [HarmonyPostfix] [HarmonyPatch(typeof(Hud), "UpdateShipHud")] [HarmonyPriority(100)] private static void Hud_UpdateShipHud(Hud __instance) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_003a: 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_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: 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_00f0: 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_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Invalid comparison between Unknown and I4 //IL_00be: Unknown result type (might be due to invalid IL or missing references) bool activeSelf = __instance.m_shipHudRoot.activeSelf; Compass compass = Plugin.Compass; if (compass != null) { ((Transform)__instance.m_shipWindIndicatorRoot).position = compass.transform.position; ((Transform)__instance.m_shipWindIndicatorRoot).localScale = compass.transform.localScale; Transform parent = __instance.m_rudder.transform.parent; ((Component)parent).gameObject.SetActive(activeSelf); if (Configs.RepositionShipPowerIndicator.Value) { Vector3 val = 74f * UI.ScaleFactor * Vector3.right; Transform transform = ((Component)__instance.m_shipRudderIndicator).transform; parent.position = transform.position + val; } if (activeSelf) { bool flag = (int)Minimap.instance.m_mode == 2; ((Transform)__instance.m_shipWindIndicatorRoot).eulerAngles = compass.Heading; __instance.m_shipControlsRoot.SetActive(!flag); ((Component)parent).gameObject.SetActive(!flag); } else { ((Transform)__instance.m_shipWindIndicatorRoot).eulerAngles = compass.North; ((Transform)__instance.m_shipWindIconRoot).localEulerAngles = Vector3.forward * (0f - EnvMan.instance.GetWindDir().Yaw()); ((Graphic)__instance.m_shipWindIcon).color = Color.white; __instance.m_shipHudRoot.gameObject.SetActive(true); } } } [HarmonyTranspiler] [HarmonyPatch(typeof(Hud), "UpdateStamina")] private static IEnumerable<CodeInstruction> Hud_UpdateStamina_Transpile(IEnumerable<CodeInstruction> instructions) { return IgnoreShipHudRoot(instructions); } [HarmonyTranspiler] [HarmonyPatch(typeof(Hud), "UpdateEitr")] private static IEnumerable<CodeInstruction> Hud_UpdateEitr_Transpile(IEnumerable<CodeInstruction> instructions) { return IgnoreShipHudRoot(instructions); } private static IEnumerable<CodeInstruction> IgnoreShipHudRoot(IEnumerable<CodeInstruction> instructions) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Expected O, but got Unknown FieldInfo fieldInfo = AccessTools.Field(typeof(Hud), "m_shipHudRoot"); MethodInfo methodInfo = AccessTools.PropertyGetter(typeof(GameObject), "activeSelf"); CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchEndForward((CodeMatch[])(object)new CodeMatch[3] { new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldfld, (object)fieldInfo, (string)null), new CodeMatch((OpCode?)OpCodes.Callvirt, (object)methodInfo, (string)null) }).ThrowIfInvalid("Unable to find IL match").Advance(1) .Insert((CodeInstruction[])(object)new CodeInstruction[2] { new CodeInstruction(OpCodes.Pop, (object)null), new CodeInstruction(OpCodes.Ldc_I4_0, (object)null) }); return val.InstructionEnumeration(); } [HarmonyPostfix] [HarmonyPatch(typeof(Inventory), "MoveInventoryToGrave")] private static void RestoreFromGraveInventory(Inventory __instance, Inventory original) { if (((Humanoid)Player.m_localPlayer).m_inventory != original || Configs.PlayerDeath.Value == Configs.DeathRule.Tombstone) { return; } bool flag = false; for (int num = __instance.m_inventory.Count - 1; num >= 0; num--) { ItemData item = __instance.GetItem(num); if (item.IsNavItem()) { flag = true; switch (Configs.PlayerDeath.Value) { case Configs.DeathRule.Keep: Logging<Plugin>.Info("Player died, keeping compass", 0); __instance.m_inventory.Remove(item); original.m_inventory.Add(item); break; case Configs.DeathRule.Destroy: Logging<Plugin>.Info("Player died, compass destroyed", 0); __instance.m_inventory.Remove(item); break; case Configs.DeathRule.Tombstone: return; default: throw new ArgumentOutOfRangeException("DeathRule", "Invalid death rule"); } } } if (flag) { __instance.Changed(); original.Changed(); } } } [BepInPlugin("ZenDragon.ZenCompass", "ZenCompass", "1.7.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [SynchronizationMode(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] internal class Plugin : ZenMod<Plugin> { public const string PluginName = "ZenCompass"; public const string PluginVersion = "1.7.1"; public const string PluginID = "ZenDragon.ZenCompass"; private const string ZenMapPluginID = "ZenDragon.ZenMap"; internal static Compass? Compass; internal static bool IsZenMapLoaded => Chainloader.PluginInfos.ContainsKey("ZenDragon.ZenMap"); protected override void Setup() { if (IsZenMapLoaded) { Logging<Plugin>.Info("ZenDragon.ZenMap is loaded", 0); } base.RegisterCraftingItems += CompassItem.AddCraftingItems; } protected override void TitleScene(bool isFirstBoot) { Compass = null; } protected override void WorldStart() { Compass = new Compass(); } protected override void Shutdown() { Compass?.Shutdown(); } private void LateUpdate() { if (Compass != null) { Compass.Update(); DeathPinPatch.CheckForceRemoveButtonPress(); } } protected override HelpInfo? GetHelpInfo() { //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Expected O, but got Unknown StringBuilder stringBuilder = new StringBuilder(); if (Configs.CraftToUse.Value) { if (Configs.CraftingEnabledCompass.Value) { stringBuilder.AppendLine(HelpInfo.Format<bool>(Configs.CraftingEnabledCompass, false, true, false)); } if (Configs.CraftingEnabledSunstone.Value) { stringBuilder.AppendLine(HelpInfo.Format<bool>(Configs.CraftingEnabledSunstone, false, true, false)); } if (Configs.EquipToUse.Value) { stringBuilder.AppendLine(HelpInfo.Format<bool>(Configs.EquipToUse, false, true, true)); } else { stringBuilder.AppendLine(HelpInfo.Format<bool>(Configs.CraftToUse, false, true, true)); } } if (!Configs.MalfunctionEnabled.Value.IsNone()) { stringBuilder.AppendLine(HelpInfo.Format<Configs.NavTool>(Configs.MalfunctionEnabled, false, true, true)); } if (!Configs.TrackSun.Value.IsNone()) { stringBuilder.AppendLine(HelpInfo.Format<Configs.NavTool>(Configs.TrackSun, false, true, true)); } if (Configs.AllowInDungeon.Value) { stringBuilder.AppendLine(HelpInfo.Format<bool>(Configs.AllowInDungeon, false, true, true)); } if (!IsZenMapLoaded) { stringBuilder.AppendLine(HelpInfo.Format<KeyCode>(Configs.ForceRemoveDeathPinKey, true, true, true)); } return new HelpInfo("Compass", stringBuilder.ToString()); } } } [CompilerGenerated] internal sealed class <>z__ReadOnlyArray<T> : IEnumerable, ICollection, IList, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T> { int ICollection.Count => _items.Length; bool ICollection.IsSynchronized => false; object ICollection.SyncRoot => this; object IList.this[int index] { get { return _items[index]; } set { throw new NotSupportedException(); } } bool IList.IsFixedSize => true; bool IList.IsReadOnly => true; int IReadOnlyCollection<T>.Count => _items.Length; T IReadOnlyList<T>.this[int index] => _items[index]; int ICollection<T>.Count => _items.Length; bool ICollection<T>.IsReadOnly => true; T IList<T>.this[int index] { get { return _items[index]; } set { throw new NotSupportedException(); } } public <>z__ReadOnlyArray(T[] items) { _items = items; } IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)_items).GetEnumerator(); } void ICollection.CopyTo(Array array, int index) { ((ICollection)_items).CopyTo(array, index); } int IList.Add(object value) { throw new NotSupportedException(); } void IList.Clear() { throw new NotSupportedException(); } bool IList.Contains(object value) { return ((IList)_items).Contains(value); } int IList.IndexOf(object value) { return ((IList)_items).IndexOf(value); } void IList.Insert(int index, object value) { throw new NotSupportedException(); } void IList.Remove(object value) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } IEnumerator<T> IEnumerable<T>.GetEnumerator() { return ((IEnumerable<T>)_items).GetEnumerator(); } void ICollection<T>.Add(T item) { throw new NotSupportedException(); } void ICollection<T>.Clear() { throw new NotSupportedException(); } bool ICollection<T>.Contains(T item) { return ((ICollection<T>)_items).Contains(item); } void ICollection<T>.CopyTo(T[] array, int arrayIndex) { ((ICollection<T>)_items).CopyTo(array, arrayIndex); } bool ICollection<T>.Remove(T item) { throw new NotSupportedException(); } int IList<T>.IndexOf(T item) { return ((IList<T>)_items).IndexOf(item); } void IList<T>.Insert(int index, T item) { throw new NotSupportedException(); } void IList<T>.RemoveAt(int index) { throw new NotSupportedException(); } } [CompilerGenerated] internal sealed class <>z__ReadOnlySingleElementList<T> : IEnumerable, ICollection, IList, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T> { private sealed class Enumerator : IDisposable, IEnumerator, IEnumerator<T> { object IEnumerator.Current => _item; T IEnumerator<T>.Current => _item; public Enumerator(T item) { _item = item; } bool IEnumerator.MoveNext() { if (!_moveNextCalled) { return _moveNextCalled = true; } return false; } void IEnumerator.Reset() { _moveNextCalled = false; } void IDisposable.Dispose() { } } int ICollection.Count => 1; bool ICollection.IsSynchronized => false; object ICollection.SyncRoot => this; object IList.this[int index] { get { if (index != 0) { throw new IndexOutOfRangeException(); } return _item; } set { throw new NotSupportedException(); } } bool IList.IsFixedSize => true; bool IList.IsReadOnly => true; int IReadOnlyCollection<T>.Count => 1; T IReadOnlyList<T>.this[int index] { get { if (index != 0) { throw new IndexOutOfRangeException(); } return _item; } } int ICollection<T>.Count => 1; bool ICollection<T>.IsReadOnly => true; T IList<T>.this[int index] { get { if (index != 0) { throw new IndexOutOfRangeException(); } return _item; } set { throw new NotSupportedException(); } } public <>z__ReadOnlySingleElementList(T item) { _item = item; } IEnumerator IEnumerable.GetEnumerator() { return new Enumerator(_item); } void ICollection.CopyTo(Array array, int index) { array.SetValue(_item, index); } int IList.Add(object value) { throw new NotSupportedException(); } void IList.Clear() { throw new NotSupportedException(); } bool IList.Contains(object value) { return EqualityComparer<T>.Default.Equals(_item, (T)value); } int IList.IndexOf(object value) { if (!EqualityComparer<T>.Default.Equals(_item, (T)value)) { return -1; } return 0; } void IList.Insert(int index, object value) { throw new NotSupportedException(); } void IList.Remove(object value) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } IEnumerator<T> IEnumerable<T>.GetEnumerator() { return new Enumerator(_item); } void ICollection<T>.Add(T item) { throw new NotSupportedException(); } void ICollection<T>.Clear() { throw new NotSupportedException(); } bool ICollection<T>.Contains(T item) { return EqualityComparer<T>.Default.Equals(_item, item); } void ICollection<T>.CopyTo(T[] array, int arrayIndex) { array[arrayIndex] = _item; } bool ICollection<T>.Remove(T item) { throw new NotSupportedException(); } int IList<T>.IndexOf(T item) { if (!EqualityComparer<T>.Default.Equals(_item, item)) { return -1; } return 0; } void IList<T>.Insert(int index, T item) { throw new NotSupportedException(); } void IList<T>.RemoveAt(int index) { throw new NotSupportedException(); } }