Decompiled source of ValuableBreakNotifier v1.0.0

plugins/ValuableBreakNotifier.dll

Decompiled 3 weeks ago
using 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 System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ValuableBreakNotifier")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("A mod for R.E.P.O. that adds a notifier for broken valuables.")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ValuableBreakNotifier")]
[assembly: AssemblyTitle("ValuableBreakNotifier")]
[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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ValuableBreakNotifier
{
	[HarmonyPatch(typeof(PhysGrabber))]
	public static class PhysGrabberPatch
	{
		private static ManualLogSource Logger = Logger.CreateLogSource("PhysGrabberPatch");

		[HarmonyPrefix]
		[HarmonyPatch("ReleaseObject")]
		private static void ReleaseObject_Prefix(PhysGrabber __instance)
		{
			object? value = AccessTools.Field(typeof(PhysGrabber), "grabbedPhysGrabObject").GetValue(__instance);
			PhysGrabObject val = (PhysGrabObject)((value is PhysGrabObject) ? value : null);
			if ((Object)(object)val != (Object)null)
			{
				int instanceID = ((Object)val).GetInstanceID();
				PlayerAvatar playerAvatar = __instance.playerAvatar;
				PhysGrabObjectImpactDetectorPatch.lastTouchedByPlayer[instanceID] = playerAvatar;
				string arg = AccessTools.Field(typeof(PlayerAvatar), "playerName").GetValue(playerAvatar) as string;
				Logger.LogInfo((object)$"JUGADOR '{arg}' ha soltado el objeto ID '{instanceID}'. Lo estamos rastreando.");
			}
		}
	}
	[HarmonyPatch(typeof(PhysGrabObjectImpactDetector))]
	internal static class PhysGrabObjectImpactDetector_CollisionPatch
	{
		private static ManualLogSource Logger = Logger.CreateLogSource("ValuableBreakNotifierCollisionPatch");

		internal static HashSet<int> hitByEnemyThisFrame = new HashSet<int>();

		[HarmonyPostfix]
		[HarmonyPatch("FixedUpdate")]
		private static void FixedUpdate_Postfix()
		{
			hitByEnemyThisFrame.Clear();
		}

		[HarmonyPrefix]
		[HarmonyPatch("OnCollisionStay")]
		private static void OnCollisionStay_Prefix(PhysGrabObjectImpactDetector __instance, Collision collision)
		{
			if (((Component)collision.transform).CompareTag("Enemy"))
			{
				int instanceID = ((Object)((Component)__instance).gameObject).GetInstanceID();
				hitByEnemyThisFrame.Add(instanceID);
			}
		}
	}
	[HarmonyPatch(typeof(PhysGrabObjectImpactDetector))]
	internal static class PhysGrabObjectImpactDetectorPatch
	{
		public static Dictionary<int, PlayerAvatar> lastTouchedByPlayer = new Dictionary<int, PlayerAvatar>();

		private static ManualLogSource Logger = Logger.CreateLogSource("ValuableBreakNotifierPatch");

		[HarmonyPrefix]
		[HarmonyPatch("BreakRPC")]
		private static void BreakRPC_Prefix(PhysGrabObjectImpactDetector __instance, float valueLost, bool _loseValue)
		{
			if (!ValuableBreakNotifierPlugin.IsEnabled.Value)
			{
				return;
			}
			int instanceID = ((Object)((Component)__instance).gameObject).GetInstanceID();
			if (PhysGrabObjectImpactDetector_CollisionPatch.hitByEnemyThisFrame.Contains(instanceID))
			{
				return;
			}
			object? value = AccessTools.Field(typeof(PhysGrabObjectImpactDetector), "valuableObject").GetValue(__instance);
			ValuableObject val = (ValuableObject)((value is ValuableObject) ? value : null);
			if (!_loseValue || !((Object)(object)val != (Object)null))
			{
				return;
			}
			float num = (float)AccessTools.Field(typeof(ValuableObject), "dollarValueCurrent").GetValue(val);
			float num2 = (float)AccessTools.Field(typeof(ValuableObject), "dollarValueOriginal").GetValue(val);
			if (!(num - valueLost < num2 * 0.15f))
			{
				return;
			}
			object? value2 = AccessTools.Field(typeof(PhysGrabObjectImpactDetector), "physGrabObject").GetValue(__instance);
			PhysGrabObject val2 = (PhysGrabObject)((value2 is PhysGrabObject) ? value2 : null);
			List<string> list = new List<string>();
			if ((Object)(object)val2 != (Object)null)
			{
				List<PhysGrabber> list2 = AccessTools.Field(typeof(PhysGrabObject), "playerGrabbing").GetValue(val2) as List<PhysGrabber>;
				int instanceID2 = ((Object)val2).GetInstanceID();
				if (list2 != null && list2.Count > 0)
				{
					foreach (PhysGrabber item in list2)
					{
						list.Add(AccessTools.Field(typeof(PlayerAvatar), "playerName").GetValue(item.playerAvatar) as string);
					}
				}
				else if (lastTouchedByPlayer.ContainsKey(instanceID2))
				{
					PlayerAvatar obj = lastTouchedByPlayer[instanceID2];
					list.Add(AccessTools.Field(typeof(PlayerAvatar), "playerName").GetValue(obj) as string);
				}
				if (lastTouchedByPlayer.ContainsKey(instanceID2))
				{
					lastTouchedByPlayer.Remove(instanceID2);
				}
			}
			if (list.Count != 0 && !list.All(string.IsNullOrEmpty))
			{
				string text = string.Join(" y ", list.Where((string name) => !string.IsNullOrEmpty(name)).Distinct());
				string text2 = ((Object)val).name.Replace("(Clone)", "");
				string message = "<color=yellow>" + text + "</color> ha DESTRUIDO un " + text2 + "!";
				if ((Object)(object)UINotifier.Instance != (Object)null)
				{
					UINotifier.Instance.ShowNotification(message);
				}
			}
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "com.gambrinus.valuablebreaknotifier";

		public const string PLUGIN_NAME = "ValuableBreakNotifier";

		public const string PLUGIN_VERSION = "1.0.0";
	}
	public class UINotifier : MonoBehaviour
	{
		private TextMeshProUGUI notificationText;

		private Coroutine hideCoroutine;

		public static UINotifier Instance { get; private set; }

		private void Awake()
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			notificationText = ((Component)this).GetComponent<TextMeshProUGUI>();
			if (!((Object)(object)notificationText == (Object)null))
			{
				((TMP_Text)notificationText).fontSize = 22f;
				((TMP_Text)notificationText).text = "";
				((Graphic)notificationText).color = Color.white;
				((TMP_Text)notificationText).alignment = (TextAlignmentOptions)514;
				RectTransform component = ((Component)this).GetComponent<RectTransform>();
				component.anchoredPosition = new Vector2(0f, -300f);
				component.sizeDelta = new Vector2(700f, 60f);
				((Component)this).gameObject.SetActive(false);
			}
		}

		public void ShowNotification(string message, float duration = 4f)
		{
			if (!((Object)(object)notificationText == (Object)null))
			{
				((TMP_Text)notificationText).text = message;
				((Component)this).gameObject.SetActive(true);
				if (hideCoroutine != null)
				{
					((MonoBehaviour)this).StopCoroutine(hideCoroutine);
				}
				hideCoroutine = ((MonoBehaviour)this).StartCoroutine(HideAfterDelay(duration));
			}
		}

		private IEnumerator HideAfterDelay(float delay)
		{
			yield return (object)new WaitForSeconds(delay);
			((Component)this).gameObject.SetActive(false);
		}
	}
	[HarmonyPatch(typeof(LevelGenerator), "GenerateDone")]
	public static class UIPatcher
	{
		private static ManualLogSource Logger = Logger.CreateLogSource("UIPatcher");

		private static GameObject CreateUIElementFromClone<T>(string name) where T : MonoBehaviour
		{
			Logger.LogInfo((object)"Intentando crear elemento de UI...");
			GameObject val = GameObject.Find("UI/HUD/HUD Canvas/HUD/Game Hud");
			if ((Object)(object)val == (Object)null)
			{
				Logger.LogError((object)"No se encontró 'Game Hud'. No se puede crear la UI.");
				return null;
			}
			GameObject val2 = GameObject.Find("UI/HUD/HUD Canvas/HUD/Game Hud/Health");
			if ((Object)(object)val2 == (Object)null)
			{
				Logger.LogError((object)"No se encontró el objeto 'Health' para clonar. No se puede crear la UI.");
				return null;
			}
			GameObject val3 = Object.Instantiate<GameObject>(val2, val.transform);
			((Object)val3).name = name;
			Object.DestroyImmediate((Object)(object)val3.GetComponent<HealthUI>());
			Transform[] array = ((IEnumerable)val3.transform).Cast<Transform>().ToArray();
			foreach (Transform val4 in array)
			{
				Object.DestroyImmediate((Object)(object)((Component)val4).gameObject);
			}
			val3.AddComponent<T>();
			Logger.LogInfo((object)("¡Elemento de UI '" + name + "' creado y componente '" + typeof(T).Name + "' añadido con éxito!"));
			return val3;
		}

		private static void Postfix()
		{
			Logger.LogInfo((object)"UIPatcher Postfix EJECUTADO!");
			if ((Object)(object)UINotifier.Instance == (Object)null)
			{
				CreateUIElementFromClone<UINotifier>("ValuableBreakNotifierUI");
			}
			else
			{
				Logger.LogInfo((object)"La instancia de UINotifier ya existe, no se creará de nuevo.");
			}
		}
	}
	[BepInPlugin("com.gambrinus.valuablebreaknotifier", "ValuableBreakNotifier", "1.0.0")]
	public class ValuableBreakNotifierPlugin : BaseUnityPlugin
	{
		private static Harmony harmony;

		public static ConfigEntry<bool> IsEnabled { get; set; }

		private void Awake()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			IsEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Activa o desactiva las notificaciones de rotura de objetos.");
			harmony = new Harmony("com.gambrinus.valuablebreaknotifier");
			if (IsEnabled.Value)
			{
				harmony.PatchAll();
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Mod ValuableBreakNotifier v1.0.0 cargado y parches aplicados.");
			}
		}

		private void OnDestroy()
		{
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
}