Decompiled source of spawn viewer v2.1.0

SpawnViewer.dll

Decompiled 2 months ago
using System;
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 ComputerysModdingUtilities;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: StraftatMod(true)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("SpawnViewer")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("suvilba.straftat.spawnviewer")]
[assembly: AssemblyFileVersion("2.1.0.0")]
[assembly: AssemblyInformationalVersion("2.1.0+efc8b8e4df3f52e0040d34943932a5c82cd2ea6c")]
[assembly: AssemblyProduct("SpawnViewer")]
[assembly: AssemblyTitle("SpawnViewer")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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 StraftatSpawnViewer
{
	public enum GameMode
	{
		_2v2,
		_1v1
	}
	public static class Configs
	{
		private const float BeamLengthMin = 1f;

		private const float BeamLengthMax = 400f;

		public static ConfigEntry<bool> Enabled { get; private set; }

		public static ConfigEntry<KeyboardShortcut> ToggleKey { get; private set; }

		public static ConfigEntry<KeyboardShortcut> RefreshKey { get; private set; }

		public static ConfigEntry<GameMode> Mode { get; private set; }

		public static ConfigEntry<float> BeamLength { get; private set; }

		public static ConfigEntry<Color> TeamAColor { get; private set; }

		public static ConfigEntry<Color> TeamBColor { get; private set; }

		public static event Action EnabledChanged;

		public static event Action ModeChanged;

		public static event Action BeamLengthChanged;

		public static event Action ColorsChanged;

		internal static void Init(ConfigFile config)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Expected O, but got Unknown
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			Enabled = config.Bind<bool>("General", "Show Spawns", false, "Toggle spawn point visibility.");
			ToggleKey = config.Bind<KeyboardShortcut>("General", "Toggle Key", new KeyboardShortcut((KeyCode)286, Array.Empty<KeyCode>()), "Keybind to toggle spawn point visibility.");
			RefreshKey = config.Bind<KeyboardShortcut>("General", "Refresh Key", new KeyboardShortcut((KeyCode)287, Array.Empty<KeyCode>()), "Keybind to refresh spawn points mid map.");
			Mode = config.Bind<GameMode>("General", "Game Mode", GameMode._2v2, "Which spawn set to display.");
			BeamLength = config.Bind<float>("Markers", "Beam Length", 5f, new ConfigDescription("Height of the spawn point beams.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 400f), Array.Empty<object>()));
			TeamAColor = config.Bind<Color>("Markers", "Team A Color", new Color(0.25f, 0.75f, 1f), "Color of Team A spawnpoints.");
			TeamBColor = config.Bind<Color>("Markers", "Team B Color", new Color(1f, 0.35f, 0.55f), "Color of Team B spawnpoints.");
			Enabled.SettingChanged += delegate
			{
				Configs.EnabledChanged?.Invoke();
			};
			Mode.SettingChanged += delegate
			{
				Configs.ModeChanged?.Invoke();
			};
			BeamLength.SettingChanged += delegate
			{
				Configs.BeamLengthChanged?.Invoke();
			};
			TeamAColor.SettingChanged += delegate
			{
				Configs.ColorsChanged?.Invoke();
			};
			TeamBColor.SettingChanged += delegate
			{
				Configs.ColorsChanged?.Invoke();
			};
		}
	}
	[BepInPlugin("suvilba.straftat.spawnviewer", "SpawnViewer", "2.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class SpawnViewer : BaseUnityPlugin
	{
		private const string RootName = "StraftatSpawnViewer_ROOT";

		internal static ManualLogSource Logger;

		private GameObject _root;

		private SpawnpointDisplay _display;

		private Harmony _harmony;

		private bool _spawnsLocked;

		private bool _rescan;

		private int SpawnCount => (Configs.Mode.Value == GameMode._1v1) ? 2 : 4;

		private void Awake()
		{
			Logger = ((BaseUnityPlugin)this).Logger;
			Configs.Init(((BaseUnityPlugin)this).Config);
			SubscribeToConfig();
			EnsureDisplay();
			SceneManager.sceneLoaded += OnSceneLoaded;
			_rescan = true;
			TryHarmonyPatch();
		}

		private void Update()
		{
			HandleInput();
			if (Configs.Enabled.Value && _rescan)
			{
				_rescan = false;
				RefreshSpawns();
			}
		}

		private void OnDestroy()
		{
			SceneManager.sceneLoaded -= OnSceneLoaded;
			try
			{
				Harmony harmony = _harmony;
				if (harmony != null)
				{
					harmony.UnpatchSelf();
				}
			}
			catch
			{
			}
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			_spawnsLocked = false;
			_rescan = true;
		}

		private void HandleInput()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			KeyboardShortcut value = Configs.ToggleKey.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				Configs.Enabled.Value = !Configs.Enabled.Value;
			}
			value = Configs.RefreshKey.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				_spawnsLocked = false;
				_rescan = true;
			}
		}

		private void SubscribeToConfig()
		{
			Configs.EnabledChanged += delegate
			{
				if (Configs.Enabled.Value)
				{
					_spawnsLocked = false;
					_rescan = true;
				}
				else
				{
					_display.Hide();
				}
			};
			Configs.ModeChanged += delegate
			{
				_spawnsLocked = false;
				_display.Hide();
				_rescan = true;
			};
			Configs.BeamLengthChanged += delegate
			{
				_display.SetBeamLength(Configs.BeamLength.Value);
			};
			Configs.ColorsChanged += delegate
			{
				//IL_000b: 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)
				_display.SetColors(Configs.TeamAColor.Value, Configs.TeamBColor.Value);
			};
		}

		private void RefreshSpawns()
		{
			EnsureDisplay();
			if (!_spawnsLocked)
			{
				List<Transform> list = SpawnFinder.Find(Configs.Mode.Value);
				int spawnCount = SpawnCount;
				if (list.Count < spawnCount)
				{
					string arg = ((Configs.Mode.Value == GameMode._1v1) ? "1v1" : "2v2");
					Logger.LogWarning((object)$"SpawnViewer: Found {list.Count}/{spawnCount} {arg} spawnpoints.");
					_display.Hide();
				}
				else
				{
					_display.Show(list, spawnCount);
					_spawnsLocked = true;
				}
			}
		}

		private void EnsureDisplay()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			if ((Object)(object)_root == (Object)null)
			{
				_root = GameObject.Find("StraftatSpawnViewer_ROOT");
				if ((Object)(object)_root == (Object)null)
				{
					_root = new GameObject("StraftatSpawnViewer_ROOT");
					Object.DontDestroyOnLoad((Object)(object)_root);
				}
			}
			if ((Object)(object)_display == (Object)null)
			{
				_display = _root.GetComponent<SpawnpointDisplay>() ?? _root.AddComponent<SpawnpointDisplay>();
			}
		}

		private void TryHarmonyPatch()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			try
			{
				_harmony = new Harmony("suvilba.straftat.spawnviewer");
				Type type = AccessTools.TypeByName("PlayerManager");
				if (!(type == null))
				{
					PatchPostfixIfExists(type, "PopulateSpawnPoints");
					PatchPostfixIfExists(type, "SetActiveSpawnPoints");
					PatchPostfixIfExists(type, "RoundSpawn");
					PatchPostfixIfExists(type, "NewSceneSpawn");
				}
			}
			catch (Exception arg)
			{
				Logger.LogWarning((object)$"SpawnViewer Harmony patching failed: {arg}");
			}
		}

		private void PatchPostfixIfExists(Type type, string methodName)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.Method(type, methodName, (Type[])null, (Type[])null);
			if (!(methodInfo == null))
			{
				_harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(SpawnViewer), "RefreshPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
		}

		public static void RefreshPostfix()
		{
			try
			{
				SpawnViewer[] array = Resources.FindObjectsOfTypeAll<SpawnViewer>();
				if (array != null && array.Length != 0)
				{
					array[0]._spawnsLocked = false;
					array[0]._rescan = true;
				}
			}
			catch (Exception arg)
			{
				Debug.LogWarning((object)$"SpawnViewer RefreshPostfix failed: {arg}");
			}
		}
	}
	internal static class PluginInfo
	{
		public const string PLUGIN_GUID = "suvilba.straftat.spawnviewer";

		public const string PLUGIN_NAME = "SpawnViewer";

		public const string PLUGIN_VERSION = "2.1.0";
	}
	internal static class SpawnFinder
	{
		private const string Tag1v1 = "Spawnpoints";

		private const string Tag2v2 = "Spawnpoints4Player";

		internal static List<Transform> Find(GameMode mode)
		{
			string tag = ((mode == GameMode._1v1) ? "Spawnpoints" : "Spawnpoints4Player");
			return (from s in (from s in Object.FindObjectsByType<SpawnPoint>((FindObjectsSortMode)0)
					where (Object)(object)((Component)s).transform.parent != (Object)null && ((Component)((Component)s).transform.parent).CompareTag(tag)
					select s).OrderBy<SpawnPoint, string>((SpawnPoint s) => ((Object)s).name, StringComparer.OrdinalIgnoreCase)
				select ((Component)s).transform).ToList();
		}
	}
	public sealed class SpawnpointDisplay : MonoBehaviour
	{
		private const float BallSize = 0.35f;

		private readonly GameObject[] _spheres = (GameObject[])(object)new GameObject[4];

		private readonly LineRenderer[] _beams = (LineRenderer[])(object)new LineRenderer[4];

		private Material _matA;

		private Material _matB;

		private void Awake()
		{
			BuildPool();
		}

		private void OnDestroy()
		{
			DestroyPool();
			if ((Object)(object)_matA != (Object)null)
			{
				Object.Destroy((Object)(object)_matA);
			}
			if ((Object)(object)_matB != (Object)null)
			{
				Object.Destroy((Object)(object)_matB);
			}
		}

		public void Show(IReadOnlyList<Transform> spawns, int count)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			EnsurePool();
			for (int i = 0; i < count && i < spawns.Count; i++)
			{
				PlaceSphere(i, spawns[i].position, spawns[i].eulerAngles.y);
			}
			for (int j = 0; j < 4; j++)
			{
				bool flag = j < count;
				if ((Object)(object)_spheres[j] != (Object)null)
				{
					_spheres[j].SetActive(flag);
				}
				if ((Object)(object)_beams[j] != (Object)null)
				{
					((Renderer)_beams[j]).enabled = flag;
				}
			}
		}

		public void Hide()
		{
			for (int i = 0; i < 4; i++)
			{
				if ((Object)(object)_spheres[i] != (Object)null)
				{
					_spheres[i].SetActive(false);
				}
				if ((Object)(object)_beams[i] != (Object)null)
				{
					((Renderer)_beams[i]).enabled = false;
				}
			}
		}

		public void SetBeamLength(float length)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < 4; i++)
			{
				if ((Object)(object)_beams[i] != (Object)null)
				{
					_beams[i].SetPosition(1, Vector3.up * length);
				}
			}
		}

		public void SetColors(Color teamA, Color teamB)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_matA != (Object)null)
			{
				Object.Destroy((Object)(object)_matA);
			}
			if ((Object)(object)_matB != (Object)null)
			{
				Object.Destroy((Object)(object)_matB);
			}
			_matA = MakeMaterial(teamA);
			_matB = MakeMaterial(teamB);
			for (int i = 0; i < 4; i++)
			{
				if (!((Object)(object)_spheres[i] == (Object)null))
				{
					Material val = ((i == 0 || i == 2) ? _matA : _matB);
					Renderer component = _spheres[i].GetComponent<Renderer>();
					if ((Object)(object)component != (Object)null)
					{
						component.sharedMaterial = val;
					}
					if ((Object)(object)_beams[i] != (Object)null)
					{
						((Renderer)_beams[i]).material = val;
					}
				}
			}
		}

		private void EnsurePool()
		{
			for (int i = 0; i < 4; i++)
			{
				if ((Object)(object)_spheres[i] == (Object)null || (Object)(object)_beams[i] == (Object)null)
				{
					BuildPool();
					break;
				}
			}
		}

		private void BuildPool()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			DestroyPool();
			if (_matA == null)
			{
				_matA = MakeMaterial(Configs.TeamAColor.Value);
			}
			if (_matB == null)
			{
				_matB = MakeMaterial(Configs.TeamBColor.Value);
			}
			CreateSphere(0, "Spawnpoint_A1", _matA);
			CreateSphere(1, "Spawnpoint_B1", _matB);
			CreateSphere(2, "Spawnpoint_A2", _matA);
			CreateSphere(3, "Spawnpoint_B2", _matB);
		}

		private void DestroyPool()
		{
			for (int i = 0; i < 4; i++)
			{
				if ((Object)(object)_spheres[i] != (Object)null)
				{
					Object.Destroy((Object)(object)_spheres[i]);
				}
				_spheres[i] = null;
				_beams[i] = null;
			}
		}

		private void CreateSphere(int slot, string objectName, Material mat)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Expected O, but got Unknown
			//IL_00ba: 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_00d6: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = GameObject.CreatePrimitive((PrimitiveType)0);
			((Object)val).name = objectName;
			((Object)val).hideFlags = (HideFlags)52;
			val.transform.SetParent(((Component)this).transform, true);
			val.transform.localScale = new Vector3(0.35f, 0.35f, 0.35f);
			Object.Destroy((Object)(object)val.GetComponent<Collider>());
			Renderer component = val.GetComponent<Renderer>();
			if ((Object)(object)component != (Object)null)
			{
				component.sharedMaterial = mat;
			}
			GameObject val2 = new GameObject(objectName + "_Beam")
			{
				hideFlags = (HideFlags)52
			};
			val2.transform.SetParent(val.transform, false);
			LineRenderer val3 = val2.AddComponent<LineRenderer>();
			val3.useWorldSpace = false;
			val3.positionCount = 2;
			val3.SetPosition(0, Vector3.zero);
			val3.SetPosition(1, Vector3.up * Configs.BeamLength.Value);
			val3.startWidth = 0.15f;
			val3.endWidth = 0.15f;
			((Renderer)val3).material = mat;
			val.SetActive(false);
			_spheres[slot] = val;
			_beams[slot] = val3;
		}

		private void PlaceSphere(int slot, Vector3 pos, float yaw)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = _spheres[slot];
			if (!((Object)(object)val == (Object)null))
			{
				val.transform.position = pos + new Vector3(0f, 0.225f, 0f);
				val.transform.rotation = Quaternion.Euler(0f, yaw, 0f);
			}
		}

		private static Material MakeMaterial(Color color)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			return new Material(Shader.Find("Unlit/Color"))
			{
				color = color
			};
		}
	}
}