Decompiled source of SharedEnergy v1.1.6

SharedEnergy.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
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.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[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: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("Misemise")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+cf9bc7ca77cfc312bcb9f7bb063975a4ae39b0f9")]
[assembly: AssemblyProduct("SharedEnergy")]
[assembly: AssemblyTitle("SharedEnergy")]
[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.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 SharedEnergy
{
	internal readonly struct BatterySnapshot
	{
		internal float BatteryLife { get; }

		internal int BatteryLifeInt { get; }

		internal int BatteryLifeCountBars { get; }

		internal int BatteryLifeCountBarsPrev { get; }

		internal int CurrentBars { get; }

		internal BatterySnapshot(float batteryLife, int batteryLifeInt, int batteryLifeCountBars, int batteryLifeCountBarsPrev, int currentBars)
		{
			BatteryLife = batteryLife;
			BatteryLifeInt = batteryLifeInt;
			BatteryLifeCountBars = batteryLifeCountBars;
			BatteryLifeCountBarsPrev = batteryLifeCountBarsPrev;
			CurrentBars = currentBars;
		}
	}
	internal static class BatteryStateUtil
	{
		private static readonly MethodInfo BatteryUpdateBarsMethod = typeof(ItemBattery).GetMethod("BatteryUpdateBars", BindingFlags.Instance | BindingFlags.NonPublic);

		internal static ItemBattery? FindBattery(Component component)
		{
			return ((Object)(object)component == (Object)null) ? null : component.GetComponent<ItemBattery>();
		}

		internal static BatterySnapshot Capture(ItemBattery itemBattery)
		{
			Traverse val = Traverse.Create((object)itemBattery);
			return new BatterySnapshot(itemBattery.batteryLife, itemBattery.batteryLifeInt, val.Field("batteryLifeCountBars").GetValue<int>(), val.Field("batteryLifeCountBarsPrev").GetValue<int>(), itemBattery.currentBars);
		}

		internal static void Restore(ItemBattery itemBattery, BatterySnapshot state)
		{
			itemBattery.batteryLife = state.BatteryLife;
			itemBattery.batteryLifeInt = state.BatteryLifeInt;
			itemBattery.currentBars = state.CurrentBars;
			Traverse val = Traverse.Create((object)itemBattery);
			val.Field("batteryLifeCountBars").SetValue((object)state.BatteryLifeCountBars);
			val.Field("batteryLifeCountBarsPrev").SetValue((object)state.BatteryLifeCountBarsPrev);
			ItemAttributes component = ((Component)itemBattery).GetComponent<ItemAttributes>();
			if (!string.IsNullOrEmpty(component?.instanceName))
			{
				SemiFunc.StatSetBattery(component.instanceName, Mathf.RoundToInt(state.BatteryLife));
			}
			BatteryUpdateBarsMethod?.Invoke(itemBattery, new object[1] { state.BatteryLifeInt });
		}
	}
	[HarmonyPatch(typeof(ItemBattery), "RemoveFullBar")]
	public class PatchBatteryConsume
	{
		private const string PowerCrystalItemName = "Item Power Crystal";

		private const int FallbackEnergyPerCrystal = 10;

		private const int FallbackMaxCrystals = 10;

		private static int? LastSyncedChargeTotal;

		private static int? LastSyncedCrystalCount;

		private static bool Prefix(ItemBattery __instance, int _bars)
		{
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				return true;
			}
			if (SemiFunc.RunIsShop())
			{
				return true;
			}
			if ((Object)(object)ChargingStation.instance == (Object)null)
			{
				return true;
			}
			if ((Object)(object)StatsManager.instance == (Object)null)
			{
				return true;
			}
			int num = Mathf.Max(1, Mathf.RoundToInt((float)_bars * 20f / (float)__instance.batteryBars));
			if (ChargingStation.instance.chargeTotal >= num)
			{
				DrainStation(num);
				return false;
			}
			return true;
		}

		internal static void DrainStation(int cost)
		{
			if (SemiFunc.IsMasterClientOrSingleplayer() && !((Object)(object)ChargingStation.instance == (Object)null) && !((Object)(object)StatsManager.instance == (Object)null))
			{
				SharedEnergy.LogDebug(string.Format("[DrainStation] 消費:{0}, 現在のchargeTotal:{1}, itemsPurchased:{2}", cost, ChargingStation.instance.chargeTotal, SemiFunc.StatGetItemsPurchased("Item Power Crystal")));
				int chargeTotal = Mathf.Max(0, ChargingStation.instance.chargeTotal - cost);
				SyncStationState(chargeTotal);
			}
		}

		internal static int GetEnergyPerCrystal()
		{
			if ((Object)(object)ChargingStation.instance == (Object)null)
			{
				return 10;
			}
			return Traverse.Create((object)ChargingStation.instance).Field("energyPerCrystal").GetValue<int>();
		}

		internal static int GetMaxCrystals()
		{
			if ((Object)(object)ChargingStation.instance == (Object)null)
			{
				return 10;
			}
			return Traverse.Create((object)ChargingStation.instance).Field("maxCrystals").GetValue<int>();
		}

		internal static int GetMaxChargeTotal()
		{
			return GetEnergyPerCrystal() * GetMaxCrystals();
		}

		internal static int CalculateCrystalCount(int chargeTotal)
		{
			int energyPerCrystal = GetEnergyPerCrystal();
			int maxCrystals = GetMaxCrystals();
			return Mathf.Clamp(Mathf.CeilToInt((float)chargeTotal / (float)energyPerCrystal), 0, maxCrystals);
		}

		internal static void SyncStationState(int chargeTotal, int? crystalCount = null)
		{
			if (!((Object)(object)StatsManager.instance == (Object)null))
			{
				int maxChargeTotal = GetMaxChargeTotal();
				int num = Mathf.Clamp(chargeTotal, 0, maxChargeTotal);
				int num2 = crystalCount ?? CalculateCrystalCount(num);
				num2 = Mathf.Clamp(num2, 0, GetMaxCrystals());
				bool flag = false;
				if ((Object)(object)ChargingStation.instance != (Object)null)
				{
					ChargingStation.instance.chargeTotal = num;
					float num3 = (float)num / (float)maxChargeTotal;
					Traverse.Create((object)ChargingStation.instance).Field("chargeFloat").SetValue((object)num3);
					int count = ChargingStation.instance.crystals.Count;
					flag = count > num2;
				}
				if (flag)
				{
					SyncCrystalVisuals(num2);
				}
				if ((Object)(object)ChargingStation.instance != (Object)null)
				{
					Traverse.Create((object)ChargingStation.instance).Field("chargeInt").SetValue((object)num2);
				}
				StatsManager.instance.runStats["chargingStationChargeTotal"] = num;
				StatsManager.instance.runStats["chargingStationCharge"] = num2;
				StatsManager.instance.itemsPurchased["Item Power Crystal"] = num2;
				LastSyncedChargeTotal = num;
				LastSyncedCrystalCount = num2;
				SharedEnergy.LogDebug(string.Format("[SyncStationState] total={0}/{1}, crystals={2}/{3}, runCharge={4}, purchased={5}", num, maxChargeTotal, num2, GetMaxCrystals(), StatsManager.instance.runStats["chargingStationCharge"], StatsManager.instance.itemsPurchased["Item Power Crystal"]));
			}
		}

		internal static void ResetCachedSync()
		{
			LastSyncedChargeTotal = null;
			LastSyncedCrystalCount = null;
		}

		internal static int GetPurchaseBaselineTotal(int rawTotal)
		{
			int num = Mathf.Clamp(rawTotal, 0, GetMaxChargeTotal());
			if (!LastSyncedChargeTotal.HasValue)
			{
				return num;
			}
			return Mathf.Min(num, LastSyncedChargeTotal.Value);
		}

		internal static int GetPurchaseBaselineCrystalCount(int purchasedAfter)
		{
			int num = Mathf.Clamp(purchasedAfter - 1, 0, GetMaxCrystals());
			if (!LastSyncedCrystalCount.HasValue)
			{
				return num;
			}
			return Mathf.Min(num, LastSyncedCrystalCount.Value);
		}

		private static void SyncCrystalVisuals(int targetCrystalCount)
		{
			if ((Object)(object)ChargingStation.instance == (Object)null || SemiFunc.RunIsShop() || !SemiFunc.IsMasterClientOrSingleplayer())
			{
				return;
			}
			int count = ChargingStation.instance.crystals.Count;
			int num = Mathf.Max(0, count - targetCrystalCount);
			if (num <= 0)
			{
				return;
			}
			int num2 = Mathf.Clamp(targetCrystalCount + num, 0, GetMaxCrystals());
			Traverse.Create((object)ChargingStation.instance).Field("chargeInt").SetValue((object)num2);
			StatsManager.instance.runStats["chargingStationCharge"] = num2;
			StatsManager.instance.itemsPurchased["Item Power Crystal"] = num2;
			MethodInfo method = typeof(ChargingStation).GetMethod("DestroyCrystal", BindingFlags.Instance | BindingFlags.NonPublic);
			if (!(method == null))
			{
				for (int i = 0; i < num; i++)
				{
					method.Invoke(ChargingStation.instance, null);
				}
			}
		}
	}
	[HarmonyPatch(typeof(ChargingStation), "Start")]
	public class PatchChargingStationStartNormalize
	{
		private static void Prefix(ChargingStation __instance)
		{
			if (SemiFunc.IsMasterClientOrSingleplayer() && !((Object)(object)StatsManager.instance == (Object)null))
			{
				int value = Traverse.Create((object)__instance).Field("energyPerCrystal").GetValue<int>();
				int value2 = Traverse.Create((object)__instance).Field("maxCrystals").GetValue<int>();
				int num = value * value2;
				int num2 = StatsManager.instance.runStats["chargingStationChargeTotal"];
				int num3 = StatsManager.instance.itemsPurchased["Item Power Crystal"];
				int num4 = Mathf.Clamp(num2, 0, num);
				int num5 = Mathf.Clamp(Mathf.CeilToInt((float)num4 / (float)value), 0, value2);
				int num6 = Mathf.Clamp(Mathf.Max(num3, num5), 0, value2);
				if (num2 != num4 || num3 != num6)
				{
					SharedEnergy.LogDebug($"[ChargingStationStartNormalize] rawTotal={num2}, rawCrystals={num3} -> total={num4}, crystals={num6}");
				}
				PatchBatteryConsume.SyncStationState(num4, num6);
			}
		}
	}
	[HarmonyPatch(typeof(ItemBattery), "Update")]
	public class PatchBatteryContinuousDrain
	{
		internal static readonly Dictionary<int, BatterySnapshot> Saved = new Dictionary<int, BatterySnapshot>();

		internal static readonly Dictionary<int, float> Debt = new Dictionary<int, float>();

		private static void Prefix(ItemBattery __instance)
		{
			if (SemiFunc.IsMasterClientOrSingleplayer() && !SemiFunc.RunIsShop())
			{
				Saved[((Object)__instance).GetInstanceID()] = BatteryStateUtil.Capture(__instance);
			}
		}

		private static void Postfix(ItemBattery __instance)
		{
			if (!SemiFunc.IsMasterClientOrSingleplayer() || (Object)(object)ChargingStation.instance == (Object)null)
			{
				return;
			}
			int instanceID = ((Object)__instance).GetInstanceID();
			if (!Saved.TryGetValue(instanceID, out var value))
			{
				return;
			}
			float num = value.BatteryLife - __instance.batteryLife;
			if (num <= 0f)
			{
				return;
			}
			if (ChargingStation.instance.chargeTotal <= 0)
			{
				Debt.Remove(instanceID);
				return;
			}
			BatteryStateUtil.Restore(__instance, value);
			if (!Debt.TryGetValue(instanceID, out var value2))
			{
				value2 = 0f;
			}
			value2 += num * 20f / 100f;
			if (value2 >= 1f)
			{
				int num2 = Mathf.FloorToInt(value2);
				num2 = Mathf.Min(num2, ChargingStation.instance.chargeTotal);
				PatchBatteryConsume.DrainStation(num2);
				value2 -= (float)num2;
			}
			Debt[instanceID] = value2;
		}
	}
	[HarmonyPatch(typeof(ItemBattery), "FixedUpdate")]
	public class PatchBatteryFixedUpdate
	{
		private static void Prefix(ItemBattery __instance)
		{
			if (SemiFunc.IsMasterClientOrSingleplayer() && !SemiFunc.RunIsShop())
			{
				PatchBatteryContinuousDrain.Saved[((Object)__instance).GetInstanceID()] = BatteryStateUtil.Capture(__instance);
			}
		}

		private static void Postfix(ItemBattery __instance)
		{
			if (!SemiFunc.IsMasterClientOrSingleplayer() || (Object)(object)ChargingStation.instance == (Object)null)
			{
				return;
			}
			int instanceID = ((Object)__instance).GetInstanceID();
			if (!PatchBatteryContinuousDrain.Saved.TryGetValue(instanceID, out var value))
			{
				return;
			}
			float num = value.BatteryLife - __instance.batteryLife;
			if (num <= 0f)
			{
				return;
			}
			if (ChargingStation.instance.chargeTotal <= 0)
			{
				PatchBatteryContinuousDrain.Debt.Remove(instanceID);
				return;
			}
			BatteryStateUtil.Restore(__instance, value);
			if (!PatchBatteryContinuousDrain.Debt.TryGetValue(instanceID, out var value2))
			{
				value2 = 0f;
			}
			value2 += num * 20f / 100f;
			if (value2 >= 1f)
			{
				int num2 = Mathf.FloorToInt(value2);
				num2 = Mathf.Min(num2, ChargingStation.instance.chargeTotal);
				PatchBatteryConsume.DrainStation(num2);
				value2 -= (float)num2;
			}
			PatchBatteryContinuousDrain.Debt[instanceID] = value2;
		}
	}
	[HarmonyPatch(typeof(ItemBattery), "OnDisable")]
	public class PatchBatteryCleanup
	{
		private static void Postfix(ItemBattery __instance)
		{
			int instanceID = ((Object)__instance).GetInstanceID();
			PatchBatteryContinuousDrain.Saved.Remove(instanceID);
			PatchBatteryContinuousDrain.Debt.Remove(instanceID);
			PatchDroneDirectBatteryDrain.Remove(__instance);
		}
	}
	[HarmonyPatch(typeof(ItemMelee), "SwingHitRPC")]
	public class PatchMeleeSwingHit
	{
		private static readonly Dictionary<int, float> Debt = new Dictionary<int, float>();

		private static readonly Dictionary<int, BatterySnapshot> SavedBattery = new Dictionary<int, BatterySnapshot>();

		private static readonly FieldInfo CooldownField = typeof(ItemMelee).GetField("durabilityLossCooldown", BindingFlags.Instance | BindingFlags.NonPublic);

		private static void Prefix(ItemMelee __instance)
		{
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				ItemBattery val = BatteryStateUtil.FindBattery((Component)(object)__instance);
				if (!((Object)(object)val == (Object)null))
				{
					SavedBattery[((Object)__instance).GetInstanceID()] = BatteryStateUtil.Capture(val);
				}
			}
		}

		private static void Postfix(ItemMelee __instance, bool durabilityLoss)
		{
			if (!SemiFunc.IsMasterClientOrSingleplayer() || !durabilityLoss || (Object)(object)ChargingStation.instance == (Object)null)
			{
				return;
			}
			ItemBattery val = BatteryStateUtil.FindBattery((Component)(object)__instance);
			if ((Object)(object)val == (Object)null || ChargingStation.instance.chargeTotal <= 0 || !SavedBattery.TryGetValue(((Object)__instance).GetInstanceID(), out var value))
			{
				return;
			}
			float num = (float)CooldownField.GetValue(__instance);
			if (num <= 0f)
			{
				return;
			}
			float num2 = value.BatteryLife - val.batteryLife;
			if (!(num2 <= 0f))
			{
				SharedEnergy.LogDebug($"[PatchMeleeSwingHit] name={((Object)((Component)__instance).gameObject).name}, drain={num2}, before={value.BatteryLife}, after={val.batteryLife}, station={ChargingStation.instance.chargeTotal}");
				BatteryStateUtil.Restore(val, value);
				int instanceID = ((Object)__instance).GetInstanceID();
				if (!Debt.TryGetValue(instanceID, out var value2))
				{
					value2 = 0f;
				}
				value2 += num2 * 20f / 100f;
				if (value2 >= 1f)
				{
					int num3 = Mathf.FloorToInt(value2);
					num3 = Mathf.Min(num3, ChargingStation.instance.chargeTotal);
					PatchBatteryConsume.DrainStation(num3);
					value2 -= (float)num3;
				}
				Debt[instanceID] = value2;
			}
		}

		internal static void Remove(int id)
		{
			Debt.Remove(id);
			SavedBattery.Remove(id);
		}

		internal static void Clear()
		{
			Debt.Clear();
			SavedBattery.Clear();
		}
	}
	[HarmonyPatch(typeof(ItemMelee), "EnemyOrPVPSwingHitRPC")]
	public class PatchMeleeEnemySwingHit
	{
		private static readonly Dictionary<int, float> Debt = new Dictionary<int, float>();

		private static readonly Dictionary<int, BatterySnapshot> SavedBattery = new Dictionary<int, BatterySnapshot>();

		private static void Prefix(ItemMelee __instance)
		{
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				ItemBattery val = BatteryStateUtil.FindBattery((Component)(object)__instance);
				if (!((Object)(object)val == (Object)null))
				{
					SavedBattery[((Object)__instance).GetInstanceID()] = BatteryStateUtil.Capture(val);
				}
			}
		}

		private static void Postfix(ItemMelee __instance, bool _playerHit)
		{
			if (!SemiFunc.IsMasterClientOrSingleplayer() || (Object)(object)ChargingStation.instance == (Object)null)
			{
				return;
			}
			ItemBattery val = BatteryStateUtil.FindBattery((Component)(object)__instance);
			if ((Object)(object)val == (Object)null || ChargingStation.instance.chargeTotal <= 0 || !SavedBattery.TryGetValue(((Object)__instance).GetInstanceID(), out var value))
			{
				return;
			}
			float num = value.BatteryLife - val.batteryLife;
			if (!(num <= 0f))
			{
				SharedEnergy.LogDebug($"[PatchMeleeEnemySwingHit] name={((Object)((Component)__instance).gameObject).name}, playerHit={_playerHit}, drain={num}, before={value.BatteryLife}, after={val.batteryLife}, station={ChargingStation.instance.chargeTotal}");
				BatteryStateUtil.Restore(val, value);
				int instanceID = ((Object)__instance).GetInstanceID();
				if (!Debt.TryGetValue(instanceID, out var value2))
				{
					value2 = 0f;
				}
				value2 += num * 20f / 100f;
				if (value2 >= 1f)
				{
					int num2 = Mathf.FloorToInt(value2);
					num2 = Mathf.Min(num2, ChargingStation.instance.chargeTotal);
					PatchBatteryConsume.DrainStation(num2);
					value2 -= (float)num2;
				}
				Debt[instanceID] = value2;
			}
		}

		internal static void Remove(int id)
		{
			Debt.Remove(id);
			SavedBattery.Remove(id);
		}

		internal static void Clear()
		{
			Debt.Clear();
			SavedBattery.Clear();
		}
	}
	[HarmonyPatch(typeof(StatsManager), "ItemPurchase")]
	public class PatchCrystalPurchase
	{
		private static void Postfix(string itemName)
		{
			if (SemiFunc.IsMasterClientOrSingleplayer() && !(itemName != "Item Power Crystal") && !((Object)(object)StatsManager.instance == (Object)null))
			{
				int num = StatsManager.instance.runStats["chargingStationChargeTotal"];
				int num2 = Mathf.Max(StatsManager.instance.itemsPurchased["Item Power Crystal"], 0);
				int purchaseBaselineTotal = PatchBatteryConsume.GetPurchaseBaselineTotal(num);
				int energyPerCrystal = PatchBatteryConsume.GetEnergyPerCrystal();
				int purchaseBaselineCrystalCount = PatchBatteryConsume.GetPurchaseBaselineCrystalCount(num2);
				int num3 = Mathf.Min(PatchBatteryConsume.GetMaxCrystals(), purchaseBaselineCrystalCount + 1);
				int num4 = Mathf.Min(num3 * energyPerCrystal, PatchBatteryConsume.GetMaxChargeTotal());
				int num5 = Mathf.Clamp(purchaseBaselineTotal + energyPerCrystal, 0, num4);
				SharedEnergy.LogDebug($"[PatchCrystalPurchase] rawTotal={num}, baselineTotal={purchaseBaselineTotal}, purchasedAfter={num2}, baselineCrystals={purchaseBaselineCrystalCount}, energyPerCrystal={energyPerCrystal}, crystalsAfterPurchase={num3}, maxForCrystals={num4}, targetTotal={num5}");
				PatchBatteryConsume.SyncStationState(num5, num3);
			}
		}
	}
	[HarmonyPatch]
	public static class PatchDroneDirectBatteryDrain
	{
		private static readonly Dictionary<int, BatterySnapshot> Saved = new Dictionary<int, BatterySnapshot>();

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

		internal static void Capture(ItemBattery itemBattery)
		{
			if (SemiFunc.IsMasterClientOrSingleplayer() && !((Object)(object)itemBattery == (Object)null))
			{
				Saved[((Object)itemBattery).GetInstanceID()] = BatteryStateUtil.Capture(itemBattery);
			}
		}

		internal static void Redirect(ItemBattery itemBattery, string source)
		{
			if (!SemiFunc.IsMasterClientOrSingleplayer() || (Object)(object)itemBattery == (Object)null)
			{
				return;
			}
			int instanceID = ((Object)itemBattery).GetInstanceID();
			if (!Saved.TryGetValue(instanceID, out var value))
			{
				return;
			}
			float num = value.BatteryLife - itemBattery.batteryLife;
			if (!(num <= 0f) && !((Object)(object)ChargingStation.instance == (Object)null) && ChargingStation.instance.chargeTotal > 0)
			{
				SharedEnergy.LogDebug($"[PatchDroneDirectBatteryDrain] source={source}, name={((Object)((Component)itemBattery).gameObject).name}, drain={num}, before={value.BatteryLife}, after={itemBattery.batteryLife}, station={ChargingStation.instance.chargeTotal}");
				BatteryStateUtil.Restore(itemBattery, value);
				if (!Debt.TryGetValue(instanceID, out var value2))
				{
					value2 = 0f;
				}
				value2 += num * 20f / 100f;
				if (value2 >= 1f)
				{
					int num2 = Mathf.FloorToInt(value2);
					num2 = Mathf.Min(num2, ChargingStation.instance.chargeTotal);
					PatchBatteryConsume.DrainStation(num2);
					value2 -= (float)num2;
				}
				Debt[instanceID] = value2;
			}
		}

		internal static void Remove(ItemBattery itemBattery)
		{
			if (!((Object)(object)itemBattery == (Object)null))
			{
				int instanceID = ((Object)itemBattery).GetInstanceID();
				Saved.Remove(instanceID);
				Debt.Remove(instanceID);
			}
		}

		internal static void Clear()
		{
			Saved.Clear();
			Debt.Clear();
		}
	}
	[HarmonyPatch(typeof(ItemDroneFeather), "BatteryDrain")]
	public class PatchDroneFeatherBatteryDrain
	{
		private static void Prefix(ItemDroneFeather __instance)
		{
			ItemBattery val = BatteryStateUtil.FindBattery((Component)(object)__instance);
			if (!((Object)(object)val == (Object)null))
			{
				PatchDroneDirectBatteryDrain.Capture(val);
			}
		}

		private static void Postfix(ItemDroneFeather __instance)
		{
			ItemBattery val = BatteryStateUtil.FindBattery((Component)(object)__instance);
			if (!((Object)(object)val == (Object)null))
			{
				PatchDroneDirectBatteryDrain.Redirect(val, "ItemDroneFeather");
			}
		}
	}
	[HarmonyPatch(typeof(ItemDroneTorque), "BatteryDrain")]
	public class PatchDroneTorqueBatteryDrain
	{
		private static void Prefix(ItemDroneTorque __instance)
		{
			ItemBattery val = BatteryStateUtil.FindBattery((Component)(object)__instance);
			if (!((Object)(object)val == (Object)null))
			{
				PatchDroneDirectBatteryDrain.Capture(val);
			}
		}

		private static void Postfix(ItemDroneTorque __instance)
		{
			ItemBattery val = BatteryStateUtil.FindBattery((Component)(object)__instance);
			if (!((Object)(object)val == (Object)null))
			{
				PatchDroneDirectBatteryDrain.Redirect(val, "ItemDroneTorque");
			}
		}
	}
	[HarmonyPatch(typeof(ItemDroneZeroGravity), "Update")]
	public class PatchDroneZeroGravityUpdate
	{
		private static void Prefix(ItemDroneZeroGravity __instance)
		{
			ItemBattery val = BatteryStateUtil.FindBattery((Component)(object)__instance);
			if (!((Object)(object)val == (Object)null))
			{
				PatchDroneDirectBatteryDrain.Capture(val);
			}
		}

		private static void Postfix(ItemDroneZeroGravity __instance)
		{
			ItemBattery val = BatteryStateUtil.FindBattery((Component)(object)__instance);
			if (!((Object)(object)val == (Object)null))
			{
				PatchDroneDirectBatteryDrain.Redirect(val, "ItemDroneZeroGravity.Update");
			}
		}
	}
	[HarmonyPatch(typeof(ItemDroneZeroGravity), "FixedUpdate")]
	public class PatchDroneZeroGravityFixedUpdate
	{
		private static void Prefix(ItemDroneZeroGravity __instance)
		{
			ItemBattery val = BatteryStateUtil.FindBattery((Component)(object)__instance);
			if (!((Object)(object)val == (Object)null))
			{
				PatchDroneDirectBatteryDrain.Capture(val);
			}
		}

		private static void Postfix(ItemDroneZeroGravity __instance)
		{
			ItemBattery val = BatteryStateUtil.FindBattery((Component)(object)__instance);
			if (!((Object)(object)val == (Object)null))
			{
				PatchDroneDirectBatteryDrain.Redirect(val, "ItemDroneZeroGravity.FixedUpdate");
			}
		}
	}
	[HarmonyPatch(typeof(ChargingStation), "ChargingStationCrystalBrokenRPC")]
	public class PatchChargingStationCrystalBrokenClamp
	{
		private static void Postfix()
		{
			if (!((Object)(object)StatsManager.instance == (Object)null))
			{
				int num = StatsManager.instance.itemsPurchased["Item Power Crystal"];
				if (num < 0)
				{
					StatsManager.instance.itemsPurchased["Item Power Crystal"] = 0;
					SharedEnergy.LogDebug("[ChargingStationCrystalBrokenClamp] corrected negative crystal count back to 0");
				}
			}
		}
	}
	[HarmonyPatch(typeof(ItemMelee), "Start")]
	public class PatchMeleeInstanceInit
	{
		private static void Postfix(ItemMelee __instance)
		{
			int instanceID = ((Object)__instance).GetInstanceID();
			PatchMeleeSwingHit.Remove(instanceID);
			PatchMeleeEnemySwingHit.Remove(instanceID);
		}
	}
	[HarmonyPatch(typeof(StatsManager), "ResetAllStats")]
	public class PatchStatsResetCleanup
	{
		private static void Prefix()
		{
			PatchBatteryConsume.ResetCachedSync();
			PatchBatteryContinuousDrain.Saved.Clear();
			PatchBatteryContinuousDrain.Debt.Clear();
			PatchDroneDirectBatteryDrain.Clear();
			PatchMeleeSwingHit.Clear();
			PatchMeleeEnemySwingHit.Clear();
		}
	}
	[HarmonyPatch(typeof(StatsManager), "LoadGame")]
	public class PatchStatsLoadCleanup
	{
		private static void Prefix()
		{
			PatchBatteryConsume.ResetCachedSync();
			PatchBatteryContinuousDrain.Saved.Clear();
			PatchBatteryContinuousDrain.Debt.Clear();
			PatchDroneDirectBatteryDrain.Clear();
			PatchMeleeSwingHit.Clear();
			PatchMeleeEnemySwingHit.Clear();
		}
	}
	[BepInPlugin("Misemise.SharedEnergy", "SharedEnergy", "1.0")]
	public class SharedEnergy : BaseUnityPlugin
	{
		internal static readonly bool EnableDebugLogging;

		internal static SharedEnergy Instance { get; private set; }

		internal static ManualLogSource Logger => Instance._logger;

		private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger;

		internal Harmony? Harmony { get; set; }

		internal static void LogDebug(string message)
		{
			if (EnableDebugLogging)
			{
				Logger.LogInfo((object)message);
			}
		}

		private void Awake()
		{
			Instance = this;
			((Component)this).gameObject.transform.parent = null;
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			Patch();
			Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} has loaded!");
		}

		internal void Patch()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_0026: Expected O, but got Unknown
			if (Harmony == null)
			{
				Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID);
				Harmony val2 = val;
				Harmony = val;
			}
			Harmony.PatchAll();
		}

		internal void Unpatch()
		{
			Harmony? harmony = Harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		private void Update()
		{
		}
	}
}