Decompiled source of Sailwind Receipt Alert v1.1.0

plugins/SailwindReceiptAlert/SailwindReceiptAlert.dll

Decompiled a day ago
using System;
using System.Diagnostics;
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.7.1", FrameworkDisplayName = ".NET Framework 4.7.1")]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace SailwindReceiptAlert
{
	[BepInPlugin("skeptic043.sailwind.receiptalert", "Sailwind Receipt Alert", "1.1.0")]
	public sealed class ReceiptAlertPlugin : BaseUnityPlugin
	{
		public const string PluginId = "skeptic043.sailwind.receiptalert";

		public const string PluginName = "Sailwind Receipt Alert";

		public const string PluginVersion = "1.1.0";

		internal const string WarningText = "Don't forget your trade receipt!";

		internal const string CollectedText = "Trade receipt collected!";

		private const float ParchmentWidthMultiplier = 1.2f;

		internal static readonly Vector3 ZoneSize = new Vector3(12f, 4f, 12f);

		internal static readonly Vector3 ZoneOffset = new Vector3(0f, 0.5f, 0f);

		private static ReceiptAlertPlugin? _instance;

		private static readonly FieldInfo? NotificationUiField = AccessTools.Field(typeof(NotificationUi), "UI");

		private static bool _issuingReceiptNotification;

		private static bool _parchmentSetupFailureLogged;

		private static bool _parchmentSetupLogged;

		private static bool _receiptStorageFailureLogged;

		private static Transform? _widenedParchment;

		private static Vector3 _originalParchmentScale;

		private static ReceiptAlertParchmentReset? _parchmentReset;

		private ConfigEntry<bool>? _enabled;

		private ConfigEntry<bool>? _autoCollectReceipt;

		private Harmony? _harmony;

		private void Awake()
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			_instance = this;
			_enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Handle uncollected trade receipts when leaving a port desk area.");
			_autoCollectReceipt = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AutoCollectReceipt", false, "Automatically collect an available trade receipt on exit instead of showing a reminder.");
			_harmony = new Harmony("skeptic043.sailwind.receiptalert");
			_harmony.PatchAll(typeof(PortDudeAwakePatch));
			_harmony.PatchAll(typeof(NotificationUiShowNotificationPatch));
			((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("{0} {1} loaded; PortDude zone size {2} m.", "Sailwind Receipt Alert", "1.1.0", ZoneSize));
		}

		private void OnDestroy()
		{
			RestoreParchmentWidth();
			if (Object.op_Implicit((Object)(object)_parchmentReset))
			{
				Object.Destroy((Object)(object)_parchmentReset);
			}
			_parchmentReset = null;
			Harmony? harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			if (_instance == this)
			{
				_instance = null;
			}
		}

		internal static void LogSetup(string message)
		{
			ReceiptAlertPlugin? instance = _instance;
			if (instance != null)
			{
				((BaseUnityPlugin)instance).Logger.LogDebug((object)message);
			}
		}

		internal static void LogSetupFailure(string message, Exception? error = null)
		{
			ReceiptAlertPlugin? instance = _instance;
			ManualLogSource val = ((instance != null) ? ((BaseUnityPlugin)instance).Logger : null);
			if (val != null)
			{
				if (error == null)
				{
					val.LogWarning((object)message);
				}
				else
				{
					val.LogWarning((object)$"{message}: {error}");
				}
			}
		}

		internal static bool HandleReceiptOnExit()
		{
			ReceiptAlertPlugin instance = _instance;
			if (!((Object)(object)instance == (Object)null))
			{
				ConfigEntry<bool>? enabled = instance._enabled;
				if (enabled != null && enabled.Value)
				{
					EconomyUIReceiptScribe instance2 = EconomyUIReceiptScribe.instance;
					if (!Object.op_Implicit((Object)(object)instance2) || !instance2.ReceiptAvailable())
					{
						return false;
					}
					NotificationUi instance3 = NotificationUi.instance;
					if (!Object.op_Implicit((Object)(object)instance3))
					{
						return false;
					}
					ConfigEntry<bool>? autoCollectReceipt = instance._autoCollectReceipt;
					if (autoCollectReceipt != null && autoCollectReceipt.Value)
					{
						if (!Object.op_Implicit((Object)(object)TradeReceiptsUI.instance))
						{
							if (!_receiptStorageFailureLogged)
							{
								_receiptStorageFailureLogged = true;
								LogSetupFailure("Trade receipt storage is unavailable; falling back to the reminder.");
							}
							return ShowReceiptNotification(instance3, "Don't forget your trade receipt!");
						}
						if (!instance2.RequestCurrentReceipt())
						{
							return false;
						}
						return ShowReceiptNotification(instance3, "Trade receipt collected!");
					}
					return ShowReceiptNotification(instance3, "Don't forget your trade receipt!");
				}
			}
			return false;
		}

		private static bool ShowReceiptNotification(NotificationUi notification, string message)
		{
			_issuingReceiptNotification = true;
			try
			{
				notification.ShowNotification(message);
			}
			catch
			{
				RestoreParchmentWidth();
				throw;
			}
			finally
			{
				_issuingReceiptNotification = false;
			}
			return true;
		}

		internal static void OnNotificationShown(NotificationUi notification, string message)
		{
			if (!_issuingReceiptNotification || (!string.Equals(message, "Don't forget your trade receipt!", StringComparison.Ordinal) && !string.Equals(message, "Trade receipt collected!", StringComparison.Ordinal)))
			{
				RestoreParchmentWidth();
				return;
			}
			try
			{
				WidenParchment(notification);
			}
			catch (Exception arg)
			{
				RestoreParchmentWidth();
				LogParchmentSetupFailure($"Could not widen receipt notification parchment: {arg}");
			}
		}

		private static void WidenParchment(NotificationUi notification)
		{
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)_widenedParchment))
			{
				object? obj = NotificationUiField?.GetValue(notification);
				GameObject val = (GameObject)((obj is GameObject) ? obj : null);
				if ((Object)(object)val != (Object)null && Object.op_Implicit((Object)(object)val) && (Object)(object)_widenedParchment != (Object)null && _widenedParchment.IsChildOf(val.transform))
				{
					return;
				}
				RestoreParchmentWidth();
			}
			object? obj2 = NotificationUiField?.GetValue(notification);
			GameObject val2 = (GameObject)((obj2 is GameObject) ? obj2 : null);
			if ((Object)(object)val2 == (Object)null || !Object.op_Implicit((Object)(object)val2))
			{
				LogParchmentSetupFailure("Could not find Sailwind's notification UI; receipt notification will use its normal size.");
				return;
			}
			Transform val3 = val2.transform.Find("notification UI");
			Transform val4 = (Object.op_Implicit((Object)(object)val3) ? val3.Find("notification_UI") : null);
			if ((Object)(object)val3 == (Object)null || !Object.op_Implicit((Object)(object)val3) || (Object)(object)val4 == (Object)null || !Object.op_Implicit((Object)(object)val4) || !Object.op_Implicit((Object)(object)((Component)val4).GetComponent<SkinnedMeshRenderer>()))
			{
				LogParchmentSetupFailure("Could not find Sailwind's notification parchment; receipt notification will use its normal size.");
				return;
			}
			ReceiptAlertParchmentReset receiptAlertParchmentReset = val2.GetComponent<ReceiptAlertParchmentReset>();
			if (!Object.op_Implicit((Object)(object)receiptAlertParchmentReset))
			{
				receiptAlertParchmentReset = val2.AddComponent<ReceiptAlertParchmentReset>();
			}
			_parchmentReset = receiptAlertParchmentReset;
			_widenedParchment = val3;
			_originalParchmentScale = val3.localScale;
			val3.localScale = new Vector3(_originalParchmentScale.x * 1.2f, _originalParchmentScale.y, _originalParchmentScale.z);
			if (!_parchmentSetupLogged)
			{
				_parchmentSetupLogged = true;
				LogSetup($"Receipt notification parchment width set to {1.2f:0.0}x while the message is visible.");
			}
		}

		internal static void RestoreParchmentWidth(ReceiptAlertParchmentReset? reset = null)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)reset != (Object)null) || _parchmentReset == reset)
			{
				if ((Object)(object)_widenedParchment != (Object)null && Object.op_Implicit((Object)(object)_widenedParchment))
				{
					_widenedParchment.localScale = _originalParchmentScale;
				}
				_widenedParchment = null;
			}
		}

		internal static void OnParchmentResetDestroyed(ReceiptAlertParchmentReset reset)
		{
			RestoreParchmentWidth(reset);
			if (_parchmentReset == reset)
			{
				_parchmentReset = null;
			}
		}

		private static void LogParchmentSetupFailure(string message)
		{
			if (!_parchmentSetupFailureLogged)
			{
				_parchmentSetupFailureLogged = true;
				LogSetupFailure(message);
			}
		}

		internal static void LogPlayerEvent(string phase, Collider collider, string area, bool? notificationCalled)
		{
			ReceiptAlertPlugin instance = _instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			try
			{
				EconomyUIReceiptScribe instance2 = EconomyUIReceiptScribe.instance;
				string arg = "unknown";
				if (Object.op_Implicit((Object)(object)instance2))
				{
					try
					{
						arg = (instance2.ReceiptAvailable() ? "available" : "unavailable");
					}
					catch (Exception ex)
					{
						arg = "check-failed:" + ex.GetType().Name;
					}
				}
				((BaseUnityPlugin)instance).Logger.LogDebug((object)("Player-tagged collider " + phase + " receipt zone at " + area + ": " + $"collider={((Object)collider).name} ({((object)collider).GetType().Name}, id={((Object)collider).GetInstanceID()}), " + $"scribe={Object.op_Implicit((Object)(object)instance2)}, receipt={arg}, notification={Object.op_Implicit((Object)(object)NotificationUi.instance)}, " + $"enabled={instance._enabled?.Value ?? false}, autoCollect={instance._autoCollectReceipt?.Value ?? false}, " + "notificationCalled=" + (notificationCalled?.ToString() ?? "n/a") + "."));
			}
			catch (Exception ex2)
			{
				((BaseUnityPlugin)instance).Logger.LogDebug((object)("Could not log receipt zone " + phase + " event at " + area + ": " + ex2.GetType().Name + "."));
			}
		}
	}
	[HarmonyPatch(typeof(NotificationUi), "ShowNotification", new Type[]
	{
		typeof(string),
		typeof(float)
	})]
	internal static class NotificationUiShowNotificationPatch
	{
		[HarmonyPostfix]
		private static void Postfix(NotificationUi __instance, string __0)
		{
			ReceiptAlertPlugin.OnNotificationShown(__instance, __0);
		}
	}
	public sealed class ReceiptAlertParchmentReset : MonoBehaviour
	{
		private void OnDisable()
		{
			ReceiptAlertPlugin.RestoreParchmentWidth(this);
		}

		private void OnDestroy()
		{
			ReceiptAlertPlugin.OnParchmentResetDestroyed(this);
		}
	}
	[HarmonyPatch(typeof(PortDude), "Awake")]
	internal static class PortDudeAwakePatch
	{
		[HarmonyPostfix]
		private static void Postfix(PortDude __instance)
		{
			//IL_003e: 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)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: 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_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Expected O, but got Unknown
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)__instance))
			{
				ReceiptAlertPlugin.LogSetupFailure("Skipped receipt zone: PortDude is missing.");
				return;
			}
			GameObject val = null;
			try
			{
				Transform transform = ((Component)__instance).transform;
				if (Object.op_Implicit((Object)(object)((Component)transform).GetComponent<ReceiptAlertSkippedMarker>()))
				{
					return;
				}
				foreach (Transform item in transform)
				{
					if (Object.op_Implicit((Object)(object)((Component)item).GetComponent<ReceiptAlertZone>()))
					{
						ReceiptAlertPlugin.LogSetup("Receipt zone already exists for " + ((Object)__instance).name + "; skipped duplicate.");
						return;
					}
				}
				Vector3 lossyScale = transform.lossyScale;
				if (!ValidScale(lossyScale.x) || !ValidScale(lossyScale.y) || !ValidScale(lossyScale.z))
				{
					((Component)transform).gameObject.AddComponent<ReceiptAlertSkippedMarker>();
					ReceiptAlertPlugin.LogSetupFailure($"Skipped receipt zone for {((Object)__instance).name}: invalid world scale {lossyScale}.");
					return;
				}
				val = new GameObject("Receipt Alert Zone");
				val.SetActive(false);
				val.transform.SetParent(transform, false);
				val.transform.localPosition = new Vector3(ReceiptAlertPlugin.ZoneOffset.x / lossyScale.x, ReceiptAlertPlugin.ZoneOffset.y / lossyScale.y, ReceiptAlertPlugin.ZoneOffset.z / lossyScale.z);
				val.transform.localRotation = Quaternion.identity;
				val.transform.localScale = new Vector3(1f / lossyScale.x, 1f / lossyScale.y, 1f / lossyScale.z);
				Rigidbody obj = val.AddComponent<Rigidbody>();
				obj.isKinematic = true;
				obj.useGravity = false;
				BoxCollider obj2 = val.AddComponent<BoxCollider>();
				((Collider)obj2).isTrigger = true;
				obj2.size = ReceiptAlertPlugin.ZoneSize;
				val.AddComponent<ReceiptAlertZone>();
				val.SetActive(true);
				ReceiptAlertPlugin.LogSetup("Created receipt zone for " + ((Object)__instance).name + ".");
			}
			catch (Exception error)
			{
				if (Object.op_Implicit((Object)(object)val))
				{
					Object.Destroy((Object)(object)val);
				}
				ReceiptAlertPlugin.LogSetupFailure("Could not create receipt zone for " + ((Object)__instance).name, error);
			}
		}

		private static bool ValidScale(float value)
		{
			if (value > 0.0001f && !float.IsNaN(value))
			{
				return !float.IsInfinity(value);
			}
			return false;
		}
	}
	public sealed class ReceiptAlertSkippedMarker : MonoBehaviour
	{
	}
	public sealed class ReceiptAlertZone : MonoBehaviour
	{
		private const int MaxPlayerEventLogs = 12;

		private bool _callbackFailureLogged;

		private int _playerEventLogs;

		private void OnTriggerEnter(Collider other)
		{
			if (Object.op_Implicit((Object)(object)other) && ((Component)other).CompareTag("Player"))
			{
				LogPlayerEvent("entered", other, null);
			}
		}

		private void OnTriggerExit(Collider other)
		{
			if (!Object.op_Implicit((Object)(object)other) || !((Component)other).CompareTag("Player"))
			{
				return;
			}
			bool value = false;
			try
			{
				value = ReceiptAlertPlugin.HandleReceiptOnExit();
			}
			catch (Exception error)
			{
				if (!_callbackFailureLogged)
				{
					_callbackFailureLogged = true;
					Transform parent = ((Component)this).transform.parent;
					ReceiptAlertPlugin.LogSetupFailure("Receipt handling failed at " + ((parent != null) ? ((Object)parent).name : null), error);
				}
			}
			LogPlayerEvent("exited", other, value);
		}

		private void LogPlayerEvent(string phase, Collider other, bool? notificationCalled)
		{
			if (_playerEventLogs < 12)
			{
				_playerEventLogs++;
				Transform parent = ((Component)this).transform.parent;
				ReceiptAlertPlugin.LogPlayerEvent(phase, other, ((parent != null) ? ((Object)parent).name : null) ?? ((Object)this).name, notificationCalled);
				if (_playerEventLogs == 12)
				{
					Transform parent2 = ((Component)this).transform.parent;
					ReceiptAlertPlugin.LogSetup("Receipt zone at " + (((parent2 != null) ? ((Object)parent2).name : null) ?? ((Object)this).name) + " reached its player-event debug log limit.");
				}
			}
		}
	}
}