Decompiled source of MiddleFingerChance v1.0.0

BepInEx/plugins/MiddleFingerChance/MiddleFingerChance.dll

Decompiled a day ago
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using MiddleFingerChance.Patches;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("MiddleFingerChance")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Sometimes hand just doesn't like you")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+00bab9c65c5cf5f92832a514cdf153706f27f530")]
[assembly: AssemblyProduct("MiddleFingerChance")]
[assembly: AssemblyTitle("MiddleFingerChance")]
[assembly: AssemblyVersion("1.0.0.0")]
[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 MiddleFingerChance
{
	internal static class AssetManager
	{
		private const string MfResource = "MiddleFingerChance.assets.mf.png";

		private const string LadderMfResource = "MiddleFingerChance.assets.laddermf.png";

		private static readonly Vector2 HandIconPivot = new Vector2(0.4651093f, 0.5235695f);

		private static readonly Vector2 HandIconPointPivot = new Vector2(0.4101668f, 0.5298965f);

		private static readonly Vector2 HandLadderIconPivot = new Vector2(0.5723158f, 0.4730356f);

		public static void LoadAssets(IconService service)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = LoadTexture("MiddleFingerChance.assets.mf.png");
			if ((Object)(object)val != (Object)null)
			{
				service.MfForHandIcon = BuildSprite(val, HandIconPivot, "mf_HandIcon");
				service.MfForHandIconPoint = BuildSprite(val, HandIconPointPivot, "mf_HandIconPoint");
			}
			Texture2D val2 = LoadTexture("MiddleFingerChance.assets.laddermf.png");
			if ((Object)(object)val2 != (Object)null)
			{
				service.MfLadder = BuildSprite(val2, HandLadderIconPivot, "mf_HandLadderIcon");
			}
		}

		private static Texture2D? LoadTexture(string resourceName)
		{
			//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_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			byte[] array = ReadEmbedded(resourceName);
			if (array == null)
			{
				return null;
			}
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false)
			{
				filterMode = (FilterMode)0,
				wrapMode = (TextureWrapMode)1
			};
			if (!ImageConversion.LoadImage(val, array))
			{
				return null;
			}
			return val;
		}

		private static byte[]? ReadEmbedded(string name)
		{
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			using Stream stream = executingAssembly.GetManifestResourceStream(name);
			if (stream == null)
			{
				return null;
			}
			using MemoryStream memoryStream = new MemoryStream();
			stream.CopyTo(memoryStream);
			return memoryStream.ToArray();
		}

		private static Sprite BuildSprite(Texture2D tex, Vector2 pivot, string spriteName)
		{
			//IL_0019: 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)
			Sprite val = Sprite.Create(tex, new Rect(0f, 0f, (float)((Texture)tex).width, (float)((Texture)tex).height), pivot, 100f);
			((Object)val).name = spriteName;
			return val;
		}
	}
	internal static class ConfigManager
	{
		public static ConfigEntry<float> Chance { get; private set; }

		public static ConfigEntry<bool> FixHoldIcon { get; private set; }

		internal static void Initialize(ConfigFile config)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			Chance = config.Bind<float>("General", "Chance", 5f, new ConfigDescription("Chance of an interact hand icon being replaced with the middle finger.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
			FixHoldIcon = config.Bind<bool>("Fixes", "FixHoldIcon", false, "There is a bug in vanilla where if u hold [E] and hover on holdable interactables (doors, ship lever), hand icon will not be visible.");
		}
	}
	public class IconService
	{
		private const string HandIconName = "HandIcon";

		private const string HandIconPointName = "HandIconPoint";

		private const string HandLadderIconName = "HandLadderIcon";

		private object? _currentHover;

		private bool _currentDecision;

		public Sprite? MfForHandIcon { get; set; }

		public Sprite? MfForHandIconPoint { get; set; }

		public Sprite? MfLadder { get; set; }

		public bool CurrentDecision => _currentDecision;

		public Sprite? GetReplacement(string vanillaSpriteName)
		{
			return (Sprite?)(vanillaSpriteName switch
			{
				"HandIcon" => MfForHandIcon, 
				"HandIconPoint" => MfForHandIconPoint, 
				"HandLadderIcon" => MfLadder, 
				_ => null, 
			});
		}

		public void UpdateHoverState(object? identity)
		{
			if (identity != _currentHover)
			{
				_currentHover = identity;
				if (identity == null)
				{
					_currentDecision = false;
					return;
				}
				float value = ConfigManager.Chance.Value;
				_currentDecision = Random.value * 100f < value;
				Plugin.Log.LogDebug((object)$"Hover-enter roll: chance={value:F1}%, result={_currentDecision}");
			}
		}
	}
	internal static class Metadata
	{
		public const string GUID = "com.seeya.middlefingerchance";

		public const string PLUGIN_NAME = "MiddleFingerChance";

		public const string VERSION = "1.0.0";
	}
	[BepInPlugin("com.seeya.middlefingerchance", "MiddleFingerChance", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		private readonly Harmony _harmony = new Harmony("com.seeya.middlefingerchance");

		internal static ManualLogSource Log { get; private set; }

		public static IconService Service { get; private set; }

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			Log.LogInfo((object)"Initializing MiddleFingerChance");
			ConfigManager.Initialize(((BaseUnityPlugin)this).Config);
			Service = new IconService();
			AssetManager.LoadAssets(Service);
			Log.LogInfo((object)"Applying patches");
			_harmony.PatchAll(typeof(PlayerControllerBPatch));
			Log.LogInfo((object)"MiddleFingerChance is loaded!");
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "MiddleFingerChance";

		public const string PLUGIN_NAME = "MiddleFingerChance";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace MiddleFingerChance.Patches
{
	[HarmonyPatch(typeof(PlayerControllerB))]
	internal static class PlayerControllerBPatch
	{
		private static readonly object GrabHoverToken = new object();

		private static bool _raisedCursorForHold;

		[HarmonyPostfix]
		[HarmonyPatch("SetHoverTipAndCurrentInteractTrigger")]
		private static void AfterSetHoverTip(PlayerControllerB __instance)
		{
			Image cursorIcon = __instance.cursorIcon;
			InteractTrigger hoveringOverTrigger = __instance.hoveringOverTrigger;
			if (ConfigManager.FixHoldIcon.Value && __instance.isHoldingInteract && (Object)(object)cursorIcon != (Object)null && (Object)(object)hoveringOverTrigger != (Object)null && hoveringOverTrigger.interactable && (Object)(object)hoveringOverTrigger.hoverIcon != (Object)null)
			{
				((Behaviour)cursorIcon).enabled = true;
				cursorIcon.sprite = hoveringOverTrigger.hoverIcon;
				if (!_raisedCursorForHold)
				{
					((Component)cursorIcon).transform.SetAsLastSibling();
					_raisedCursorForHold = true;
				}
			}
			else if (_raisedCursorForHold && !__instance.isHoldingInteract)
			{
				_raisedCursorForHold = false;
			}
			object obj;
			Sprite val;
			if ((Object)(object)hoveringOverTrigger != (Object)null)
			{
				obj = hoveringOverTrigger;
				val = (((Object)(object)cursorIcon != (Object)null && (Object)(object)cursorIcon.sprite != (Object)null) ? Plugin.Service.GetReplacement(((Object)cursorIcon.sprite).name) : null);
			}
			else if (IsGrabHover(__instance, cursorIcon))
			{
				obj = GrabHoverToken;
				val = Plugin.Service.MfForHandIcon;
			}
			else
			{
				obj = null;
				val = null;
			}
			Plugin.Service.UpdateHoverState(obj);
			if (obj != null && !((Object)(object)cursorIcon == (Object)null) && ((Behaviour)cursorIcon).enabled && Plugin.Service.CurrentDecision && !((Object)(object)val == (Object)null))
			{
				cursorIcon.sprite = val;
			}
		}

		private static bool IsGrabHover(PlayerControllerB player, Image? cursor)
		{
			if ((Object)(object)cursor != (Object)null && ((Behaviour)cursor).enabled && (Object)(object)cursor.sprite != (Object)null && (Object)(object)player.grabItemIcon != (Object)null)
			{
				return (Object)(object)cursor.sprite == (Object)(object)player.grabItemIcon;
			}
			return false;
		}
	}
}