Decompiled source of AutoRechargeHelper v0.1.5

plugins/AutoRechargeHelper.dll

Decompiled 2 months 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 UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("Kai")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("AutoRechargeHelper")]
[assembly: AssemblyTitle("AutoRechargeHelper")]
[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 AutoRechargeHelper
{
	[BepInPlugin("Kai.AutoRechargeHelper", "AutoRechargeHelper", "0.2.6")]
	public class AutoRechargeHelper : BaseUnityPlugin
	{
		internal sealed class ARHRunner : MonoBehaviour
		{
			private static ARHRunner _inst;

			public static ARHRunner Ensure()
			{
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				//IL_001e: Expected O, but got Unknown
				if ((Object)(object)_inst != (Object)null)
				{
					return _inst;
				}
				GameObject val = new GameObject("AutoRechargeHelper.Runner");
				Object.DontDestroyOnLoad((Object)(object)val);
				_inst = val.AddComponent<ARHRunner>();
				LogX.Info("[ARH] Runner created.");
				return _inst;
			}

			public static void Run(IEnumerator routine)
			{
				((MonoBehaviour)Ensure()).StartCoroutine(routine);
			}
		}

		public static ConfigEntry<bool> EnableMod;

		public static ConfigEntry<bool> FirstTimeOnly;

		public static ConfigEntry<string> BlacklistItems;

		public static ConfigEntry<bool> EnableLogging;

		private static HashSet<string> BlacklistSet = new HashSet<string>();

		internal static AutoRechargeHelper Instance { get; private set; } = null;


		internal static ManualLogSource Logger => Instance._logger;

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

		internal Harmony? Harmony { get; set; }

		private void Awake()
		{
			Instance = this;
			LoadConfig();
			Patch();
			Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} loaded with config support.");
		}

		private void LoadConfig()
		{
			EnableMod = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableMod", true, "Mod全体の有効化 / Enable or disable this mod.");
			FirstTimeOnly = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "FirstTimeOnly", true, "初回のみマークし、満充電後は再充電しない / Mark batteries only once; disable recharging after fully charged.");
			BlacklistItems = ((BaseUnityPlugin)this).Config.Bind<string>("General", "Blacklist", "Rubber Duck", "自動充電対象から除外するアイテム名(部分一致、カンマ区切り) / Exclude specific items from auto-recharge (partial match, comma-separated).");
			EnableLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "EnableLogging", false, "ログ出力を有効化 / Enable detailed log output.");
			ParseBlacklist();
		}

		internal static void SetInstance(AutoRechargeHelper helper)
		{
			Instance = helper;
		}

		private static void ParseBlacklist()
		{
			BlacklistSet = (from x in BlacklistItems.Value.Split(',')
				select x.Trim().ToLowerInvariant() into x
				where !string.IsNullOrEmpty(x)
				select x).ToHashSet();
		}

		public static bool IsBlacklisted(string itemName)
		{
			if (string.IsNullOrEmpty(itemName))
			{
				return false;
			}
			string name = itemName.Replace("(Clone)", "").ToLowerInvariant();
			return BlacklistSet.Any((string bad) => name.Contains(bad));
		}

		internal void Patch()
		{
			//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)
			//IL_0020: Expected O, but got Unknown
			//IL_0025: 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();
			}
		}
	}
	internal static class LogX
	{
		public static void Info(string msg)
		{
			if (AutoRechargeHelper.EnableLogging.Value)
			{
				AutoRechargeHelper.Logger.LogInfo((object)msg);
			}
		}

		public static void Warn(string msg)
		{
			if (AutoRechargeHelper.EnableLogging.Value)
			{
				AutoRechargeHelper.Logger.LogWarning((object)msg);
			}
		}

		public static void Error(string msg)
		{
			if (AutoRechargeHelper.EnableLogging.Value)
			{
				AutoRechargeHelper.Logger.LogError((object)msg);
			}
		}
	}
	public static class AutoRechargeRuntime
	{
		private static readonly HashSet<ItemBattery> Marked = new HashSet<ItemBattery>();

		private static readonly HashSet<ItemBattery> Finished = new HashSet<ItemBattery>();

		public static IEnumerable<ItemBattery> MarkedBatteries => Marked;

		public static bool IsMarked(ItemBattery b)
		{
			if ((Object)(object)b != (Object)null)
			{
				return Marked.Contains(b);
			}
			return false;
		}

		public static bool IsFinished(ItemBattery b)
		{
			if ((Object)(object)b != (Object)null)
			{
				return Finished.Contains(b);
			}
			return false;
		}

		public static void ClearMarks()
		{
			Marked.Clear();
			Finished.Clear();
		}

		public static void MarkBattery(ItemBattery battery)
		{
			if (AutoRechargeHelper.EnableMod.Value && !((Object)(object)battery == (Object)null) && !AutoRechargeHelper.IsBlacklisted(((Object)battery).name) && !Marked.Contains(battery) && (!AutoRechargeHelper.FirstTimeOnly.Value || !Finished.Contains(battery)))
			{
				Marked.Add(battery);
				if (AutoRechargeHelper.EnableLogging.Value)
				{
					LogX.Info("[ARH] Marked " + ((Object)battery).name);
				}
			}
		}

		public static void UnmarkBattery(ItemBattery battery)
		{
			if (!((Object)(object)battery == (Object)null) && AutoRechargeHelper.FirstTimeOnly.Value && Marked.Remove(battery))
			{
				Finished.Add(battery);
				if (AutoRechargeHelper.EnableLogging.Value)
				{
					LogX.Info("[ARH] Unmarked " + ((Object)battery).name + " (fully charged, locked)");
				}
			}
		}

		public static void Tick()
		{
			if (!AutoRechargeHelper.EnableMod.Value || !AutoRechargeHelper.FirstTimeOnly.Value)
			{
				return;
			}
			foreach (ItemBattery item in Marked.ToList())
			{
				if (!((Object)(object)item == (Object)null) && item.batteryLifeInt >= item.batteryBars)
				{
					UnmarkBattery(item);
				}
			}
		}
	}
	[HarmonyPatch(typeof(LevelGenerator), "GenerateDone")]
	public static class LevelGeneratorGenerateDonePatch
	{
		[CompilerGenerated]
		private sealed class <SafePostGenerationStartup>d__1 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <SafePostGenerationStartup>d__1(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_007a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0084: Expected O, but got Unknown
				//IL_0050: Unknown result type (might be due to invalid IL or missing references)
				//IL_005a: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					LogX.Info("[ARH] SafePostGenerationStartup: コルーチン開始");
					<>2__current = (object)new WaitUntil((Func<bool>)delegate
					{
						//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)
						if ((Object)(object)GameDirector.instance != (Object)null && (Object)(object)RunManager.instance != (Object)null)
						{
							Scene activeScene = SceneManager.GetActiveScene();
							return ((Scene)(ref activeScene)).isLoaded;
						}
						return false;
					});
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					LogX.Info("[ARH] SafePostGenerationStartup: 初期化完了");
					<>2__current = (object)new WaitForSeconds(1f);
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -1;
					if (!IsLobbyOrTruckSafe())
					{
						LogX.Info("[ARH] SafeLobbyStartup: ロビー判定NG");
						return false;
					}
					LogX.Info("[ARH] SafeLobbyStartup: SetupLobbyCharging 実行");
					<>2__current = SetupLobbyCharging();
					<>1__state = 3;
					return true;
				case 3:
					<>1__state = -1;
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <SetupLobbyCharging>d__4 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			private float <timer>5__2;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <SetupLobbyCharging>d__4(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_002a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0034: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<timer>5__2 = 0f;
					break;
				case 1:
					<>1__state = -1;
					<timer>5__2 += 0.2f;
					break;
				}
				if (Object.FindObjectsOfType<ItemBattery>().Length == 0 && <timer>5__2 < 5f)
				{
					<>2__current = (object)new WaitForSeconds(0.2f);
					<>1__state = 1;
					return true;
				}
				AutoRechargeRuntime.ClearMarks();
				ItemBattery[] array = Object.FindObjectsOfType<ItemBattery>();
				int num = 0;
				ItemBattery[] array2 = array;
				foreach (ItemBattery val in array2)
				{
					if (!((Object)(object)val == (Object)null) && !AutoRechargeHelper.IsBlacklisted(((Object)val).name) && (!AutoRechargeRuntime.IsFinished(val) || !AutoRechargeHelper.FirstTimeOnly.Value) && (val.batteryLifeInt < val.batteryBars || !AutoRechargeHelper.FirstTimeOnly.Value))
					{
						AutoRechargeRuntime.MarkBattery(val);
						num++;
						if (AutoRechargeHelper.EnableLogging.Value)
						{
							LogX.Info("[ARH] Marked " + ((Object)val).name);
						}
					}
				}
				LogX.Info($"[ARH] {num} batteries marked for remote charge.");
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[HarmonyPostfix]
		public static void AfterGenerateDone()
		{
			if (AutoRechargeHelper.EnableMod.Value)
			{
				LogX.Info("[ARH] LevelGenerator.GenerateDone: Detected. Starting post-generation setup.");
				AutoRechargeHelper.ARHRunner.Run(SafePostGenerationStartup());
			}
		}

		[IteratorStateMachine(typeof(<SafePostGenerationStartup>d__1))]
		private static IEnumerator SafePostGenerationStartup()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <SafePostGenerationStartup>d__1(0);
		}

		private static bool IsMasterOrSingleplayerSafe()
		{
			try
			{
				return SemiFunc.IsMasterClientOrSingleplayer();
			}
			catch (Exception ex)
			{
				LogX.Warn("[ARH] SemiFunc.IsMasterClientOrSingleplayer() failed: " + ex.Message);
				return false;
			}
		}

		private static bool IsLobbyOrTruckSafe()
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				RunManager instance = RunManager.instance;
				if ((Object)(object)instance == (Object)null)
				{
					return false;
				}
				Level levelCurrent = instance.levelCurrent;
				if ((Object)(object)levelCurrent == (Object)null)
				{
					return false;
				}
				string name = ((Object)levelCurrent).name;
				if (name == null)
				{
					Scene activeScene = SceneManager.GetActiveScene();
					name = ((Scene)(ref activeScene)).name;
				}
				string text = name;
				return text.IndexOf("Lobby", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Track", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Truck", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			catch
			{
				return false;
			}
		}

		[IteratorStateMachine(typeof(<SetupLobbyCharging>d__4))]
		private static IEnumerator SetupLobbyCharging()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <SetupLobbyCharging>d__4(0);
		}
	}
	[HarmonyPatch(typeof(ChargingStation), "ChargeAreaCheck")]
	public static class ChargingStationExtendPatch
	{
		[HarmonyPostfix]
		public static void AddMarkedAfterScan(ChargingStation __instance)
		{
			if (!AutoRechargeHelper.EnableMod.Value || (Object)(object)__instance == (Object)null || __instance.chargeFloat <= 0f)
			{
				return;
			}
			foreach (ItemBattery markedBattery in AutoRechargeRuntime.MarkedBatteries)
			{
				if (!((Object)(object)markedBattery == (Object)null) && !AutoRechargeRuntime.IsFinished(markedBattery) && !__instance.itemsCharging.Contains(markedBattery) && markedBattery.batteryLifeInt < markedBattery.batteryBars)
				{
					__instance.itemsCharging.Add(markedBattery);
				}
			}
		}
	}
	[HarmonyPatch(typeof(ChargingStation), "Update")]
	public static class ChargingStationStopPatch
	{
		[HarmonyPostfix]
		public static void MonitorAndUnmark(ChargingStation __instance)
		{
			if (AutoRechargeHelper.EnableMod.Value && !((Object)(object)__instance == (Object)null) && !((Object)(object)RunManager.instance == (Object)null) && !RunManager.instance.restarting)
			{
				AutoRechargeRuntime.Tick();
			}
		}
	}
}