Decompiled source of ShipPins v1.1.0

ShipPins.dll

Decompiled 12 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Splatform;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ShipPins")]
[assembly: AssemblyDescription("Pins every ship and cart on the map, modded ones included")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.1.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ShipPins
{
	[BepInPlugin("onononoki.ShipPins", "ShipPins", "1.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		private sealed class Kind
		{
			internal string Label;

			internal Sprite Icon;

			internal bool Vanilla;
		}

		public const string ModGuid = "onononoki.ShipPins";

		public const string ModName = "ShipPins";

		public const string ModVersion = "1.1.0";

		private const string VPlusGuid = "org.bepinex.plugins.valheim_plus";

		private const string VPlusPins = "ValheimPlus.GameClasses.displayCartsAndBoatsOnMap";

		private const string VPlusConfig = "ValheimPlus.Configurations.Configuration";

		internal static ManualLogSource Log;

		private static ConfigEntry<bool> _enabled;

		private static ConfigEntry<float> _updateSeconds;

		private static ConfigEntry<float> _iconSize;

		private static readonly FieldRef<ZDOMan, List<ZDO>[]> ObjectsBySector = AccessTools.FieldRefAccess<ZDOMan, List<ZDO>[]>("m_objectsBySector");

		private static readonly Dictionary<string, string> VanillaLabels = new Dictionary<string, string>
		{
			{ "Cart", "Cart" },
			{ "Raft", "Raft" },
			{ "Karve", "Karve" },
			{ "VikingShip", "Longship" }
		};

		private static readonly Dictionary<int, Kind> Kinds = new Dictionary<int, Kind>();

		private static readonly Dictionary<ZDO, PinData> Pins = new Dictionary<ZDO, PinData>();

		private static Minimap _map;

		private static float _timer = float.MaxValue;

		private static bool _failed;

		private static bool _vplus;

		private static bool _vplusSilenced;

		private static PropertyInfo _configCurrent;

		private static PropertyInfo _configMap;

		private static PropertyInfo _mapEnabled;

		private static PropertyInfo _mapDisplay;

		private const float NameGap = 0.1f;

		private void Awake()
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Expected O, but got Unknown
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Expected O, but got Unknown
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Expected O, but got Unknown
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			_enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Pin every ship and cart on the map, modded ones included. With ValheimPlus installed, its own four boat and cart pins are replaced, so each ship has one pin. Off: no pins from this mod (V+ shows its own again).");
			_updateSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("General", "UpdateSeconds", 2f, new ConfigDescription("How often the pins move to where the ships and carts are, in seconds (V+ uses 5).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 10f), Array.Empty<object>()));
			_iconSize = ((BaseUnityPlugin)this).Config.Bind<float>("General", "IconSize", 1.5f, new ConfigDescription("Size of the ship and cart pins. 1 is the game's normal pin size, 2 is V+'s.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 2f), Array.Empty<object>()));
			_vplus = Chainloader.PluginInfos.ContainsKey("org.bepinex.plugins.valheim_plus");
			Harmony val = new Harmony("onononoki.ShipPins");
			val.Patch((MethodBase)AccessTools.Method(typeof(Minimap), "UpdateMap", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "UpdatePins", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.Method(typeof(Minimap), "UpdatePins", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "FitPins", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			if (_vplus)
			{
				SilenceVPlus(val);
			}
			if (!_vplus)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"ShipPins 1.1.0 loaded, pinning every ship and cart");
			}
			else if (_vplusSilenced)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"ShipPins 1.1.0 loaded, pinning every ship and cart in place of V+'s boat and cart pins");
			}
			else
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"ShipPins 1.1.0 loaded, V+'s boat pin code not found (V+ update?): V+ keeps its four vanilla pins whenever its map setting shows them, ShipPins pins the rest");
			}
		}

		internal static MethodInfo ResolveVPlus()
		{
			Type type = AccessTools.TypeByName("ValheimPlus.Configurations.Configuration");
			_configCurrent = ((type == null) ? null : AccessTools.Property(type, "Current"));
			_configMap = ((_configCurrent == null) ? null : AccessTools.Property(_configCurrent.PropertyType, "Map"));
			_mapEnabled = ((_configMap == null) ? null : AccessTools.Property(_configMap.PropertyType, "IsEnabled"));
			_mapDisplay = ((_configMap == null) ? null : AccessTools.Property(_configMap.PropertyType, "displayCartsAndBoats"));
			Type type2 = AccessTools.TypeByName("ValheimPlus.GameClasses.displayCartsAndBoatsOnMap");
			Type type3 = ((type2 == null) ? null : AccessTools.Inner(type2, "Minimap_UpdateMap_Patch"));
			if (!(type3 == null))
			{
				return AccessTools.Method(type3, "Postfix", (Type[])null, (Type[])null);
			}
			return null;
		}

		private static void SilenceVPlus(Harmony harmony)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			try
			{
				MethodInfo methodInfo = ResolveVPlus();
				if (!(methodInfo == null))
				{
					harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(Plugin), "SkipVPlusPins", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					_vplusSilenced = true;
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("V+'s boat pin code changed shape: " + ex.Message));
			}
		}

		private static bool SkipVPlusPins()
		{
			if (!_failed)
			{
				return !_enabled.Value;
			}
			return true;
		}

		internal static bool VPlusDrawsPins()
		{
			if (!_vplus || _vplusSilenced)
			{
				return false;
			}
			try
			{
				if (_configCurrent == null || _configMap == null || _mapEnabled == null || _mapDisplay == null)
				{
					return true;
				}
				object value = _configMap.GetValue(_configCurrent.GetValue(null, null), null);
				return value == null || ((bool)_mapEnabled.GetValue(value, null) && (bool)_mapDisplay.GetValue(value, null));
			}
			catch
			{
				return true;
			}
		}

		private static void UpdatePins(Minimap __instance, Player player, float dt)
		{
			if (_failed)
			{
				return;
			}
			try
			{
				if ((Object)(object)__instance != (Object)(object)_map)
				{
					Pins.Clear();
					_map = __instance;
					_timer = float.MaxValue;
				}
				if (!_enabled.Value)
				{
					Clear(__instance);
					return;
				}
				_timer += dt;
				if (_timer < _updateSeconds.Value)
				{
					return;
				}
				_timer = 0f;
				if (!Object.op_Implicit((Object)(object)player) || ZDOMan.instance == null || !Object.op_Implicit((Object)(object)ZNetScene.instance))
				{
					return;
				}
				bool skipVanilla = VPlusDrawsPins();
				Ship controlledShip = player.GetControlledShip();
				List<ZDO>[] array = ObjectsBySector.Invoke(ZDOMan.instance);
				foreach (List<ZDO> list in array)
				{
					if (list == null)
					{
						continue;
					}
					foreach (ZDO item in list)
					{
						Kind kind = KindOf(item.GetPrefab());
						if (kind != null && !(kind.Vanilla && skipVanilla))
						{
							Pin(__instance, controlledShip, item, kind);
						}
					}
				}
				foreach (KeyValuePair<ZDO, PinData> item2 in Pins.Where((KeyValuePair<ZDO, PinData> p) => Stale(p.Key, skipVanilla)).ToList())
				{
					__instance.RemovePin(item2.Value);
					Pins.Remove(item2.Key);
				}
			}
			catch (Exception arg)
			{
				_failed = true;
				Log.LogError((object)$"pin update failed, ShipPins stops (V+ shows its own pins again if installed): {arg}");
				try
				{
					Clear(__instance);
				}
				catch (Exception)
				{
					Pins.Clear();
				}
			}
		}

		private static bool Stale(ZDO zdo, bool skipVanilla)
		{
			if (!zdo.IsValid())
			{
				return true;
			}
			Kind kind = KindOf(zdo.GetPrefab());
			if (kind != null)
			{
				return kind.Vanilla && skipVanilla;
			}
			return true;
		}

		private static void Pin(Minimap map, Ship steered, ZDO zdo, Kind kind)
		{
			//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_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = zdo.GetPosition();
			PinData value;
			bool flag = Pins.TryGetValue(zdo, out value);
			if (Object.op_Implicit((Object)(object)steered) && Vector3.Distance(((Component)steered).transform.position, position) < 0.01f)
			{
				if (flag)
				{
					map.RemovePin(value);
					Pins.Remove(zdo);
				}
				return;
			}
			if (flag)
			{
				value.m_pos = position;
				return;
			}
			value = map.AddPin(position, (PinType)4, kind.Label, false, false, 0L, default(PlatformUserID));
			if (Object.op_Implicit((Object)(object)kind.Icon))
			{
				value.m_icon = kind.Icon;
			}
			value.m_doubleSize = true;
			Pins.Add(zdo, value);
		}

		private static void FitPins(Minimap __instance)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Invalid comparison between Unknown and I4
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			if (Pins.Count == 0)
			{
				return;
			}
			float num = (((int)__instance.m_mode == 2) ? __instance.m_pinSizeLarge : __instance.m_pinSizeSmall);
			float num2 = num * _iconSize.Value;
			float num3 = (num2 - num) * 0.5f + num * 0.1f;
			foreach (PinData value in Pins.Values)
			{
				if (Object.op_Implicit((Object)(object)value.m_uiElement))
				{
					value.m_uiElement.sizeDelta = new Vector2(num2, num2);
					PinNameData namePinData = value.m_NamePinData;
					RectTransform val = ((namePinData != null) ? namePinData.PinNameRectTransform : null);
					if (Object.op_Implicit((Object)(object)val))
					{
						val.anchoredPosition = value.m_uiElement.anchoredPosition + new Vector2(0f, 0f - num3);
					}
				}
			}
		}

		private static void Clear(Minimap map)
		{
			foreach (PinData value in Pins.Values)
			{
				map.RemovePin(value);
			}
			Pins.Clear();
			_timer = float.MaxValue;
		}

		private static Kind KindOf(int hash)
		{
			if (Kinds.TryGetValue(hash, out var value))
			{
				return value;
			}
			if (!Object.op_Implicit((Object)(object)ZNetScene.instance))
			{
				return null;
			}
			GameObject prefab = ZNetScene.instance.GetPrefab(hash);
			if (Object.op_Implicit((Object)(object)prefab) && (Object.op_Implicit((Object)(object)prefab.GetComponent<Ship>()) || Object.op_Implicit((Object)(object)prefab.GetComponent<Vagon>())))
			{
				Piece component = prefab.GetComponent<Piece>();
				string value2;
				bool flag = VanillaLabels.TryGetValue(((Object)prefab).name, out value2);
				if (!flag)
				{
					value2 = ((Object.op_Implicit((Object)(object)component) && !string.IsNullOrEmpty(component.m_name)) ? Localization.instance.Localize(component.m_name) : ((Object)prefab).name);
				}
				value = new Kind
				{
					Label = value2,
					Icon = (Object.op_Implicit((Object)(object)component) ? component.m_icon : null),
					Vanilla = flag
				};
			}
			Kinds[hash] = value;
			return value;
		}
	}
}