Decompiled source of FreecamMod v1.1.0

GBFreeCam.dll

Decompiled 5 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using GBFreeCam;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using MelonLoader;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.Rendering.Universal;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(FreeCamMod), "FreecamMod", "1.1.0", "Mel", "Detachable free camera for Gang Beasts. Multiplayer-safe.")]
[assembly: MelonGame("Boneloaf", "Gang Beasts")]
[assembly: AssemblyCompany("FreecamMod")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0")]
[assembly: AssemblyProduct("FreecamMod")]
[assembly: AssemblyTitle("FreecamMod")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.0.0")]
[module: UnverifiableCode]
namespace GBFreeCam;

public class FreeCamMod : MelonMod
{
	private const float BaseSpeed = 12f;

	private const float FastMultiplier = 5f;

	private const float SlowMultiplier = 0.2f;

	private const float LookSensitivity = 0.15f;

	private const float ZoomSpeed = 60f;

	private const float MinFov = 10f;

	private const float MaxFov = 170f;

	private const float MinPitch = -89f;

	private const float MaxPitch = 89f;

	private const float SlowMotionScale = 0.25f;

	private const int MaxErrors = 8;

	private const float MultiplayerPollInterval = 1f;

	private const float SceneSettleDelay = 0.35f;

	private static readonly string[] HudSkipKeywords = new string[28]
	{
		"lobby", "party", "invite", "friend", "network", "netcode", "session", "host", "menu", "pause",
		"settings", "option", "loading", "credit", "popup", "tooltip", "tutorial", "keyboard", "controller", "error",
		"disconnect", "kick", "chat", "steam", "overlay", "notify", "notification", "cursor"
	};

	private static readonly string[] PlayerIdMarkers = new string[3] { "PlayerID:", "Player ID:", "PlayerId:" };

	private bool active;

	private bool selfDisabled;

	private int errorCount;

	private GameObject camObject;

	private Camera freeCam;

	private readonly List<Camera> suppressedCams = new List<Camera>();

	private float yaw;

	private float pitch;

	private bool frozen;

	private bool slowMotion;

	private bool timeOverridden;

	private float savedTimeScale = 1f;

	private bool hudHidden;

	private readonly List<Canvas> hiddenCanvases = new List<Canvas>();

	private readonly List<bool> hiddenCanvasPrevState = new List<bool>();

	private bool inMultiplayer;

	private bool multiplayerKnown;

	private bool warnedTimeInMultiplayer;

	private bool warnedHudSkip;

	private float multiplayerPollTimer;

	private float sceneSettleTimer;

	private bool cursorWasLocked;

	public override void OnInitializeMelon()
	{
		MelonLogger.Msg("[FreecamMod] loaded. F1 freecam | F2 gameplay HUD | F3 freeze | F4 slow-mo | F5 ortho | R reset view");
	}

	public override void OnUpdate()
	{
		if (selfDisabled)
		{
			return;
		}
		try
		{
			OnUpdateSafe();
		}
		catch (Exception ex)
		{
			HandleFailure("OnUpdate", ex);
		}
	}

	private void OnUpdateSafe()
	{
		Keyboard current = Keyboard.current;
		if (current == null)
		{
			return;
		}
		if (sceneSettleTimer > 0f)
		{
			sceneSettleTimer -= Time.unscaledDeltaTime;
		}
		multiplayerPollTimer -= Time.unscaledDeltaTime;
		if (multiplayerPollTimer <= 0f)
		{
			multiplayerPollTimer = 1f;
			RefreshMultiplayerState();
		}
		if (((ButtonControl)current.f1Key).wasPressedThisFrame)
		{
			ToggleFreeCam();
		}
		if (((ButtonControl)current.f2Key).wasPressedThisFrame)
		{
			ToggleHud();
		}
		if (((ButtonControl)current.f3Key).wasPressedThisFrame)
		{
			ToggleFreeze();
		}
		if (((ButtonControl)current.f4Key).wasPressedThisFrame)
		{
			ToggleSlowMotion();
		}
		ApplyTimeOverride();
		if (active && !((Object)(object)freeCam == (Object)null))
		{
			MaintainCameraSuppression();
			if (((ButtonControl)current.f5Key).wasPressedThisFrame)
			{
				ToggleOrthographic();
			}
			if (((ButtonControl)current.rKey).wasPressedThisFrame)
			{
				ResetView();
			}
			UpdateMovement(current);
			UpdateLook();
			UpdateZoom(current);
		}
	}

	public override void OnSceneWasLoaded(int buildIndex, string sceneName)
	{
		if (selfDisabled)
		{
			return;
		}
		try
		{
			sceneSettleTimer = 0.35f;
			multiplayerPollTimer = 0f;
			multiplayerKnown = false;
			ReleaseTimeOverride();
			if (active)
			{
				RestoreSuppressedCameras();
				ClearDestroyedSuppressedCameras();
				if ((Object)(object)freeCam == (Object)null || (Object)(object)camObject == (Object)null)
				{
					MelonLogger.Warning("[FreecamMod] free camera lost on scene load, rebuilding.");
					active = false;
					ToggleFreeCam();
				}
				sceneSettleTimer = 0.35f;
			}
		}
		catch (Exception ex)
		{
			HandleFailure("OnSceneWasLoaded", ex);
		}
	}

	public override void OnApplicationQuit()
	{
		Shutdown();
	}

	private void HandleFailure(string where, Exception ex)
	{
		errorCount++;
		MelonLogger.Error($"[FreecamMod] {where} failed ({errorCount}/{8}): {ex.GetType().Name}: {ex.Message}");
		if (errorCount >= 8)
		{
			MelonLogger.Error("[FreecamMod] too many failures - disabling the mod and restoring the game to its original state.");
			Shutdown();
			selfDisabled = true;
		}
	}

	private void Shutdown()
	{
		try
		{
			ReleaseTimeOverride();
			RestoreHud();
			DisableCamera();
			RestoreCursor();
		}
		catch (Exception ex)
		{
			MelonLogger.Error("[FreecamMod] shutdown error: " + ex.Message);
		}
	}

	private void UpdateMovement(Keyboard kb)
	{
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: 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)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: 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_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: 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_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d0: 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)
		//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00db: 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_00f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0104: Unknown result type (might be due to invalid IL or missing references)
		float num = 12f;
		if (((ButtonControl)kb.leftShiftKey).isPressed)
		{
			num *= 5f;
		}
		if (((ButtonControl)kb.leftCtrlKey).isPressed)
		{
			num *= 0.2f;
		}
		Transform transform = ((Component)freeCam).transform;
		Vector3 val = Vector3.zero;
		if (((ButtonControl)kb.upArrowKey).isPressed)
		{
			val += transform.forward;
		}
		if (((ButtonControl)kb.downArrowKey).isPressed)
		{
			val -= transform.forward;
		}
		if (((ButtonControl)kb.rightArrowKey).isPressed)
		{
			val += transform.right;
		}
		if (((ButtonControl)kb.leftArrowKey).isPressed)
		{
			val -= transform.right;
		}
		if (((ButtonControl)kb.eKey).isPressed)
		{
			val += Vector3.up;
		}
		if (((ButtonControl)kb.qKey).isPressed)
		{
			val -= Vector3.up;
		}
		if (((Vector3)(ref val)).sqrMagnitude > 0f)
		{
			transform.position += ((Vector3)(ref val)).normalized * (num * Time.unscaledDeltaTime);
		}
	}

	private void UpdateLook()
	{
		//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_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		Mouse current = Mouse.current;
		if (current != null)
		{
			Vector2 val = ((InputControl<Vector2>)(object)((Pointer)current).delta).ReadValue();
			if (!(((Vector2)(ref val)).sqrMagnitude <= 0f))
			{
				yaw += val.x * 0.15f;
				pitch = Mathf.Clamp(pitch - val.y * 0.15f, -89f, 89f);
				((Component)freeCam).transform.rotation = Quaternion.Euler(pitch, yaw, 0f);
			}
		}
	}

	private void UpdateZoom(Keyboard kb)
	{
		float num = 0f;
		if (((ButtonControl)kb.equalsKey).isPressed || ((ButtonControl)kb.numpadPlusKey).isPressed)
		{
			num += 60f * Time.unscaledDeltaTime;
		}
		if (((ButtonControl)kb.minusKey).isPressed || ((ButtonControl)kb.numpadMinusKey).isPressed)
		{
			num -= 60f * Time.unscaledDeltaTime;
		}
		if (!Mathf.Approximately(num, 0f))
		{
			if (freeCam.orthographic)
			{
				freeCam.orthographicSize = Mathf.Clamp(freeCam.orthographicSize - num, 0.1f, 100f);
			}
			else
			{
				freeCam.fieldOfView = Mathf.Clamp(freeCam.fieldOfView + num, 10f, 170f);
			}
		}
	}

	private void ToggleFreeCam()
	{
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Expected O, but got Unknown
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: 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_00da: Unknown result type (might be due to invalid IL or missing references)
		if (active)
		{
			DisableCamera();
			RestoreCursor();
			MelonLogger.Msg("[FreecamMod] free camera off.");
			return;
		}
		Camera val = SafeGetMainCamera();
		if ((Object)(object)val == (Object)null)
		{
			MelonLogger.Warning("[FreecamMod] no main camera yet - try again in a moment.");
			return;
		}
		camObject = new GameObject("FreecamMod_Camera");
		Object.DontDestroyOnLoad((Object)(object)camObject);
		freeCam = camObject.AddComponent<Camera>();
		freeCam.CopyFrom(val);
		UniversalAdditionalCameraData val2 = default(UniversalAdditionalCameraData);
		if (!camObject.TryGetComponent<UniversalAdditionalCameraData>(ref val2))
		{
			val2 = camObject.AddComponent<UniversalAdditionalCameraData>();
		}
		val2.renderPostProcessing = true;
		Transform transform = ((Component)val).transform;
		((Component)freeCam).transform.position = transform.position;
		((Component)freeCam).transform.rotation = transform.rotation;
		Vector3 eulerAngles = transform.eulerAngles;
		pitch = eulerAngles.x;
		yaw = eulerAngles.y;
		((Behaviour)freeCam).enabled = true;
		SuppressCamera(val);
		LockCursor();
		active = true;
		MelonLogger.Msg("[FreecamMod] free camera on.");
	}

	private void SuppressCamera(Camera cam)
	{
		if ((Object)(object)cam == (Object)null || (Object)(object)cam == (Object)(object)freeCam)
		{
			return;
		}
		for (int i = 0; i < suppressedCams.Count; i++)
		{
			if ((Object)(object)suppressedCams[i] == (Object)(object)cam)
			{
				return;
			}
		}
		if (((Behaviour)cam).enabled)
		{
			((Behaviour)cam).enabled = false;
			suppressedCams.Add(cam);
		}
	}

	private void RestoreSuppressedCameras()
	{
		for (int i = 0; i < suppressedCams.Count; i++)
		{
			Camera val = suppressedCams[i];
			if (!((Object)(object)val == (Object)null))
			{
				try
				{
					((Behaviour)val).enabled = true;
				}
				catch (Exception ex)
				{
					MelonLogger.Error("[FreecamMod] could not re-enable camera: " + ex.Message);
				}
			}
		}
		suppressedCams.Clear();
	}

	private void ClearDestroyedSuppressedCameras()
	{
		for (int num = suppressedCams.Count - 1; num >= 0; num--)
		{
			if ((Object)(object)suppressedCams[num] == (Object)null)
			{
				suppressedCams.RemoveAt(num);
			}
		}
	}

	private void DisableCamera()
	{
		RestoreSuppressedCameras();
		if ((Object)(object)camObject != (Object)null)
		{
			Object.Destroy((Object)(object)camObject);
		}
		camObject = null;
		freeCam = null;
		active = false;
	}

	private static Camera SafeGetMainCamera()
	{
		try
		{
			return Camera.main;
		}
		catch (Exception)
		{
			return null;
		}
	}

	private void MaintainCameraSuppression()
	{
		if (!active || sceneSettleTimer > 0f)
		{
			return;
		}
		ClearDestroyedSuppressedCameras();
		if (suppressedCams.Count <= 0)
		{
			Camera val = SafeGetMainCamera();
			if ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)freeCam)
			{
				SuppressCamera(val);
			}
		}
	}

	private void ResetView()
	{
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: Unknown result type (might be due to invalid IL or missing references)
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)freeCam == (Object)null)
		{
			return;
		}
		Camera val = null;
		for (int i = 0; i < suppressedCams.Count; i++)
		{
			if ((Object)(object)suppressedCams[i] != (Object)null)
			{
				val = suppressedCams[i];
				break;
			}
		}
		val = (((Object)(object)val != (Object)null) ? val : SafeGetMainCamera());
		if ((Object)(object)val != (Object)null)
		{
			Transform transform = ((Component)val).transform;
			((Component)freeCam).transform.position = transform.position;
			((Component)freeCam).transform.rotation = transform.rotation;
			Vector3 eulerAngles = transform.eulerAngles;
			pitch = eulerAngles.x;
			yaw = eulerAngles.y;
		}
		if (!freeCam.orthographic)
		{
			freeCam.fieldOfView = 60f;
		}
	}

	private void ToggleOrthographic()
	{
		if (!((Object)(object)freeCam == (Object)null))
		{
			freeCam.orthographic = !freeCam.orthographic;
			if (freeCam.orthographic)
			{
				freeCam.orthographicSize = 5f;
			}
			else
			{
				freeCam.fieldOfView = 60f;
			}
		}
	}

	private void LockCursor()
	{
		Cursor.lockState = (CursorLockMode)1;
		Cursor.visible = false;
		cursorWasLocked = true;
	}

	private void RestoreCursor()
	{
		if (cursorWasLocked)
		{
			cursorWasLocked = false;
			Cursor.lockState = (CursorLockMode)0;
			Cursor.visible = true;
		}
	}

	private void ToggleHud()
	{
		if (hudHidden)
		{
			RestoreHud();
			MelonLogger.Msg("[FreecamMod] gameplay HUD shown.");
			return;
		}
		Il2CppArrayBase<Canvas> val = Object.FindObjectsOfType<Canvas>(true);
		if (val == null)
		{
			MelonLogger.Warning("[FreecamMod] no HUD found to hide.");
			return;
		}
		StringBuilder stringBuilder = new StringBuilder();
		int num = 0;
		for (int i = 0; i < val.Length; i++)
		{
			Canvas val2 = val[i];
			if ((Object)(object)val2 == (Object)null)
			{
				continue;
			}
			GameObject gameObject = ((Component)val2).gameObject;
			if ((Object)(object)gameObject == (Object)null || !gameObject.activeSelf)
			{
				continue;
			}
			if (IsProtectedHud(((Object)gameObject).name))
			{
				if (stringBuilder.Length < 400)
				{
					stringBuilder.Append(((Object)gameObject).name).Append(", ");
				}
				continue;
			}
			try
			{
				hiddenCanvases.Add(val2);
				hiddenCanvasPrevState.Add(item: true);
				gameObject.SetActive(false);
				num++;
			}
			catch (Exception ex)
			{
				MelonLogger.Error("[FreecamMod] could not hide canvas '" + ((Object)gameObject).name + "': " + ex.Message);
			}
		}
		hudHidden = true;
		MelonLogger.Msg($"[FreecamMod] gameplay HUD hidden ({num} canvas(es)).");
		if (stringBuilder.Length > 0 && !warnedHudSkip)
		{
			warnedHudSkip = true;
			MelonLogger.Msg("[FreecamMod] left lobby/menu UI alone: " + stringBuilder.ToString().TrimEnd(',', ' '));
		}
	}

	private void RestoreHud()
	{
		for (int i = 0; i < hiddenCanvases.Count; i++)
		{
			Canvas val = hiddenCanvases[i];
			if (!((Object)(object)val == (Object)null))
			{
				try
				{
					((Component)val).gameObject.SetActive(hiddenCanvasPrevState[i]);
				}
				catch (Exception ex)
				{
					MelonLogger.Error("[FreecamMod] could not restore canvas: " + ex.Message);
				}
			}
		}
		hiddenCanvases.Clear();
		hiddenCanvasPrevState.Clear();
		hudHidden = false;
	}

	private static bool IsProtectedHud(string name)
	{
		if (string.IsNullOrEmpty(name))
		{
			return true;
		}
		for (int i = 0; i < HudSkipKeywords.Length; i++)
		{
			if (name.IndexOf(HudSkipKeywords[i], StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
		}
		return false;
	}

	private void ToggleFreeze()
	{
		if (CanUseTimeControls())
		{
			frozen = !frozen;
			if (!frozen)
			{
				slowMotion = false;
			}
			ApplyTimeOverride();
			MelonLogger.Msg(frozen ? "[FreecamMod] time frozen." : "[FreecamMod] time resumed.");
		}
	}

	private void ToggleSlowMotion()
	{
		if (CanUseTimeControls())
		{
			if (frozen)
			{
				MelonLogger.Warning("[FreecamMod] resume time (F3) before using slow motion.");
				return;
			}
			slowMotion = !slowMotion;
			ApplyTimeOverride();
			MelonLogger.Msg(slowMotion ? "[FreecamMod] slow motion on." : "[FreecamMod] slow motion off.");
		}
	}

	private bool CanUseTimeControls()
	{
		if (inMultiplayer)
		{
			if (!warnedTimeInMultiplayer)
			{
				warnedTimeInMultiplayer = true;
				MelonLogger.Warning("[FreecamMod] freeze/slow-mo are disabled while in a multiplayer session (they change the global time scale).");
			}
			return false;
		}
		return true;
	}

	private void ApplyTimeOverride()
	{
		if (!frozen && !slowMotion)
		{
			ReleaseTimeOverride();
			return;
		}
		float timeScale = (frozen ? 0f : 0.25f);
		if (!timeOverridden)
		{
			if (Time.timeScale > 0f)
			{
				savedTimeScale = Time.timeScale;
			}
			timeOverridden = true;
		}
		Time.timeScale = timeScale;
	}

	private void ReleaseTimeOverride()
	{
		if (timeOverridden)
		{
			timeOverridden = false;
			frozen = false;
			slowMotion = false;
			if (Time.timeScale <= 0.251f)
			{
				Time.timeScale = ((savedTimeScale > 0f) ? savedTimeScale : 1f);
			}
		}
	}

	private void RefreshMultiplayerState()
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		bool flag = false;
		try
		{
			Scene activeScene = SceneManager.GetActiveScene();
			if (!((Scene)(ref activeScene)).IsValid() || !((Scene)(ref activeScene)).isLoaded)
			{
				return;
			}
			Il2CppArrayBase<GameObject> rootGameObjects = (Il2CppArrayBase<GameObject>)(object)((Scene)(ref activeScene)).GetRootGameObjects();
			if (rootGameObjects == null)
			{
				return;
			}
			HashSet<int> hashSet = new HashSet<int>();
			for (int i = 0; i < rootGameObjects.Length; i++)
			{
				GameObject val = rootGameObjects[i];
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				int num = ParsePlayerId(((Object)val).name);
				if (num >= 0)
				{
					hashSet.Add(num);
					if (num > 0)
					{
						flag = true;
					}
				}
			}
			if (hashSet.Count > 1)
			{
				flag = true;
			}
		}
		catch (Exception ex)
		{
			if (!multiplayerKnown)
			{
				MelonLogger.Error("[FreecamMod] multiplayer detection failed: " + ex.Message);
			}
			return;
		}
		if (multiplayerKnown && flag != inMultiplayer)
		{
			MelonLogger.Msg(flag ? "[FreecamMod] multiplayer session detected - time controls disabled." : "[FreecamMod] left multiplayer session - time controls available again.");
			if (flag)
			{
				ReleaseTimeOverride();
			}
		}
		inMultiplayer = flag;
		multiplayerKnown = true;
	}

	private static int ParsePlayerId(string name)
	{
		if (string.IsNullOrEmpty(name))
		{
			return -1;
		}
		for (int i = 0; i < PlayerIdMarkers.Length; i++)
		{
			int num = name.IndexOf(PlayerIdMarkers[i], StringComparison.OrdinalIgnoreCase);
			if (num >= 0)
			{
				int j;
				for (j = num + PlayerIdMarkers[i].Length; j < name.Length && name[j] == ' '; j++)
				{
				}
				int k;
				for (k = j; k < name.Length && char.IsDigit(name[k]); k++)
				{
				}
				if (k > j && int.TryParse(name.Substring(j, k - j), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result))
				{
					return result;
				}
			}
		}
		return -1;
	}
}