Decompiled source of RepoChargingPadRegen v0.3.0

BepInEx/plugins/RepoChargingPadRegen.dll

Decompiled 9 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[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("RepoChargingPadRegen")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("RepoChargingPadRegen")]
[assembly: AssemblyTitle("RepoChargingPadRegen")]
[assembly: AssemblyVersion("1.0.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 RepoChargingPadRegen
{
	[BepInPlugin("com.chatgpt.repochargingpadregen", "REPO Charging Pad Regen", "0.3.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		internal static Plugin Instance;

		private static readonly Harmony Harmony = new Harmony("com.chatgpt.repochargingpadregen");

		private static readonly Dictionary<int, float> LastHeal = new Dictionary<int, float>();

		private static readonly Dictionary<int, float> LastStationTick = new Dictionary<int, float>();

		private const BindingFlags InstanceFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

		private void Awake()
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Expected O, but got Unknown
			Instance = this;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"REPO Charging Pad Regen 0.3.0 diagnostic build loaded.");
			try
			{
				Type type = AccessTools.TypeByName("ChargingStation");
				MethodInfo methodInfo = ((type == null) ? null : AccessTools.Method(type, "Update", (Type[])null, (Type[])null));
				if (methodInfo == null)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)"Could not find ChargingStation.Update.");
					return;
				}
				Harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "ChargingStationUpdatePostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Patched ChargingStation.Update.");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Patch setup failed: " + ex));
			}
		}

		private static void ChargingStationUpdatePostfix(object __instance)
		{
			try
			{
				if (__instance == null || !IsHost())
				{
					return;
				}
				Component val = (Component)((__instance is Component) ? __instance : null);
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				float unscaledTime = Time.unscaledTime;
				int instanceID = ((Object)val).GetInstanceID();
				if (LastStationTick.TryGetValue(instanceID, out var value) && unscaledTime - value < 0.2f)
				{
					return;
				}
				LastStationTick[instanceID] = unscaledTime;
				Type type = AccessTools.TypeByName("PlayerHealth");
				if (type == null)
				{
					return;
				}
				Object[] array = Object.FindObjectsOfType(type);
				foreach (Object obj in array)
				{
					Component val2 = (Component)(object)((obj is Component) ? obj : null);
					if ((Object)(object)val2 == (Object)null || !val2.gameObject.activeInHierarchy || !IsPlayerOnStation(val2, val) || !TryReadInt(type, val2, out var value2, "health", "playerHealth", "currentHealth") || !TryReadInt(type, val2, out var value3, "maxHealth", "playerMaxHealth", "maximumHealth") || value2 <= 0 || value3 <= 0 || value2 >= value3 || IsDead(val2))
					{
						continue;
					}
					int instanceID2 = ((Object)val2).GetInstanceID();
					if (!LastHeal.TryGetValue(instanceID2, out var value4) || !(unscaledTime - value4 < 1f))
					{
						if (TryInvokeHealOther(val2, 1))
						{
							LastHeal[instanceID2] = unscaledTime;
							int value5;
							bool flag = TryReadInt(type, val2, out value5, "health", "playerHealth", "currentHealth");
							((BaseUnityPlugin)Instance).Logger.LogInfo((object)("Charging-pad heal call returned. Before=" + value2 + "/" + value3 + ", after=" + (flag ? value5.ToString() : "unreadable") + ", station=" + ((Object)val).name + ", player=" + ((Object)val2).name + "."));
						}
						else
						{
							((BaseUnityPlugin)Instance).Logger.LogWarning((object)"PlayerHealth.HealOther(int, bool) was not found; no health changed.");
						}
					}
				}
			}
			catch (Exception ex)
			{
				if ((Object)(object)Instance != (Object)null)
				{
					((BaseUnityPlugin)Instance).Logger.LogError((object)("Regen tick failed: " + ex));
				}
			}
		}

		private static bool TryInvokeHealOther(Component health, int amount)
		{
			MethodInfo method = ((object)health).GetType().GetMethod("HealOther", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[2]
			{
				typeof(int),
				typeof(bool)
			}, null);
			if (method == null)
			{
				return false;
			}
			try
			{
				method.Invoke(health, new object[2] { amount, true });
				return true;
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)Instance).Logger.LogWarning((object)("HealOther failed: " + ex.GetBaseException().Message));
				return false;
			}
		}

		private static bool IsDead(Component health)
		{
			object obj = ReadMember(health, "playerAvatar", "playerAvatarScript", "playerAvatarReference");
			if (obj == null)
			{
				return false;
			}
			object obj2 = ReadMember(obj, "deadSet");
			if (obj2 is bool)
			{
				return (bool)obj2;
			}
			return false;
		}

		private static bool IsHost()
		{
			Type type = AccessTools.TypeByName("Photon.Pun.PhotonNetwork");
			if (type == null)
			{
				return true;
			}
			try
			{
				PropertyInfo property = type.GetProperty("InRoom", BindingFlags.Static | BindingFlags.Public);
				PropertyInfo property2 = type.GetProperty("IsMasterClient", BindingFlags.Static | BindingFlags.Public);
				return !(property != null) || !(bool)property.GetValue(null, null) || (property2 != null && (bool)property2.GetValue(null, null));
			}
			catch
			{
				return false;
			}
		}

		private static bool IsPlayerOnStation(Component player, Component station)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			Collider[] componentsInChildren = player.GetComponentsInChildren<Collider>();
			Collider[] componentsInChildren2 = station.GetComponentsInChildren<Collider>();
			if (componentsInChildren == null || componentsInChildren2 == null)
			{
				return false;
			}
			Collider[] array = componentsInChildren;
			foreach (Collider val in array)
			{
				if ((Object)(object)val == (Object)null || !val.enabled || !((Component)val).gameObject.activeInHierarchy)
				{
					continue;
				}
				Bounds bounds = val.bounds;
				Collider[] array2 = componentsInChildren2;
				foreach (Collider val2 in array2)
				{
					if (!((Object)(object)val2 == (Object)null) && val2.enabled && ((Component)val2).gameObject.activeInHierarchy && !val2.isTrigger)
					{
						Bounds bounds2 = val2.bounds;
						bool num = ((Bounds)(ref bounds)).max.x >= ((Bounds)(ref bounds2)).min.x && ((Bounds)(ref bounds)).min.x <= ((Bounds)(ref bounds2)).max.x && ((Bounds)(ref bounds)).max.z >= ((Bounds)(ref bounds2)).min.z && ((Bounds)(ref bounds)).min.z <= ((Bounds)(ref bounds2)).max.z;
						float y = ((Bounds)(ref bounds)).min.y;
						bool flag = y >= ((Bounds)(ref bounds2)).min.y - 0.25f && y <= ((Bounds)(ref bounds2)).max.y + 0.45f;
						if (num && flag)
						{
							return true;
						}
					}
				}
			}
			return false;
		}

		private static bool TryReadInt(Type type, object target, out int value, params string[] names)
		{
			value = 0;
			object obj = ReadMember(target, names);
			if (obj == null)
			{
				return false;
			}
			try
			{
				value = Convert.ToInt32(obj);
				return true;
			}
			catch
			{
				return false;
			}
		}

		private static object ReadMember(object target, params string[] names)
		{
			if (target == null)
			{
				return null;
			}
			Type type = ((target is Type) ? ((Type)target) : target.GetType());
			foreach (string name in names)
			{
				FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					try
					{
						return field.GetValue(target);
					}
					catch
					{
					}
				}
				PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (property != null && property.CanRead)
				{
					try
					{
						return property.GetValue(target, null);
					}
					catch
					{
					}
				}
			}
			return null;
		}
	}
}