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 XPortalSharedMapPins v0.2.0
plugins\XPortalSharedMapPins.dll
Decompiled 8 hours agousing System; using System.Collections; 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.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [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("XPortalSharedMapPins")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("XPortalSharedMapPins")] [assembly: AssemblyTitle("XPortalSharedMapPins")] [assembly: AssemblyVersion("1.0.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace XPortalSharedMapPins { [BepInPlugin("buldosik.XPortalSharedMapPins", "XPortal Shared Map Pins", "0.2.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { [HarmonyPatch(typeof(Minimap), "UpdatePins")] private static class MinimapUpdatePinsPatch { private static void Postfix() { Instance?.ReapplyPortalColors(); } } public const string PluginGuid = "buldosik.XPortalSharedMapPins"; public const string PluginName = "XPortal Shared Map Pins"; public const string PluginVersion = "0.2.0"; private const string PinPrefix = ""; private static ManualLogSource Log = null; private static Plugin? Instance; private static readonly Dictionary<string, Vector3> ManagedPins = new Dictionary<string, Vector3>(); private ConfigEntry<float> _refreshInterval; private ConfigEntry<bool> _includePrivatePortals; private ConfigEntry<bool> _showPortalPins; private ConfigEntry<bool> _showNetworkInPinName; private ConfigEntry<bool> _restoreXPortalPins; private ConfigEntry<Color> _pinColor; private float _nextRefresh; private bool _warnedAboutApi; private MethodInfo? _getList; private MethodInfo? _getPortalList; private PropertyInfo? _managerInstance; private MethodInfo? _addPin; private MethodInfo? _removePin; private FieldInfo? _pinsField; private FieldInfo? _pinNameField; private FieldInfo? _pinPositionField; private FieldInfo? _pinTypeField; private FieldInfo? _pinIconField; private FieldInfo? _pinIconElementField; private FieldInfo? _iconsField; private FieldInfo? _visibleIconTypesField; private FieldInfo? _spriteDataNameField; private FieldInfo? _spriteDataIconField; private object? _portalManager; private object? _customPinType; private Sprite? _portalIcon; private bool _customPinTypeInstalled; private Harmony? _harmony; private void Awake() { //IL_00be: 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_010f: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; _refreshInterval = ((BaseUnityPlugin)this).Config.Bind<float>("General", "RefreshIntervalSeconds", 5f, "How often the local portal list is reflected onto the map."); _includePrivatePortals = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "IncludePrivatePortals", false, "Also add pins for private and personal-network portals. Each player sees these locally."); _showPortalPins = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowPortalPins", true, "Show XPortalNetworks portals on the map. Disable to remove only this mod's portal pins."); _showNetworkInPinName = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowNetworkInPinName", false, "Show the XPortalNetworks network name in generated map pin names."); _pinColor = ((BaseUnityPlugin)this).Config.Bind<Color>("General", "PinColor", new Color(0.4f, 0.8f, 1f, 1f), "Color of the generated portal pin icon. Configuration Manager provides a color picker."); _restoreXPortalPins = ((BaseUnityPlugin)this).Config.Bind<bool>("Actions", "RestoreXPortalPins", false, "Set to true to recreate only XPortal-generated pins; vanilla player pins are not touched."); CacheXPortalApi(); CacheMapApi(); _harmony = new Harmony("buldosik.XPortalSharedMapPins"); _harmony.PatchAll(typeof(Plugin).Assembly); Log.LogInfo((object)"Loaded. Portal pins are client-local and synchronized from XPortalNetworks."); } private void Update() { if (Time.unscaledTime < _nextRefresh || (Object)(object)Minimap.instance == (Object)null) { return; } _nextRefresh = Time.unscaledTime + Mathf.Max(1f, _refreshInterval.Value); EnsureCustomPortalType(); if (!_showPortalPins.Value) { RemoveAllManagedPins(); ManagedPins.Clear(); return; } if (_restoreXPortalPins.Value) { RestoreAllPins(); _restoreXPortalPins.Value = false; ((BaseUnityPlugin)this).Config.Save(); } RefreshPins(); } private void OnDestroy() { Harmony? harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } if (Instance == this) { Instance = null; } RemoveAllManagedPins(); ManagedPins.Clear(); } private void CacheXPortalApi() { try { Type type = Type.GetType("XPortalNetworks.KnownPortalsManager, XPortalNetworks"); if (type == null) { throw new InvalidOperationException("XPortalNetworks.KnownPortalsManager was not found"); } _managerInstance = type.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public); _getList = type.GetMethod("GetList", BindingFlags.Instance | BindingFlags.Public); _portalManager = _managerInstance?.GetValue(null, null); _getPortalList = typeof(ZDOMan).GetMethod("GetPortalList", BindingFlags.Instance | BindingFlags.Public); if (_managerInstance == null || _getList == null || _portalManager == null) { throw new MissingMethodException("XPortalNetworks portal list API is unavailable"); } } catch (Exception ex) { Log.LogError((object)("Could not connect to XPortalNetworks: " + ex.GetBaseException().Message)); } } private void CacheMapApi() { try { Type typeFromHandle = typeof(Minimap); _addPin = typeFromHandle.GetMethods(BindingFlags.Instance | BindingFlags.Public).FirstOrDefault((MethodInfo method) => method.Name == "AddPin" && IsAddPinSignature(method)); _removePin = typeFromHandle.GetMethods(BindingFlags.Instance | BindingFlags.Public).FirstOrDefault((MethodInfo method) => method.Name == "RemovePin" && IsRemovePinSignature(method)); Type nestedType = typeFromHandle.GetNestedType("PinData", BindingFlags.Public | BindingFlags.NonPublic); _pinsField = typeFromHandle.GetField("m_pins", BindingFlags.Instance | BindingFlags.NonPublic); _pinNameField = nestedType?.GetField("m_name", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _pinPositionField = nestedType?.GetField("m_pos", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _pinTypeField = nestedType?.GetField("m_type", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _pinIconField = nestedType?.GetField("m_icon", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _pinIconElementField = nestedType?.GetField("m_iconElement", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _iconsField = typeFromHandle.GetField("m_icons", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _visibleIconTypesField = typeFromHandle.GetField("m_visibleIconTypes", BindingFlags.Instance | BindingFlags.NonPublic); Type nestedType2 = typeFromHandle.GetNestedType("SpriteData", BindingFlags.Public | BindingFlags.NonPublic); _spriteDataNameField = nestedType2?.GetField("m_name", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _spriteDataIconField = nestedType2?.GetField("m_icon", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (_addPin == null || _removePin == null || _pinsField == null || _pinNameField == null || _pinPositionField == null || _pinTypeField == null || _pinIconField == null || _iconsField == null || _visibleIconTypesField == null || _spriteDataNameField == null || _spriteDataIconField == null) { throw new MissingMethodException("Valheim Minimap pin API is unavailable"); } } catch (Exception ex) { Log.LogError((object)("Could not connect to Valheim map pin API: " + ex.GetBaseException().Message)); } } private static bool IsAddPinSignature(MethodInfo method) { ParameterInfo[] parameters = method.GetParameters(); if (parameters.Length >= 5 && parameters.Length <= 7 && parameters[0].ParameterType == typeof(Vector3) && parameters[1].ParameterType.IsEnum && parameters[2].ParameterType == typeof(string) && parameters[3].ParameterType == typeof(bool) && parameters[4].ParameterType == typeof(bool)) { if (parameters.Length != 5 && parameters.Length != 6) { return parameters.Length == 7; } return true; } return false; } private static bool IsRemovePinSignature(MethodInfo method) { ParameterInfo[] parameters = method.GetParameters(); Type nestedType = typeof(Minimap).GetNestedType("PinData", BindingFlags.Public | BindingFlags.NonPublic); if (parameters.Length == 1 && nestedType != null) { return parameters[0].ParameterType == nestedType; } return false; } private void RefreshPins() { //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) if (_getList == null || _portalManager == null || _addPin == null || _removePin == null) { WarnOnce(ref _warnedAboutApi, "Portal or map APIs are unavailable; no pins will be created."); return; } try { Dictionary<string, Vector3> dictionary = new Dictionary<string, Vector3>(); if (_getList.Invoke(_portalManager, null) is IEnumerable enumerable) { foreach (object item in enumerable) { AddKnownPortalPin(dictionary, item); } } AddLocalPortalZdos(dictionary); foreach (KeyValuePair<string, Vector3> item2 in ManagedPins.ToList()) { if (!dictionary.TryGetValue(item2.Key, out var value) || value != item2.Value) { RemovePin(item2.Key, item2.Value); ManagedPins.Remove(item2.Key); } } foreach (KeyValuePair<string, Vector3> item3 in dictionary) { if (!ManagedPins.ContainsKey(item3.Key)) { AddPin(item3.Key, item3.Value); ManagedPins[item3.Key] = item3.Value; } } } catch (Exception ex) { Log.LogWarning((object)("Refreshing portal pins failed: " + ex.GetBaseException().Message)); } } private void AddKnownPortalPin(Dictionary<string, Vector3> wanted, object portal) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) if (TryReadPortal(portal, out string name, out Vector3 location, out long networkOwner, out bool isPrivate, out string networkName) && (_includePrivatePortals.Value || IsSharedPortal(networkOwner, isPrivate))) { AddWantedPin(wanted, name, location, networkName); } } private void AddLocalPortalZdos(Dictionary<string, Vector3> wanted) { //IL_0049: 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_0053: 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_008d: Unknown result type (might be due to invalid IL or missing references) if (_getPortalList == null || ZDOMan.instance == null || !(_getPortalList.Invoke(ZDOMan.instance, null) is IEnumerable enumerable)) { return; } foreach (object item in enumerable) { Vector3 location = ((ZDO)item).GetPosition(); if (!wanted.Values.Any(delegate(Vector3 existing) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) Vector3 val = existing - location; return ((Vector3)(ref val)).sqrMagnitude < 0.25f; })) { string name = ((ZDO)item).GetString("tag", string.Empty); AddWantedPin(wanted, name, location, "Global"); } } } private void AddWantedPin(Dictionary<string, Vector3> wanted, string name, Vector3 location, string networkName) { //IL_0072: Unknown result type (might be due to invalid IL or missing references) string text = (string.IsNullOrWhiteSpace(name) ? "Unnamed portal" : name.Trim()); string text2 = ((_showNetworkInPinName.Value && !string.IsNullOrWhiteSpace(networkName)) ? ("[" + networkName + "] ") : string.Empty) + text; string key = text2; int num = 2; while (wanted.ContainsKey(key)) { key = $"{text2} ({num++})"; } wanted[key] = location; } private static bool IsSharedPortal(long networkOwner, bool isPrivate) { if (!isPrivate) { if (networkOwner != 0L) { if (networkOwner >= 1) { return networkOwner <= 15; } return false; } return true; } return false; } private static bool TryReadPortal(object portal, out string name, out Vector3 location, out long networkOwner, out bool isPrivate, out string networkName) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) name = string.Empty; location = Vector3.zero; networkOwner = 0L; isPrivate = false; networkName = string.Empty; Type type = portal.GetType(); PropertyInfo property = type.GetProperty("Name"); PropertyInfo property2 = type.GetProperty("Location"); PropertyInfo property3 = type.GetProperty("NetworkOwnerPlayerId"); PropertyInfo property4 = type.GetProperty("NetworkOwnerDisplayName"); PropertyInfo property5 = type.GetProperty("IsPrivate"); if (property == null || property2 == null || property3 == null || property4 == null || property5 == null) { return false; } name = (property.GetValue(portal, null) as string) ?? string.Empty; location = (Vector3)(property2.GetValue(portal, null) ?? ((object)Vector3.zero)); networkOwner = Convert.ToInt64(property3.GetValue(portal, null)); isPrivate = Convert.ToBoolean(property5.GetValue(portal, null)); networkName = (property4.GetValue(portal, null) as string) ?? string.Empty; if (networkOwner == 0L) { networkName = "Global"; } else if (networkOwner >= 1 && networkOwner <= 15 && string.IsNullOrWhiteSpace(networkName)) { networkName = $"Network {networkOwner}"; } else if (string.IsNullOrWhiteSpace(networkName)) { networkName = "Personal"; } return true; } private void AddPin(string name, Vector3 location) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) Type parameterType = _addPin.GetParameters()[1].ParameterType; object item = _customPinType ?? Enum.Parse(parameterType, "Icon3"); ParameterInfo[] parameters = _addPin.GetParameters(); List<object> list = new List<object> { location, item, name, false, false }; if (parameters.Length >= 6) { list.Add(0L); } if (parameters.Length == 7) { list.Add(Activator.CreateInstance(parameters[6].ParameterType)); } object pin = _addPin.Invoke(Minimap.instance, list.ToArray()); ApplyPortalIcon(pin); } private void RemovePin(string name, Vector3 location) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) foreach (object item in GetMapPins().Cast<object>().ToList()) { if (object.Equals(_pinNameField.GetValue(item), name) && (Vector3)_pinPositionField.GetValue(item) == location) { _removePin.Invoke(Minimap.instance, new object[1] { item }); break; } } } private IEnumerable GetMapPins() { return (_pinsField?.GetValue(Minimap.instance) as IEnumerable) ?? Array.Empty<object>(); } private void EnsureCustomPortalType() { if (_customPinTypeInstalled || (Object)(object)Minimap.instance == (Object)null || _iconsField == null || _visibleIconTypesField == null || _spriteDataNameField == null || _spriteDataIconField == null || !(_iconsField.GetValue(Minimap.instance) is IList list)) { return; } foreach (object item in list) { object? value = _spriteDataIconField.GetValue(item); Sprite val = (Sprite)((value is Sprite) ? value : null); if ((Object)(object)val != (Object)null && ((Object)val).name.IndexOf("portal", StringComparison.OrdinalIgnoreCase) >= 0) { _portalIcon = val; break; } } if (_portalIcon == null) { _portalIcon = CreateFallbackPortalIcon(); } Type parameterType = _addPin.GetParameters()[1].ParameterType; int length = Enum.GetValues(parameterType).Length; _customPinType = Enum.ToObject(parameterType, length); object obj = Activator.CreateInstance(_spriteDataNameField.DeclaringType); _spriteDataNameField.SetValue(obj, _customPinType); _spriteDataIconField.SetValue(obj, _portalIcon); list.Add(obj); if (_visibleIconTypesField.GetValue(Minimap.instance) is bool[] array && array.Length <= length) { bool[] array2 = new bool[length + 1]; for (int i = 0; i < array2.Length; i++) { array2[i] = i >= array.Length || array[i]; } _visibleIconTypesField.SetValue(Minimap.instance, array2); } _customPinTypeInstalled = true; } private Sprite CreateFallbackPortalIcon() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: 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_004b: Unknown result type (might be due to invalid IL or missing references) //IL_008f: 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) Texture2D val = new Texture2D(32, 32, (TextureFormat)4, false) { name = "XPortalSharedMapPins_PortalIcon", filterMode = (FilterMode)1, wrapMode = (TextureWrapMode)1 }; Color[] array = (Color[])(object)new Color[1024]; for (int i = 0; i < 32; i++) { for (int j = 0; j < 32; j++) { float num = Vector2.Distance(new Vector2((float)j, (float)i), new Vector2(15.5f, 15.5f)); float num2 = Mathf.Clamp01((0.9f - Mathf.Abs(num - 9.5f)) * 4f); array[i * 32 + j] = new Color(1f, 1f, 1f, num2); } } val.SetPixels(array); val.Apply(); return Sprite.Create(val, new Rect(0f, 0f, 32f, 32f), new Vector2(0.5f, 0.5f), 32f); } private void ApplyPortalIcon(object? pin) { //IL_0084: Unknown result type (might be due to invalid IL or missing references) if (pin != null && !((Object)(object)_portalIcon == (Object)null)) { _pinTypeField?.SetValue(pin, _customPinType); _pinIconField?.SetValue(pin, _portalIcon); object obj = _pinIconElementField?.GetValue(pin); SetImageSprite(obj, _portalIcon); (obj?.GetType().GetProperty("color"))?.SetValue(obj, _pinColor.Value, null); } } private static void SetImageSprite(object? image, Sprite sprite) { (image?.GetType().GetProperty("sprite"))?.SetValue(image, sprite, null); } private void RestoreAllPins() { RemoveAllManagedPins(); ManagedPins.Clear(); } private void RemoveAllManagedPins() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Minimap.instance == (Object)null || _removePin == null) { return; } foreach (KeyValuePair<string, Vector3> managedPin in ManagedPins) { try { RemovePin(managedPin.Key, managedPin.Value); } catch (Exception ex) { Log.LogDebug((object)("Could not remove managed map pin: " + ex.GetBaseException().Message)); } } } private void ReapplyPortalColors() { //IL_0095: Unknown result type (might be due to invalid IL or missing references) if (_pinTypeField == null || _pinIconElementField == null || _customPinType == null || (Object)(object)Minimap.instance == (Object)null) { return; } foreach (object item in GetMapPins().Cast<object>()) { if (object.Equals(_pinTypeField.GetValue(item), _customPinType)) { object value = _pinIconElementField.GetValue(item); (value?.GetType().GetProperty("color"))?.SetValue(value, _pinColor.Value, null); } } } private static void WarnOnce(ref bool warned, string message) { if (!warned) { warned = true; Log.LogWarning((object)message); } } } }