Decompiled source of GrabRechargeMP v1.0.0

PlayerGrabRecharge.dll

Decompiled 2 weeks ago
using System;
using System.Diagnostics;
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 ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using TMPro;
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("PlayerGrabRecharge")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("3.0.0.0")]
[assembly: AssemblyInformationalVersion("3.0.0")]
[assembly: AssemblyProduct("PlayerGrabRecharge")]
[assembly: AssemblyTitle("PlayerGrabRecharge")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("3.0.0.0")]
[module: UnverifiableCode]
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;
		}
	}
}
namespace PlayerGrabRecharge
{
	[BepInPlugin("modx.playergrabrecharge", "Player Grab Recharge", "3.0.0")]
	public class PlayerGrabRechargePlugin : BaseUnityPlugin, IOnEventCallback
	{
		public const string PLUGIN_GUID = "modx.playergrabrecharge";

		public const string PLUGIN_NAME = "Player Grab Recharge";

		public const string PLUGIN_VERSION = "3.0.0";

		private const byte EVENT_CHARGE = 143;

		internal static ManualLogSource Logger = null;

		private Harmony _harmony;

		internal static bool IsRecharging = false;

		internal static float ModPower = 10f;

		internal static float Cooldown = 0f;

		private static float _chargeAccum = 0f;

		private static ItemBattery? _lastBattery = null;

		internal const float MAX_POWER = 10f;

		internal const float COOLDOWN_TIME = 2f;

		internal const float REGEN_RATE = 0.1f;

		private static MethodInfo? _syncMethod;

		private static FieldInfo? _chargeTimerField;

		private static FieldInfo? _isChargingField;

		public static ConfigEntry<KeyCode> RechargeKey { get; private set; } = null;


		public static ConfigEntry<bool> ToggleMode { get; private set; } = null;


		public static ConfigEntry<int> RechargeRate { get; private set; } = null;


		public static ConfigEntry<bool> ShowUI { get; private set; } = null;


		public static ConfigEntry<bool> DebugLog { get; private set; } = null;


		public static PlayerGrabRechargePlugin Instance { get; private set; } = null;


		private void Awake()
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Expected O, but got Unknown
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Expected O, but got Unknown
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			Logger = ((BaseUnityPlugin)this).Logger;
			RechargeKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Settings", "RechargeKey", (KeyCode)122, "Key to hold (or tap in toggle mode) to recharge grabbed item.");
			ToggleMode = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "ToggleMode", false, "False = hold to charge. True = tap to toggle.");
			RechargeRate = ((BaseUnityPlugin)this).Config.Bind<int>("Settings", "RechargeRate", 10, new ConfigDescription("Battery % per second.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 30), Array.Empty<object>()));
			ShowUI = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "ShowChargeBar", true, "Show mod power bar on HUD.");
			DebugLog = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "DebugLogging", false, "Verbose logging.");
			_harmony = new Harmony("modx.playergrabrecharge");
			_harmony.PatchAll(typeof(PlayerGrabRechargePlugin));
			Logger.LogInfo((object)string.Format("[PGR] v{0} loaded. Key={1}", "3.0.0", RechargeKey.Value));
		}

		private void OnDestroy()
		{
			_harmony.UnpatchSelf();
			PhotonNetwork.RemoveCallbackTarget((object)this);
		}

		private static ItemBattery? GetGrabbedBattery(PlayerController pc)
		{
			GameObject physGrabObject = pc.physGrabObject;
			if ((Object)(object)physGrabObject == (Object)null)
			{
				return null;
			}
			Transform val = physGrabObject.transform;
			while ((Object)(object)val.parent != (Object)null && (Object)(object)((Component)val.parent).GetComponent<PhysGrabObject>() != (Object)null)
			{
				val = val.parent;
			}
			ItemBattery componentInChildren = ((Component)val).GetComponentInChildren<ItemBattery>(true);
			if (DebugLog.Value && (Object)(object)componentInChildren == (Object)null && (Object)(object)pc.physGrabObject != (Object)null)
			{
				Logger.LogInfo((object)("[PGR] No battery found in " + ((Object)val).name + " (grabbed=" + ((Object)physGrabObject).name + ")"));
			}
			return componentInChildren;
		}

		private static void EnsureVisualFields()
		{
			if (_chargeTimerField == null)
			{
				_chargeTimerField = typeof(ItemBattery).GetField("chargeTimer", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			}
			if (_isChargingField == null)
			{
				_isChargingField = typeof(ItemBattery).GetField("isCharging", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			}
		}

		private static void SetChargingVisual(ItemBattery battery)
		{
			EnsureVisualFields();
			_chargeTimerField?.SetValue(battery, 0.2f);
			_isChargingField?.SetValue(battery, true);
		}

		private static void StopChargingVisual(ItemBattery? battery)
		{
			if (!((Object)(object)battery == (Object)null))
			{
				EnsureVisualFields();
				_isChargingField?.SetValue(battery, false);
				_chargeTimerField?.SetValue(battery, 0f);
				_chargeAccum = 0f;
				_lastBattery = null;
			}
		}

		private static void ApplyCharge(ItemBattery battery, float amount)
		{
			if ((Object)(object)_lastBattery != (Object)(object)battery)
			{
				_chargeAccum = 0f;
				_lastBattery = battery;
			}
			float num = ((battery.batteryBars > 0) ? (100f / (float)battery.batteryBars) : 100f);
			_chargeAccum += amount;
			if (_chargeAccum >= num)
			{
				_chargeAccum -= num;
				float batteryLife = battery.batteryLife;
				float num2 = Mathf.Clamp(batteryLife + num, num, 100f);
				if (battery.batteryLife <= 0f)
				{
					battery.batteryLife = 0.001f;
				}
				battery.SetBatteryLife(Mathf.RoundToInt(num2));
				if (DebugLog.Value)
				{
					Logger.LogInfo((object)$"[PGR] Bar added! {batteryLife:F0}→{num2:F0} bars={battery.batteryBars} barSize={num:F0}");
				}
			}
		}

		public void OnEvent(EventData photonEvent)
		{
			if (photonEvent.Code != 143 || !PhotonNetwork.IsMasterClient)
			{
				return;
			}
			try
			{
				object[] obj = (object[])photonEvent.CustomData;
				int num = (int)obj[0];
				float num2 = (float)obj[1];
				PhotonView val = PhotonView.Find(num);
				ItemBattery val2 = ((val != null) ? ((Component)val).GetComponent<ItemBattery>() : null) ?? ((val != null) ? ((Component)val).GetComponentInChildren<ItemBattery>(true) : null);
				if (!((Object)(object)val2 == (Object)null))
				{
					ApplyCharge(val2, num2);
					if (DebugLog.Value)
					{
						Logger.LogInfo((object)$"[PGR:HOST] Applied remote charge +{num2:F3} on {((Object)val2).name}");
					}
				}
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("[PGR] OnEvent error: " + ex.Message));
			}
		}

		private static void DrawPowerBar(TextMeshProUGUI tmp)
		{
			if (!ShowUI.Value || (Object)(object)tmp == (Object)null)
			{
				return;
			}
			float num = Mathf.Clamp01(ModPower / 10f);
			string text = $"{Mathf.RoundToInt(num * 100f)}%";
			if (Cooldown > 0f)
			{
				text += $" (CD {Cooldown:F1}s)";
			}
			string text2 = ((num < 0.25f) ? "#ff3333" : ((num < 0.6f) ? "#ffaa00" : "#00ff66"));
			string text3 = "<line-height=70%>\n<color=" + text2 + "><size=22>Charge: " + text + "</size></color>";
			if (!((TMP_Text)tmp).text.Contains("Charge:"))
			{
				((TMP_Text)tmp).text = ((TMP_Text)tmp).text + text3;
				return;
			}
			int num2 = ((TMP_Text)tmp).text.IndexOf("Charge:");
			int num3 = ((TMP_Text)tmp).text.IndexOf('\n', num2);
			if (num3 == -1)
			{
				num3 = ((TMP_Text)tmp).text.Length;
			}
			string text4 = ((TMP_Text)tmp).text.Substring(0, num2);
			string text5 = ((TMP_Text)tmp).text;
			int num4 = num3;
			((TMP_Text)tmp).text = text4 + text3 + text5.Substring(num4, text5.Length - num4);
		}

		[HarmonyPatch(typeof(PlayerController), "Update")]
		[HarmonyPostfix]
		private static void PlayerControllerUpdate_Postfix(PlayerController __instance)
		{
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_028b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_0292: Unknown result type (might be due to invalid IL or missing references)
			//IL_0299: Expected O, but got Unknown
			//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance != (Object)(object)PlayerController.instance || (!SemiFunc.RunIsLevel() && !SemiFunc.RunIsShop()))
			{
				return;
			}
			if (Cooldown > 0f)
			{
				Cooldown -= Time.deltaTime;
			}
			else if (ModPower < 10f)
			{
				ModPower = Mathf.Min(ModPower + 0.1f * Time.deltaTime, 10f);
			}
			if (!ToggleMode.Value)
			{
				IsRecharging = Input.GetKey(RechargeKey.Value);
			}
			else if (Input.GetKeyDown(RechargeKey.Value))
			{
				IsRecharging = !IsRecharging;
				if (IsRecharging && ModPower <= 0.01f)
				{
					IsRecharging = false;
				}
			}
			if (IsRecharging && ModPower <= 0.01f)
			{
				Cooldown = 2f;
				ModPower = 0f;
				IsRecharging = false;
			}
			bool num = IsRecharging && Cooldown <= 0f && ModPower > 0.01f;
			ItemBattery grabbedBattery = GetGrabbedBattery(__instance);
			if (!num)
			{
				StopChargingVisual(grabbedBattery);
				return;
			}
			if (DebugLog.Value)
			{
				ManualLogSource logger = Logger;
				GameObject physGrabObject = __instance.physGrabObject;
				logger.LogInfo((object)string.Format("[PGR] Z held: grabbed={0} battery={1} life={2:F1}", ((physGrabObject != null) ? ((Object)physGrabObject).name : null) ?? "null", ((grabbedBattery != null) ? ((Object)grabbedBattery).name : null) ?? "null", grabbedBattery?.batteryLife));
			}
			if ((Object)(object)grabbedBattery == (Object)null || grabbedBattery.isUnchargable || grabbedBattery.batteryLife >= 100f)
			{
				StopChargingVisual(grabbedBattery);
				return;
			}
			SetChargingVisual(grabbedBattery);
			float num2 = (float)RechargeRate.Value * Time.deltaTime;
			ModPower -= Mathf.Min(1f * Time.deltaTime, ModPower);
			if (!PhotonNetwork.IsConnected || !PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient)
			{
				ApplyCharge(grabbedBattery, num2);
				if (DebugLog.Value)
				{
					Logger.LogInfo((object)$"[PGR] Charged {((Object)grabbedBattery).name} +{num2:F2} life={grabbedBattery.batteryLife:F1}");
				}
				return;
			}
			PhotonView val = ((Component)grabbedBattery).GetComponent<PhotonView>() ?? ((Component)grabbedBattery).GetComponentInParent<PhotonView>() ?? ((Component)grabbedBattery).GetComponentInChildren<PhotonView>();
			if ((Object)(object)val == (Object)null)
			{
				ApplyCharge(grabbedBattery, num2);
				if (DebugLog.Value)
				{
					Logger.LogInfo((object)"[PGR] No PhotonView, charged locally");
				}
				return;
			}
			RaiseEventOptions val2 = new RaiseEventOptions
			{
				Receivers = (ReceiverGroup)2
			};
			PhotonNetwork.RaiseEvent((byte)143, (object)new object[2] { val.ViewID, num2 }, val2, SendOptions.SendUnreliable);
			if (DebugLog.Value)
			{
				Logger.LogInfo((object)$"[PGR] Sent charge event ViewID={val.ViewID}");
			}
		}

		[HarmonyPatch(typeof(LevelGenerator), "Generate")]
		[HarmonyPostfix]
		private static void LevelGenerator_Generate_Postfix()
		{
			IsRecharging = false;
			ModPower = 10f;
			Cooldown = 0f;
			_chargeAccum = 0f;
			_lastBattery = null;
			PhotonNetwork.AddCallbackTarget((object)Instance);
			if (DebugLog.Value)
			{
				Logger.LogInfo((object)"[PGR] Level generated, callbacks registered");
			}
		}

		[HarmonyPatch(typeof(PlayerController), "Start")]
		[HarmonyPostfix]
		private static void PlayerControllerStart_Postfix(PlayerController __instance)
		{
			if (!((Object)(object)__instance != (Object)(object)PlayerController.instance))
			{
				PhotonNetwork.AddCallbackTarget((object)Instance);
				if (DebugLog.Value)
				{
					Logger.LogInfo((object)"[PGR] PlayerController started, callbacks re-registered");
				}
			}
		}

		[HarmonyPatch(typeof(GoalUI), "Update")]
		[HarmonyPostfix]
		private static void GoalUI_Update_Postfix(TextMeshProUGUI ___Text)
		{
			if (SemiFunc.RunIsLevel())
			{
				DrawPowerBar(___Text);
			}
		}

		[HarmonyPatch(typeof(EnergyUI), "Update")]
		[HarmonyPostfix]
		private static void EnergyUI_Update_Postfix(TextMeshProUGUI ___Text)
		{
			if (SemiFunc.RunIsShop())
			{
				DrawPowerBar(___Text);
			}
		}
	}
}