using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("PlayersTab")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("PlayersTab")]
[assembly: AssemblyCopyright("Copyright © 2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("9d2255b4-a2c4-470c-9536-98e86eb6a7ae")]
[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")]
namespace AntsLab.PlayersTab;
[BepInPlugin("antslab.playerstab", "AntsLab PlayersTab", "1.0.0")]
public class PlayersTabPlugin : BaseUnityPlugin
{
private struct PlayerEntry
{
public string Name;
public int Team;
public GameObject GO;
}
public const string PluginGuid = "antslab.playerstab";
public const string PluginName = "AntsLab PlayersTab";
public const string PluginVersion = "1.0.0";
internal static PlayersTabPlugin Instance;
private Harmony _harmony;
internal static ConfigEntry<KeyCode> KeyBind;
private ConfigEntry<float> _anchorXPct;
private ConfigEntry<float> _anchorYPct;
private ConfigEntry<float> _panelWidth;
private ConfigEntry<int> _fontSize;
private ConfigEntry<float> _rowHeight;
private ConfigEntry<float> _refreshSec;
private ConfigEntry<bool> _useMenuFont;
private ConfigEntry<bool> _showNamelessPlayers;
private readonly List<PlayerEntry> _players = new List<PlayerEntry>();
private float _nextRefresh;
private GUIStyle _rowStyle;
private GUIStyle _hdrStyle;
private Font _menuFont;
private void Awake()
{
//IL_014b: Unknown result type (might be due to invalid IL or missing references)
//IL_0155: Expected O, but got Unknown
Instance = this;
KeyBind = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("UI", "KeyBind", (KeyCode)9, "Default Bind to hold and show the players (I recommend to set to the same bind you use to open the map).");
_anchorXPct = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "AnchorXPct", 0.255f, "X % of screen (0..1).");
_anchorYPct = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "AnchorYPct", 0.27f, "Y % of screen (0..1) (0=top;1=bottom).");
_panelWidth = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "PanelWidth", 360f, "Panel Width (is invisible) (in px).");
_fontSize = ((BaseUnityPlugin)this).Config.Bind<int>("UI", "FontSize", 26, "Text size (px).");
_rowHeight = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "RowHeight", 35f, "Height of each line (px).");
_refreshSec = ((BaseUnityPlugin)this).Config.Bind<float>("Scan", "RefreshSeconds", 2f, "List update interval in seconds (s).");
_useMenuFont = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "UseMenuFont", true, "If true attempts to use the same font as the one on game's Menu.");
_showNamelessPlayers = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "ShowNamelessPlayers", true, "If true players that fail to render the name will show as \"nameless\" meaning will show players as nameless during lobby. Otherwise, it will not even render the tab on lobby");
_harmony = new Harmony("antslab.playerstab");
((BaseUnityPlugin)this).Logger.LogInfo((object)"AntsLab PlayersTab 1.0.0 loaded.");
}
private void OnDestroy()
{
try
{
Harmony harmony = _harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
}
catch
{
}
Instance = null;
}
private void Update()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
if (Input.GetKey(KeyBind.Value) && Time.unscaledTime >= _nextRefresh)
{
_nextRefresh = Time.unscaledTime + Mathf.Max(0.1f, _refreshSec.Value);
RefreshPlayers();
}
}
private void OnGUI()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0202: Unknown result type (might be due to invalid IL or missing references)
//IL_0207: Unknown result type (might be due to invalid IL or missing references)
//IL_021d: Unknown result type (might be due to invalid IL or missing references)
//IL_0228: Unknown result type (might be due to invalid IL or missing references)
//IL_0235: Unknown result type (might be due to invalid IL or missing references)
//IL_0286: Unknown result type (might be due to invalid IL or missing references)
//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
//IL_0318: Unknown result type (might be due to invalid IL or missing references)
//IL_0336: Unknown result type (might be due to invalid IL or missing references)
//IL_03aa: Unknown result type (might be due to invalid IL or missing references)
//IL_03c8: Unknown result type (might be due to invalid IL or missing references)
//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
//IL_0357: Unknown result type (might be due to invalid IL or missing references)
//IL_03e9: Unknown result type (might be due to invalid IL or missing references)
if (!Input.GetKey(KeyBind.Value))
{
return;
}
BuildStylesIfNeeded();
List<PlayerEntry> list = (from p in _players
where p.Team == 0
orderby p.Name
select p).ToList();
List<PlayerEntry> list2 = (from p in _players
where p.Team == 2
orderby p.Name
select p).ToList();
List<PlayerEntry> list3 = (from p in _players
where p.Team != 0 && p.Team != 2
orderby p.Name
select p).ToList();
int num = ((list.Count > 0) ? 1 : 0) + ((list2.Count > 0) ? 1 : 0) + ((list3.Count > 0) ? 1 : 0);
int num2 = list.Count + list2.Count + list3.Count;
float num3 = Mathf.Clamp(_panelWidth.Value, 200f, 800f);
float num4 = Mathf.Clamp(_rowHeight.Value, 16f, 48f);
float num5 = num4 + 2f;
float num6 = (float)num * num5 + (float)num2 * num4 + 10f;
float num7 = Mathf.Round(Mathf.Clamp01(_anchorXPct.Value) * (float)Screen.width);
float num8 = Mathf.Round(Mathf.Clamp01(_anchorYPct.Value) * (float)Screen.height);
Rect val = default(Rect);
((Rect)(ref val))..ctor(num7, num8, num3, num6);
Color color = GUI.color;
GUI.color = new Color(0f, 0f, 0f, 0f);
GUI.Box(val, GUIContent.none);
GUI.color = color;
float num9 = ((Rect)(ref val)).y + 5f;
float num10 = ((Rect)(ref val)).x + 10f;
float num11 = ((Rect)(ref val)).width - 20f;
if (list.Count > 0)
{
DrawHeader(new Rect(num10, num9, num11, num5), "Sorcerers", new Color(0.3f, 0.6f, 1f, 1f));
num9 += num5;
for (int i = 0; i < list.Count; i++)
{
DrawRow(new Rect(num10, num9, num11, num4), list[i].Name);
num9 += num4;
}
}
if (list2.Count > 0)
{
DrawHeader(new Rect(num10, num9, num11, num5), "Warlocks", new Color(0.7f, 0.5f, 1f, 1f));
num9 += num5;
for (int j = 0; j < list2.Count; j++)
{
DrawRow(new Rect(num10, num9, num11, num4), list2[j].Name);
num9 += num4;
}
}
if (list3.Count > 0)
{
DrawHeader(new Rect(num10, num9, num11, num5), "Others", new Color(0.8f, 0.8f, 0.8f, 1f));
num9 += num5;
for (int k = 0; k < list3.Count; k++)
{
DrawRow(new Rect(num10, num9, num11, num4), list3[k].Name);
num9 += num4;
}
}
}
private void DrawHeader(Rect rectHeader, string text, Color color)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: 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)
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
Color color2 = GUI.color;
GUI.color = color;
GUI.Label(rectHeader, text, _hdrStyle);
GUI.color = color2;
}
private void DrawRow(Rect rectRow, string name)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
GUI.Label(rectRow, name, _rowStyle);
}
private void BuildStylesIfNeeded()
{
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Expected O, but got Unknown
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_0080: Expected O, but got Unknown
if (_rowStyle != null && _hdrStyle != null)
{
return;
}
_rowStyle = new GUIStyle(GUI.skin.label);
_rowStyle.alignment = (TextAnchor)3;
_rowStyle.fontSize = Mathf.Max(12, _fontSize.Value);
_rowStyle.wordWrap = false;
_hdrStyle = new GUIStyle(GUI.skin.label);
_hdrStyle.alignment = (TextAnchor)3;
_hdrStyle.fontStyle = (FontStyle)1;
_hdrStyle.fontSize = Mathf.Max(12, _fontSize.Value + 2);
_hdrStyle.wordWrap = false;
if (_useMenuFont.Value)
{
Font val = TryGetMenuFontFromTMP();
if ((Object)(object)val != (Object)null)
{
_rowStyle.font = val;
_hdrStyle.font = val;
}
}
}
private static Font TryGetMenuFontFromTMP()
{
try
{
ScriptableObject[] array = Resources.FindObjectsOfTypeAll<ScriptableObject>();
foreach (ScriptableObject val in array)
{
if ((Object)(object)val == (Object)null)
{
continue;
}
Type type = ((object)val).GetType();
if (type.FullName == "TMPro.TMP_FontAsset" && ((Object)val).name.IndexOf("KELMSCOT", StringComparison.OrdinalIgnoreCase) >= 0)
{
PropertyInfo property = type.GetProperty("sourceFontFile", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
Font val2 = (Font)((property != null) ? /*isinst with value type is only supported in some contexts*/: null);
if ((Object)(object)val2 != (Object)null)
{
return val2;
}
}
}
}
catch
{
}
return null;
}
private void RefreshPlayers()
{
_players.Clear();
int num = 1;
Component[] array = FindAllComponentsSafe();
foreach (Component val in array)
{
if ((Object)(object)val == (Object)null)
{
continue;
}
Type type = ((object)val).GetType();
if (type == null || type.Name != "PlayerMovement")
{
continue;
}
GameObject gameObject = val.gameObject;
if (!((Object)(object)gameObject == (Object)null) && gameObject.activeInHierarchy)
{
int intField = GetIntField(val, "playerTeam", -1);
string text = GetStringField(val, "playername", null);
if (string.IsNullOrEmpty(text) && _showNamelessPlayers.Value)
{
text = "nameless " + num;
num++;
}
if (!string.IsNullOrEmpty(text) || _showNamelessPlayers.Value)
{
_players.Add(new PlayerEntry
{
GO = gameObject,
Team = intField,
Name = text
});
}
}
}
}
private static Component[] FindAllComponentsSafe()
{
try
{
MethodInfo method = typeof(Object).GetMethod("FindObjectsByType", BindingFlags.Static | BindingFlags.Public, null, new Type[2]
{
typeof(Type),
typeof(FindObjectsSortMode)
}, null);
if (method != null && method.Invoke(null, new object[2]
{
typeof(Component),
(object)(FindObjectsSortMode)0
}) is Array array)
{
Component[] array2 = (Component[])(object)new Component[array.Length];
Array.Copy(array, array2, array.Length);
return array2;
}
}
catch
{
}
return (Component[])(object)new Component[0];
}
private static int GetIntField(Component c, string field, int def)
{
try
{
FieldInfo field2 = ((object)c).GetType().GetField(field, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (field2 == null)
{
return def;
}
object value = field2.GetValue(c);
if (value == null)
{
return def;
}
if (value.GetType().IsEnum)
{
return Convert.ToInt32(value);
}
return Convert.ToInt32(value);
}
catch
{
return def;
}
}
private static string GetStringField(Component c, string field, string def)
{
try
{
FieldInfo field2 = ((object)c).GetType().GetField(field, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (field2 == null)
{
return def;
}
object value = field2.GetValue(c);
return (value != null) ? value.ToString() : def;
}
catch
{
return def;
}
}
}