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
};
}
}
}