Decompiled source of Practice Mod v1.2.0

plugins/KZPracticeMod/KZPracticeMod.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("KZPracticeMod")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("KZPracticeMod")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("29afc198-4944-40e8-b98c-93f884fcc30c")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
[BepInPlugin("com.drama.KZPracticeMod", "Practice Mod", "1.2.0")]
public class PracticeMod : BaseUnityPlugin
{
	private struct Checkpoint
	{
		public Vector3 pos;

		public float pitch;

		public float yaw;

		public static Checkpoint FromCurrentState(GameObject player, MonoBehaviour playerComponent, FieldInfo yawFieldInfo)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			Checkpoint result = default(Checkpoint);
			result.pos = player.transform.position;
			Quaternion localRotation = player.transform.localRotation;
			result.pitch = ((Quaternion)(ref localRotation)).eulerAngles.y;
			result.yaw = (float)yawFieldInfo.GetValue(playerComponent);
			return result;
		}
	}

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

		private object <>2__current;

		public float delay;

		public PracticeMod <>4__this;

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

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

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

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

		private bool MoveNext()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			int num = <>1__state;
			PracticeMod practiceMod = <>4__this;
			switch (num)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<>2__current = (object)new WaitForSeconds(delay);
				<>1__state = 1;
				return true;
			case 1:
				<>1__state = -1;
				practiceMod.RegisterConsoleCommands();
				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 <RegisterCommandsDelayed>d__58 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public PracticeMod <>4__this;

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

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

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

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

		private bool MoveNext()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Expected O, but got Unknown
			int num = <>1__state;
			PracticeMod practiceMod = <>4__this;
			switch (num)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<>2__current = (object)new WaitForSeconds(2f);
				<>1__state = 1;
				return true;
			case 1:
				<>1__state = -1;
				practiceMod.RegisterConsoleCommands();
				<>2__current = (object)new WaitForSeconds(3f);
				<>1__state = 2;
				return true;
			case 2:
				<>1__state = -1;
				practiceMod.RegisterConsoleCommands();
				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();
		}
	}

	private const float MIN_TIMESCALE = 0.1f;

	private const float MAX_TIMESCALE = 10f;

	private const float TIMESCALE_INCREMENT = 0.1f;

	private const float DEFAULT_TIMESCALE = 1f;

	private const int MENU_FONT_SIZE = 18;

	private const float MENU_LINE_HEIGHT = 23f;

	private const float MENU_OFFSET_X = 25f;

	private const float INITIAL_REGISTRATION_DELAY = 2f;

	private const float SECONDARY_REGISTRATION_DELAY = 3f;

	private const float SCENE_LOAD_REGISTRATION_DELAY = 1f;

	private GameObject playerGO;

	private MonoBehaviour playerComp;

	private FieldInfo yawField;

	private FieldInfo velField;

	private FieldInfo groundedField;

	private readonly List<Checkpoint> checkpoints = new List<Checkpoint>();

	private bool hasLastState;

	private Checkpoint lastState;

	private int currentIndex = -1;

	private int teleportCount;

	private AudioClip successClip;

	private AudioClip failClip;

	private AudioSource audioSrc;

	private TextMeshProUGUI timerSource;

	private RectTransform menuPanel;

	private readonly TextMeshProUGUI[] menuItems = (TextMeshProUGUI[])(object)new TextMeshProUGUI[7];

	private bool uiInitialized;

	private Color menuFullColor;

	private Color menuDimColor;

	private bool practiceMode;

	private float currentTimeScale = 1f;

	private GameObject pauseMenuGO;

	private float lastPauseCheckTime;

	private const float PAUSE_CHECK_INTERVAL = 0.5f;

	private void Awake()
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Practice Mod v1.2.0 loaded.");
		audioSrc = ((Component)this).gameObject.AddComponent<AudioSource>();
		audioSrc.spatialBlend = 0f;
		audioSrc.volume = 0.7f;
		SceneManager.sceneLoaded += OnSceneLoaded;
		RegisterConsoleCommands();
		((MonoBehaviour)this).StartCoroutine(RegisterCommandsDelayed());
	}

	private void OnDestroy()
	{
		SceneManager.sceneLoaded -= OnSceneLoaded;
	}

	private void Update()
	{
		if (practiceMode && uiInitialized && !((Object)(object)timerSource == (Object)null) && !((Object)(object)menuPanel == (Object)null))
		{
			ProcessTimescaleInput();
			ProcessNoclipInput();
			if (Time.unscaledTime - lastPauseCheckTime > 0.5f)
			{
				UpdatePauseMenuState();
				lastPauseCheckTime = Time.unscaledTime;
			}
			ProcessCheckpointInputs();
			UpdateMenuUI();
		}
	}

	private void ProcessTimescaleInput()
	{
		if (Input.GetKeyDown((KeyCode)61) || Input.GetKeyDown((KeyCode)270))
		{
			SetTimescale(currentTimeScale + 0.1f);
		}
		else if (Input.GetKeyDown((KeyCode)45) || Input.GetKeyDown((KeyCode)269))
		{
			SetTimescale(currentTimeScale - 0.1f);
		}
		else if (Input.GetKeyDown((KeyCode)48) || Input.GetKeyDown((KeyCode)256))
		{
			SetTimescale(1f);
		}
	}

	private void ProcessNoclipInput()
	{
		if (Input.GetKeyDown((KeyCode)118))
		{
			ToggleNoclip();
		}
	}

	private void ToggleNoclip()
	{
		try
		{
			CommandConsole.instance.ExecuteCommand("noclip");
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Error toggling noclip: " + ex.Message));
			try
			{
				object commandConsoleInstance = GetCommandConsoleInstance();
				if (commandConsoleInstance != null)
				{
					MethodInfo method = typeof(CommandConsole).GetMethod("ExecuteCommand", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (!(method == null))
					{
						method.Invoke(commandConsoleInstance, new object[1] { "noclip" });
					}
				}
			}
			catch (Exception ex2)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Failed to toggle noclip: " + ex2.Message));
			}
		}
	}

	private void SetTimescale(float value)
	{
		float num = currentTimeScale;
		currentTimeScale = Mathf.Clamp(value, 0.1f, 10f);
		if (!Mathf.Approximately(num, currentTimeScale))
		{
			Time.timeScale = currentTimeScale;
		}
	}

	private void ProcessCheckpointInputs()
	{
		if (Input.GetKeyDown((KeyCode)49))
		{
			CreateCheckpoint();
		}
		if (Input.GetKeyDown((KeyCode)50))
		{
			TeleportToCurrentCheckpoint();
		}
		if (Input.GetKeyDown((KeyCode)51))
		{
			CycleToPreviousCheckpoint();
		}
		if (Input.GetKeyDown((KeyCode)52))
		{
			CycleToNextCheckpoint();
		}
		if (Input.GetKeyDown((KeyCode)53))
		{
			UndoTeleport();
		}
	}

	private void CreateCheckpoint()
	{
		if (!IsGrounded())
		{
			PlayFailBeep();
			return;
		}
		SaveLastState();
		Checkpoint checkpoint = Checkpoint.FromCurrentState(playerGO, playerComp, yawField);
		checkpoints.Add(checkpoint);
		currentIndex = checkpoints.Count - 1;
		RestoreState(checkpoint);
		PlaySuccessBeep();
	}

	private void TeleportToCurrentCheckpoint()
	{
		if (currentIndex < 0)
		{
			PlayFailBeep();
			return;
		}
		SaveLastState();
		RestoreState(checkpoints[currentIndex]);
		teleportCount++;
		PlaySuccessBeep();
	}

	private void CycleToPreviousCheckpoint()
	{
		if (checkpoints.Count < 2)
		{
			PlayFailBeep();
			return;
		}
		SaveLastState();
		currentIndex = (currentIndex - 1 + checkpoints.Count) % checkpoints.Count;
		RestoreState(checkpoints[currentIndex]);
		teleportCount++;
		PlaySuccessBeep();
	}

	private void CycleToNextCheckpoint()
	{
		if (checkpoints.Count < 1)
		{
			PlayFailBeep();
			return;
		}
		SaveLastState();
		currentIndex = (currentIndex + 1) % checkpoints.Count;
		RestoreState(checkpoints[currentIndex]);
		teleportCount++;
		PlaySuccessBeep();
	}

	private void UndoTeleport()
	{
		if (!hasLastState)
		{
			PlayFailBeep();
			return;
		}
		RestoreState(lastState);
		hasLastState = false;
		PlaySuccessBeep();
	}

	private void SaveLastState()
	{
		hasLastState = true;
		lastState = Checkpoint.FromCurrentState(playerGO, playerComp, yawField);
	}

	private void InitPracticeUI()
	{
		//IL_00af: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)menuPanel != (Object)null)
		{
			Object.Destroy((Object)(object)((Component)menuPanel).gameObject);
			menuPanel = null;
		}
		uiInitialized = false;
		GameObject val = GameObject.Find("GameManager/Canvas/Game UI/GameStateTrackers/Timer");
		if ((Object)(object)val == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"Timer not found!");
			return;
		}
		timerSource = val.GetComponent<TextMeshProUGUI>();
		if ((Object)(object)timerSource == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"Timer missing TMP!");
			return;
		}
		currentTimeScale = Time.timeScale;
		Transform transform = ((Component)val.GetComponentInParent<Canvas>()).transform;
		Canvas componentInParent = val.GetComponentInParent<Canvas>();
		CreateMenuPanel(transform, componentInParent);
		CreateMenuItems();
		menuFullColor = ((Graphic)timerSource).color;
		menuDimColor = new Color(menuFullColor.r, menuFullColor.g, menuFullColor.b, menuFullColor.a * 0.5f);
		UpdateMenuUI();
		uiInitialized = true;
	}

	private void CreateMenuPanel(Transform canvasTransform, Canvas timerCanvas)
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Expected O, but got Unknown
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("PracticeMenuPanel", new Type[1] { typeof(RectTransform) });
		val.transform.SetParent(canvasTransform, false);
		Canvas obj = val.AddComponent<Canvas>();
		obj.overrideSorting = timerCanvas.overrideSorting;
		obj.sortingOrder = timerCanvas.sortingOrder;
		obj.sortingLayerID = timerCanvas.sortingLayerID;
		obj.sortingLayerName = timerCanvas.sortingLayerName;
		val.AddComponent<CanvasRenderer>();
		menuPanel = val.GetComponent<RectTransform>();
		menuPanel.anchorMin = new Vector2(0f, 0.5f);
		menuPanel.anchorMax = new Vector2(0f, 0.5f);
		menuPanel.pivot = new Vector2(0f, 0.5f);
		menuPanel.anchoredPosition = new Vector2(25f, 0f);
	}

	private void CreateMenuItems()
	{
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0120: Unknown result type (might be due to invalid IL or missing references)
		for (int i = 0; i < menuItems.Length; i++)
		{
			GameObject val = new GameObject($"MenuItem{i + 1}", new Type[2]
			{
				typeof(RectTransform),
				typeof(TextMeshProUGUI)
			});
			val.transform.SetParent((Transform)(object)menuPanel, false);
			RectTransform component = val.GetComponent<RectTransform>();
			component.anchorMin = new Vector2(0f, 1f);
			component.anchorMax = new Vector2(0f, 1f);
			component.pivot = new Vector2(0f, 1f);
			component.anchoredPosition = new Vector2(0f, (float)(-i) * 23f);
			TextMeshProUGUI component2 = val.GetComponent<TextMeshProUGUI>();
			((TMP_Text)component2).font = ((TMP_Text)timerSource).font;
			((TMP_Text)component2).fontSize = 18f;
			((TMP_Text)component2).enableAutoSizing = false;
			((TMP_Text)component2).fontSizeMin = 18f;
			((TMP_Text)component2).fontSizeMax = 18f;
			((Graphic)component2).color = ((Graphic)timerSource).color;
			((TMP_Text)component2).alignment = (TextAlignmentOptions)513;
			((TMP_Text)component2).enableWordWrapping = ((TMP_Text)timerSource).enableWordWrapping;
			((TMP_Text)component2).margin = ((TMP_Text)timerSource).margin;
			((TMP_Text)component2).richText = ((TMP_Text)timerSource).richText;
			menuItems[i] = component2;
		}
		((TMP_Text)menuItems[1]).text = "";
		((TMP_Text)menuItems[4]).text = "3. Prev CP";
		((TMP_Text)menuItems[5]).text = "4. Next CP";
		((TMP_Text)menuItems[6]).text = "5. Undo TP";
	}

	private void UpdateMenuUI()
	{
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00af: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0103: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
		((TMP_Text)menuItems[0]).text = $"Timescale {currentTimeScale:F1}";
		((TMP_Text)menuItems[2]).text = $"1. Checkpoint #{((currentIndex >= 0) ? (currentIndex + 1) : 0)}";
		((TMP_Text)menuItems[3]).text = $"2. Teleport #{teleportCount}";
		((Graphic)menuItems[3]).color = ((currentIndex < 0) ? menuDimColor : menuFullColor);
		((Graphic)menuItems[4]).color = ((checkpoints.Count < 2) ? menuDimColor : menuFullColor);
		((Graphic)menuItems[5]).color = ((checkpoints.Count < 1) ? menuDimColor : menuFullColor);
		((Graphic)menuItems[6]).color = (hasLastState ? menuFullColor : menuDimColor);
	}

	private void UpdatePauseMenuState()
	{
		if ((Object)(object)pauseMenuGO == (Object)null)
		{
			pauseMenuGO = GameObject.Find("GameManager/Canvas/Pause/Pause Menu");
		}
		bool flag = (Object)(object)pauseMenuGO != (Object)null && pauseMenuGO.activeSelf;
		if ((Object)(object)menuPanel != (Object)null && ((Component)menuPanel).gameObject.activeSelf != !flag)
		{
			((Component)menuPanel).gameObject.SetActive(!flag);
		}
	}

	private void TogglePracticeMode()
	{
		practiceMode = !practiceMode;
		if (practiceMode)
		{
			EnablePracticeMode();
		}
		else
		{
			DisablePracticeMode();
		}
	}

	private void EnablePracticeMode()
	{
		try
		{
			CommandConsole.hasCheated = true;
			if ((Object)(object)CL_GameManager.gamemode != (Object)null)
			{
				CL_GameManager.gamemode.allowAchievements = false;
				CL_GameManager.gamemode.allowCheatedScores = false;
			}
			else
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"CL_GameManager.gamemode is null");
			}
			ExecuteDeathgooCommands();
			PlaySuccessBeep();
			CachePlayerAndFields();
			InitPracticeUI();
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Error enabling practice mode: " + ex.Message));
			((BaseUnityPlugin)this).Logger.LogError((object)("Stack trace: " + ex.StackTrace));
		}
	}

	private void DisablePracticeMode()
	{
		try
		{
			PlaySuccessBeep();
			if ((Object)(object)menuPanel != (Object)null)
			{
				((Component)menuPanel).gameObject.SetActive(false);
			}
			pauseMenuGO = null;
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Error disabling practice mode: " + ex.Message));
			((BaseUnityPlugin)this).Logger.LogError((object)("Stack trace: " + ex.StackTrace));
		}
	}

	private void OnSceneLoaded(Scene s, LoadSceneMode m)
	{
		practiceMode = false;
		checkpoints.Clear();
		currentIndex = -1;
		hasLastState = false;
		teleportCount = 0;
		uiInitialized = false;
		timerSource = null;
		menuPanel = null;
		pauseMenuGO = null;
		Time.timeScale = 1f;
		currentTimeScale = 1f;
		((MonoBehaviour)this).StartCoroutine(RegisterCommandsAfterDelay(1f));
	}

	[IteratorStateMachine(typeof(<RegisterCommandsDelayed>d__58))]
	private IEnumerator RegisterCommandsDelayed()
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <RegisterCommandsDelayed>d__58(0)
		{
			<>4__this = this
		};
	}

	[IteratorStateMachine(typeof(<RegisterCommandsAfterDelay>d__59))]
	private IEnumerator RegisterCommandsAfterDelay(float delay)
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <RegisterCommandsAfterDelay>d__59(0)
		{
			<>4__this = this,
			delay = delay
		};
	}

	private void RegisterConsoleCommands()
	{
		try
		{
			if (CommandExists("practice"))
			{
				return;
			}
			CommandConsole.AddCommand("practice", (Action<string[]>)delegate(string[] args)
			{
				if (CommandConsole.IsConsoleVisible() || args.Length != 0)
				{
					TogglePracticeMode();
				}
			}, true);
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Error registering console command: " + ex.Message));
		}
	}

	private bool CommandExists(string commandName)
	{
		try
		{
			object commandConsoleInstance = GetCommandConsoleInstance();
			if (commandConsoleInstance == null)
			{
				return false;
			}
			FieldInfo field = typeof(CommandConsole).GetField("commands", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field == null)
			{
				return false;
			}
			if (!(field.GetValue(commandConsoleInstance) is IDictionary dictionary))
			{
				return false;
			}
			return dictionary.Contains(commandName);
		}
		catch
		{
			return false;
		}
	}

	private object GetCommandConsoleInstance()
	{
		return typeof(CommandConsole).GetField("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(null);
	}

	private void ExecuteDeathgooCommands()
	{
		try
		{
			CommandConsole.instance.ExecuteCommand("deathgoo-stop");
			CommandConsole.instance.ExecuteCommand("deathgoo-height -999");
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("Direct command execution failed: " + ex.Message));
			try
			{
				object commandConsoleInstance = GetCommandConsoleInstance();
				if (commandConsoleInstance != null)
				{
					MethodInfo method = typeof(CommandConsole).GetMethod("ExecuteCommand", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (!(method == null))
					{
						method.Invoke(commandConsoleInstance, new object[1] { "deathgoo-stop" });
						method.Invoke(commandConsoleInstance, new object[1] { "deathgoo-height -999" });
					}
				}
			}
			catch (Exception ex2)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Failed to execute safety commands: " + ex2.Message));
			}
		}
	}

	private void CachePlayerAndFields()
	{
		playerGO = GameObject.Find("CL_Player");
		if ((Object)(object)playerGO == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"CL_Player not found!");
			return;
		}
		MonoBehaviour[] components = playerGO.GetComponents<MonoBehaviour>();
		foreach (MonoBehaviour val in components)
		{
			Type type = ((object)val).GetType();
			FieldInfo field = type.GetField("camY", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null && field.FieldType == typeof(float))
			{
				playerComp = val;
				yawField = field;
				velField = type.GetField("vel", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				groundedField = type.GetField("isGrounded", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				break;
			}
		}
		if (!((Object)(object)successClip == (Object)null) && !((Object)(object)failClip == (Object)null))
		{
			return;
		}
		AudioClip[] array = Resources.FindObjectsOfTypeAll<AudioClip>();
		foreach (AudioClip val2 in array)
		{
			if (((Object)val2).name == "beep2")
			{
				successClip = val2;
			}
			else if (((Object)val2).name == "computer_beep2")
			{
				failClip = val2;
			}
			if ((Object)(object)successClip != (Object)null && (Object)(object)failClip != (Object)null)
			{
				break;
			}
		}
	}

	private bool IsGrounded()
	{
		if (groundedField == null || (Object)(object)playerComp == (Object)null)
		{
			return false;
		}
		return (bool)groundedField.GetValue(playerComp);
	}

	private void RestoreState(Checkpoint cp)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)playerGO == (Object)null))
		{
			playerGO.transform.position = cp.pos;
			playerGO.transform.localRotation = Quaternion.Euler(0f, cp.pitch, 0f);
			if (yawField != null && (Object)(object)playerComp != (Object)null)
			{
				yawField.SetValue(playerComp, cp.yaw);
			}
			ClearInertia();
			ResetGripStrength();
		}
	}

	private void ResetGripStrength()
	{
		ENT_Player component = playerGO.GetComponent<ENT_Player>();
		if (!((Object)(object)component == (Object)null))
		{
			Hand[] hands = component.hands;
			foreach (Hand obj in hands)
			{
				float currentGripStrengthTimer = component.GetCurrentGripStrengthTimer();
				obj.gripStrength = currentGripStrengthTimer;
			}
		}
	}

	private void ClearInertia()
	{
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//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_0083: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)playerGO == (Object)null))
		{
			Rigidbody component = playerGO.GetComponent<Rigidbody>();
			if ((Object)(object)component != (Object)null)
			{
				component.velocity = Vector3.zero;
				component.angularVelocity = Vector3.zero;
			}
			CharacterController component2 = playerGO.GetComponent<CharacterController>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.Move(Vector3.zero);
			}
			if (velField != null && (Object)(object)playerComp != (Object)null)
			{
				velField.SetValue(playerComp, Vector3.zero);
			}
		}
	}

	private void PlaySuccessBeep()
	{
		if (practiceMode && !((Object)(object)successClip == (Object)null) && !((Object)(object)audioSrc == (Object)null))
		{
			audioSrc.PlayOneShot(successClip);
		}
	}

	private void PlayFailBeep()
	{
		if (practiceMode && !((Object)(object)failClip == (Object)null) && !((Object)(object)audioSrc == (Object)null))
		{
			audioSrc.PlayOneShot(failClip);
		}
	}
}