Decompiled source of VapuFastpit v1.0.0

VapuFastpit.dll

Decompiled 8 hours 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 BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Extensions;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mirror;
using UnityEngine;
using UnityEngine.SceneManagement;
using VapuFastpit.Patches;
using VapuFastpit.Patches.PitStop;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyVersion("0.0.0.0")]
[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 VapuFastpit
{
	[BepInPlugin("vapu.fastpit", "VapuFastpit", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string ModGuid = "vapu.fastpit";

		public const string ModName = "VapuFastpit";

		public const string ModVersion = "1.0.0";

		internal static ManualLogSource Log;

		internal static ConfigEntry<float> CountdownSeconds;

		internal static ConfigEntry<bool> LowerPlayerThreshold;

		internal static ConfigEntry<bool> AutoSkipGameOverAnimation;

		internal static ConfigEntry<bool> AutoJumpInLosePit;

		internal static ConfigEntry<float> AutoJumpDelay;

		private void Awake()
		{
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: 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)
			Log = ((BaseUnityPlugin)this).Logger;
			CountdownSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Pit Stop", "CountdownSeconds", 0.2f, "Replacement for AllPlayersTriggerZone.delayBeforeEvent (the pit-stop / leave-casino countdown). Vanilla is several seconds. Set to 0 for instant.");
			LowerPlayerThreshold = ((BaseUnityPlugin)this).Config.Bind<bool>("Pit Stop", "TriggerOnAnyPlayerInZone", true, "If true, the trigger zone fires when at least one player is in the zone instead of requiring all players. Useful in solo or when teammates are AFK in the pit stop.");
			AutoSkipGameOverAnimation = ((BaseUnityPlugin)this).Config.Bind<bool>("GameOver", "AutoSkipAnimation", true, "If true, auto-fills GameOverUI's pending skip counter so each animated phase (intro, contributions, totals) completes instantly while still firing its end-state callbacks. The final result screen still appears - only the long animated buildup is skipped.");
			AutoJumpInLosePit = ((BaseUnityPlugin)this).Config.Bind<bool>("GameOver", "AutoJumpInPit", true, "If true, on LoseStateScene load the host server auto-triggers the SceneSwitcher that normally fires when all players have jumped into the pit. Skips the 'walk to the pit and drop in' step. Host-only effect.");
			AutoJumpDelay = ((BaseUnityPlugin)this).Config.Bind<float>("GameOver", "AutoJumpDelaySeconds", 1.5f, "Seconds to wait after LoseStateScene loads before auto-triggering the pit SceneSwitcher. Gives LoseInitializeRoutine and player spawn time to finish.");
			SceneManager.sceneLoaded += OnSceneLoaded;
			Harmony val = new Harmony("vapu.fastpit");
			val.PatchAll(typeof(AllPlayersTriggerZone_FastCountdown));
			val.PatchAll(typeof(AllPlayersTriggerZone_PlayerThreshold));
			val.PatchAll(typeof(GameOverUI_AutoSkip));
			Log.LogInfo((object)string.Format("{0} v{1} loaded. PitCountdown={2}s AnyPlayer={3} AutoSkipGO={4} AutoJumpPit={5}", "VapuFastpit", "1.0.0", CountdownSeconds.Value, LowerPlayerThreshold.Value, AutoSkipGameOverAnimation.Value, AutoJumpInLosePit.Value));
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			if (AutoJumpInLosePit.Value && !(((Scene)(ref scene)).name != "LoseStateScene"))
			{
				if (!NetworkServer.active)
				{
					Log.LogDebug((object)"LoseStateScene loaded but we are not the server; skipping auto-jump.");
				}
				else
				{
					((MonoBehaviour)this).StartCoroutine(AutoTriggerLosePitRoutine());
				}
			}
		}

		private IEnumerator AutoTriggerLosePitRoutine()
		{
			yield return (object)new WaitForSeconds(Mathf.Max(0f, AutoJumpDelay.Value));
			for (int attempt = 0; attempt < 20; attempt++)
			{
				if (!NetworkServer.active)
				{
					yield break;
				}
				SceneSwitcher val = ((IEnumerable<SceneSwitcher>)Object.FindObjectsByType<SceneSwitcher>((FindObjectsSortMode)0)).FirstOrDefault((Func<SceneSwitcher, bool>)((SceneSwitcher s) => (Object)(object)s != (Object)null));
				if ((Object)(object)val != (Object)null)
				{
					Log.LogInfo((object)$"Auto-jumping pit: invoking SceneSwitcher.ServerProgressSceneWithoutInteraction on '{((Object)val).name}' (attempt {attempt + 1}).");
					try
					{
						val.ServerProgressSceneWithoutInteraction();
						yield break;
					}
					catch (Exception arg)
					{
						Log.LogError((object)$"SceneSwitcher invoke failed: {arg}");
						yield break;
					}
				}
				yield return (object)new WaitForSeconds(0.25f);
			}
			Log.LogWarning((object)"AutoJumpInPit: no SceneSwitcher found in LoseStateScene after 20 attempts.");
		}
	}
}
namespace VapuFastpit.Patches
{
	[HarmonyPatch(typeof(GameOverUI), "Show")]
	public static class GameOverUI_AutoSkip
	{
		private static readonly FieldRef<GameOverUI, int> PendingRef = AccessTools.FieldRefAccess<GameOverUI, int>("_pendingSegmentSkips");

		[HarmonyPostfix]
		public static void Postfix(GameOverUI __instance)
		{
			if (Plugin.AutoSkipGameOverAnimation.Value)
			{
				((MonoBehaviour)__instance).StartCoroutine(KeepSkipping(__instance));
				Plugin.Log.LogDebug((object)"GameOverUI.Show: auto-skip coroutine started");
			}
		}

		private static IEnumerator KeepSkipping(GameOverUI ui)
		{
			for (int i = 0; i < 600; i++)
			{
				if (!((Object)(object)ui != (Object)null))
				{
					break;
				}
				if (!((Behaviour)ui).isActiveAndEnabled)
				{
					break;
				}
				PendingRef.Invoke(ui) = 64;
				yield return null;
			}
		}
	}
}
namespace VapuFastpit.Patches.PitStop
{
	[HarmonyPatch(typeof(AllPlayersTriggerZone), "OnStartClient")]
	public static class AllPlayersTriggerZone_FastCountdown
	{
		[HarmonyPostfix]
		public static void Postfix(AllPlayersTriggerZone __instance)
		{
			float num = Mathf.Max(0f, Plugin.CountdownSeconds.Value);
			FieldInfo fieldInfo = AccessTools.Field(typeof(AllPlayersTriggerZone), "delayBeforeEvent");
			if (fieldInfo != null)
			{
				fieldInfo.SetValue(__instance, num);
			}
			FieldInfo fieldInfo2 = AccessTools.Field(typeof(AllPlayersTriggerZone), "colliderCheckInterval");
			if (fieldInfo2 != null && (float)fieldInfo2.GetValue(__instance) > 0.1f)
			{
				fieldInfo2.SetValue(__instance, 0.1f);
			}
			Plugin.Log.LogDebug((object)$"AllPlayersTriggerZone '{((Object)__instance).name}' patched: delayBeforeEvent={num}s");
		}
	}
	[HarmonyPatch(typeof(AllPlayersTriggerZone), "CheckPlayers")]
	public static class AllPlayersTriggerZone_PlayerThreshold
	{
		private static readonly FieldRef<AllPlayersTriggerZone, bool> HasTriggeredRef = AccessTools.FieldRefAccess<AllPlayersTriggerZone, bool>("_hasTriggered");

		private static readonly FieldRef<AllPlayersTriggerZone, float> LastCheckTimeRef = AccessTools.FieldRefAccess<AllPlayersTriggerZone, float>("_lastCheckTime");

		private static readonly FieldRef<AllPlayersTriggerZone, float> CheckIntervalRef = AccessTools.FieldRefAccess<AllPlayersTriggerZone, float>("colliderCheckInterval");

		private static readonly FieldRef<AllPlayersTriggerZone, Collider> CheckColliderRef = AccessTools.FieldRefAccess<AllPlayersTriggerZone, Collider>("checkCollider");

		private static readonly FieldRef<AllPlayersTriggerZone, Coroutine> CountdownRoutineRef = AccessTools.FieldRefAccess<AllPlayersTriggerZone, Coroutine>("_countdownRoutine");

		private static readonly MethodInfo RpcUpdateCountdownTextMI = AccessTools.Method(typeof(AllPlayersTriggerZone), "RpcUpdateCountdownText", (Type[])null, (Type[])null);

		private static readonly MethodInfo CountdownRoutineMI = AccessTools.Method(typeof(AllPlayersTriggerZone), "CountdownRoutine", (Type[])null, (Type[])null);

		[HarmonyPrefix]
		public static bool Prefix(AllPlayersTriggerZone __instance)
		{
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.LowerPlayerThreshold.Value)
			{
				return true;
			}
			if (!__instance.IsActive)
			{
				return false;
			}
			if (HasTriggeredRef.Invoke(__instance))
			{
				return false;
			}
			LocalManager instance = MonoSingleton<LocalManager>.Instance;
			if ((Object)(object)instance == (Object)null || instance.players == null || instance.players.Count == 0)
			{
				return false;
			}
			if (Time.time - LastCheckTimeRef.Invoke(__instance) < CheckIntervalRef.Invoke(__instance))
			{
				return false;
			}
			LastCheckTimeRef.Invoke(__instance) = Time.time;
			Collider val = CheckColliderRef.Invoke(__instance);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			Bounds bounds = val.bounds;
			bool flag = false;
			foreach (PlayerReferences player in instance.players)
			{
				if (player != null && !((Object)(object)player.transform == (Object)null) && ((Bounds)(ref bounds)).Contains(player.transform.position))
				{
					flag = true;
					break;
				}
			}
			if (!flag)
			{
				if (CountdownRoutineRef.Invoke(__instance) != null)
				{
					((MonoBehaviour)__instance).StopCoroutine(CountdownRoutineRef.Invoke(__instance));
					CountdownRoutineRef.Invoke(__instance) = null;
					RpcUpdateCountdownTextMI?.Invoke(__instance, new object[1] { false });
				}
				return false;
			}
			if (CountdownRoutineRef.Invoke(__instance) == null && CountdownRoutineMI != null)
			{
				IEnumerator enumerator2 = (IEnumerator)CountdownRoutineMI.Invoke(__instance, null);
				CountdownRoutineRef.Invoke(__instance) = ((MonoBehaviour)__instance).StartCoroutine(enumerator2);
			}
			return false;
		}
	}
}