using System;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("Isanyonealive")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Isanyonealive")]
[assembly: AssemblyCopyright("Copyright © 2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("b25d8b43-3d95-4094-9170-f3523a42e5e1")]
[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 LobbyPlayerStatus;
[BepInPlugin("hoppinhaulers_isanyonealive", "isanyonealive", "1.3.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class Plugin : BaseUnityPlugin
{
private enum DisplayMode
{
All,
AliveOnly,
DeadOnly
}
private struct SimpleShortcut
{
public Key Main;
public bool Ctrl;
public bool Alt;
public bool Shift;
public static SimpleShortcut Parse(string raw)
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_012d: Unknown result type (might be due to invalid IL or missing references)
//IL_012f: Unknown result type (might be due to invalid IL or missing references)
SimpleShortcut simpleShortcut = default(SimpleShortcut);
simpleShortcut.Main = (Key)0;
SimpleShortcut result = simpleShortcut;
if (string.IsNullOrWhiteSpace(raw))
{
return result;
}
string[] array = raw.Split(new char[1] { '+' }, StringSplitOptions.RemoveEmptyEntries);
string[] array2 = array;
foreach (string text in array2)
{
string text2 = text.Trim();
if (EqualsAny(text2, "Ctrl", "Control", "LeftCtrl", "RightCtrl", "LeftControl", "RightControl"))
{
result.Ctrl = true;
continue;
}
if (EqualsAny(text2, "Alt", "LeftAlt", "RightAlt"))
{
result.Alt = true;
continue;
}
if (EqualsAny(text2, "Shift", "LeftShift", "RightShift"))
{
result.Shift = true;
continue;
}
string value = NormalizeKeyToken(text2);
if (Enum.TryParse<Key>(value, ignoreCase: true, out Key result2))
{
result.Main = result2;
}
}
return result;
}
public bool IsDown()
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Invalid comparison between Unknown and I4
//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
if ((int)Main == 0)
{
return false;
}
Keyboard current = Keyboard.current;
if (current == null)
{
return false;
}
if (Ctrl && !((ButtonControl)current.leftCtrlKey).isPressed && !((ButtonControl)current.rightCtrlKey).isPressed)
{
return false;
}
if (Alt && !((ButtonControl)current.leftAltKey).isPressed && !((ButtonControl)current.rightAltKey).isPressed)
{
return false;
}
if (Shift && !((ButtonControl)current.leftShiftKey).isPressed && !((ButtonControl)current.rightShiftKey).isPressed)
{
return false;
}
KeyControl val = current[Main];
return val != null && ((ButtonControl)val).wasPressedThisFrame;
}
public override string ToString()
{
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
StringBuilder stringBuilder = new StringBuilder();
if (Ctrl)
{
stringBuilder.Append("Ctrl+");
}
if (Alt)
{
stringBuilder.Append("Alt+");
}
if (Shift)
{
stringBuilder.Append("Shift+");
}
stringBuilder.Append(Main);
return stringBuilder.ToString();
}
private static bool EqualsAny(string s, params string[] vals)
{
foreach (string value in vals)
{
if (s.Equals(value, StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
return false;
}
private static string NormalizeKeyToken(string token)
{
if (token.Length == 1 && char.IsDigit(token[0]))
{
return (token[0] == '0') ? "Digit0" : ("Digit" + token);
}
if (token.Equals("Esc", StringComparison.OrdinalIgnoreCase))
{
return "Escape";
}
if (token.Equals("Del", StringComparison.OrdinalIgnoreCase))
{
return "Delete";
}
if (token.Equals("Return", StringComparison.OrdinalIgnoreCase))
{
return "Enter";
}
return token;
}
}
public const string ModGuid = "hoppinhaulers_isanyonealive";
public const string ModName = "isanyonealive";
public const string ModVersion = "1.3.0";
internal static ManualLogSource Log;
private Harmony _harmony;
private GameObject _canvasGo;
private TextMeshProUGUI _text;
private RectTransform _textRect;
private float _nextRefreshTime;
private ConfigEntry<bool> _enabled;
private ConfigEntry<float> _refreshInterval;
private ConfigEntry<bool> _showEmptySlots;
private ConfigEntry<float> _posX;
private ConfigEntry<float> _posY;
private ConfigEntry<int> _fontSize;
private ConfigEntry<string> _toggleOverlayKey;
private ConfigEntry<string> _cycleModeKey;
private SimpleShortcut _toggleShortcut;
private SimpleShortcut _cycleShortcut;
private DisplayMode _mode = DisplayMode.All;
private const bool DebugHotkeys = true;
private void Awake()
{
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
//IL_00a9: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
BindConfig();
ParseHotkeysFromConfig();
_toggleOverlayKey.SettingChanged += delegate
{
ParseHotkeysFromConfig();
};
_cycleModeKey.SettingChanged += delegate
{
ParseHotkeysFromConfig();
};
_posX.SettingChanged += delegate
{
ApplyUiLayout();
};
_posY.SettingChanged += delegate
{
ApplyUiLayout();
};
_fontSize.SettingChanged += delegate
{
ApplyUiLayout();
};
TryRegisterLethalConfigItems_Reflection();
_harmony = new Harmony("hoppinhaulers_isanyonealive");
_harmony.PatchAll(typeof(Plugin));
EnsureUi();
Log.LogInfo((object)"isanyonealive v1.3.0 loaded.");
}
private void OnDestroy()
{
try
{
Harmony harmony = _harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
}
catch
{
}
try
{
if ((Object)(object)_canvasGo != (Object)null)
{
Object.Destroy((Object)(object)_canvasGo);
}
}
catch
{
}
}
private void BindConfig()
{
_enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable/disable the overlay entirely.");
_refreshInterval = ((BaseUnityPlugin)this).Config.Bind<float>("General", "RefreshIntervalSeconds", 0.5f, "Refresh interval (seconds).");
_showEmptySlots = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "ShowEmptySlots", false, "Show empty/null slots.");
_posX = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "PositionX", 20f, "Overlay X (top-left anchor).");
_posY = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "PositionY", 20f, "Overlay Y (top-left anchor).");
_fontSize = ((BaseUnityPlugin)this).Config.Bind<int>("Display", "FontSize", 18, "Font size.");
_toggleOverlayKey = ((BaseUnityPlugin)this).Config.Bind<string>("Hotkeys", "ToggleOverlay", "F8", "Toggle overlay hotkey (e.g. F8, LeftCtrl+F8).");
_cycleModeKey = ((BaseUnityPlugin)this).Config.Bind<string>("Hotkeys", "CycleMode", "F9", "Cycle mode hotkey (e.g. F9, LeftCtrl+F9).");
}
private void Update()
{
EnsureUi();
HandleHotkeys();
if ((Object)(object)_text == (Object)null)
{
return;
}
if (!_enabled.Value)
{
((Behaviour)_text).enabled = false;
return;
}
((Behaviour)_text).enabled = true;
if (!(Time.unscaledTime < _nextRefreshTime))
{
_nextRefreshTime = Time.unscaledTime + Mathf.Max(0.05f, _refreshInterval.Value);
((TMP_Text)_text).text = BuildStatusText();
}
}
private void EnsureUi()
{
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Expected O, but got Unknown
//IL_0090: Unknown result type (might be due to invalid IL or missing references)
//IL_0096: Expected O, but got Unknown
//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
//IL_0100: Unknown result type (might be due to invalid IL or missing references)
//IL_011b: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)_canvasGo != (Object)null) || !((Object)(object)_text != (Object)null))
{
_canvasGo = new GameObject("LobbyPlayerStatus_Canvas");
Object.DontDestroyOnLoad((Object)(object)_canvasGo);
Canvas val = _canvasGo.AddComponent<Canvas>();
val.renderMode = (RenderMode)0;
val.sortingOrder = 9999;
CanvasGroup val2 = _canvasGo.AddComponent<CanvasGroup>();
val2.blocksRaycasts = false;
val2.interactable = false;
_canvasGo.AddComponent<CanvasScaler>();
GameObject val3 = new GameObject("LobbyPlayerStatus_Text");
val3.transform.SetParent(_canvasGo.transform, false);
_textRect = val3.AddComponent<RectTransform>();
_textRect.anchorMin = new Vector2(0f, 1f);
_textRect.anchorMax = new Vector2(0f, 1f);
_textRect.pivot = new Vector2(0f, 1f);
_textRect.sizeDelta = new Vector2(900f, 900f);
_text = val3.AddComponent<TextMeshProUGUI>();
((TMP_Text)_text).enableWordWrapping = false;
((TMP_Text)_text).richText = true;
((TMP_Text)_text).alignment = (TextAlignmentOptions)257;
((TMP_Text)_text).text = "Overlay initialized...";
ApplyUiLayout();
((Graphic)_text).raycastTarget = false;
Log.LogInfo((object)"Overlay UI created (own Canvas).");
}
}
private void ApplyUiLayout()
{
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)_text == (Object)null) && !((Object)(object)_textRect == (Object)null))
{
_textRect.anchoredPosition = new Vector2(_posX.Value, 0f - _posY.Value);
((TMP_Text)_text).fontSize = Mathf.Clamp(_fontSize.Value, 8, 80);
}
}
private void HandleHotkeys()
{
if (Keyboard.current != null)
{
if (_toggleShortcut.IsDown())
{
_enabled.Value = !_enabled.Value;
((BaseUnityPlugin)this).Config.Save();
bool flag = true;
Log.LogInfo((object)$"ToggleOverlay pressed. Enabled = {_enabled.Value}");
}
if (_cycleShortcut.IsDown())
{
_mode = (DisplayMode)((int)(_mode + 1) % 3);
bool flag2 = true;
Log.LogInfo((object)$"CycleMode pressed. Mode = {_mode}");
}
}
}
private string BuildStatusText()
{
StartOfRound instance = StartOfRound.Instance;
if ((Object)(object)instance == (Object)null || instance.allPlayerScripts == null)
{
return "<b>Players:</b>\n(no StartOfRound yet)";
}
StringBuilder stringBuilder = new StringBuilder(256);
stringBuilder.Append("<b>Players:</b>\n");
PlayerControllerB[] allPlayerScripts = instance.allPlayerScripts;
for (int i = 0; i < allPlayerScripts.Length; i++)
{
PlayerControllerB val = allPlayerScripts[i];
if ((Object)(object)val == (Object)null)
{
if (_showEmptySlots.Value)
{
stringBuilder.Append($"Slot {i + 1}: —\n");
}
continue;
}
string text = val.playerUsername;
if (string.IsNullOrWhiteSpace(text))
{
text = $"Player {i + 1}";
}
bool isPlayerDead = val.isPlayerDead;
bool flag = !val.isPlayerControlled && !isPlayerDead;
if ((_mode != DisplayMode.AliveOnly || !(isPlayerDead || flag)) && (_mode != DisplayMode.DeadOnly || isPlayerDead))
{
if (isPlayerDead)
{
stringBuilder.Append(text + ": <color=#ff4d4d>DEAD</color>\n");
}
else if (flag)
{
stringBuilder.Append(text + ": <color=#ffd24d>NOT IN GAME</color>\n");
}
else
{
stringBuilder.Append(text + ": <color=#4dff88>ALIVE</color>\n");
}
}
}
stringBuilder.Append($"\n<alpha=#AA>Mode: {_mode} | Toggle: {_toggleOverlayKey.Value} | Cycle: {_cycleModeKey.Value}</alpha>");
return stringBuilder.ToString().TrimEnd(Array.Empty<char>());
}
private void ParseHotkeysFromConfig()
{
_toggleShortcut = SimpleShortcut.Parse(_toggleOverlayKey.Value);
_cycleShortcut = SimpleShortcut.Parse(_cycleModeKey.Value);
Log.LogInfo((object)$"Hotkeys parsed: Toggle={_toggleShortcut}, Cycle={_cycleShortcut}");
}
private void TryRegisterLethalConfigItems_Reflection()
{
if (!Chainloader.PluginInfos.ContainsKey("ainavt.lc.lethalconfig"))
{
return;
}
try
{
Assembly lcAsm = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name.Equals("LethalConfig", StringComparison.OrdinalIgnoreCase));
MethodInfo addMethod;
if (!(lcAsm == null))
{
Type type = lcAsm.GetType("LethalConfig.LethalConfigManager", throwOnError: false);
addMethod = type?.GetMethod("AddConfigItem", BindingFlags.Static | BindingFlags.Public);
if (!(type == null) && !(addMethod == null))
{
object obj2 = New("LethalConfig.ConfigItems.Options.BaseOptions");
SetProp(obj2, "RequiresRestart", false);
object obj3 = New("LethalConfig.ConfigItems.Options.FloatSliderOptions");
SetProp(obj3, "Min", 0.1f);
SetProp(obj3, "Max", 2f);
SetProp(obj3, "RequiresRestart", false);
object obj4 = New("LethalConfig.ConfigItems.Options.FloatSliderOptions");
SetProp(obj4, "Min", 0f);
SetProp(obj4, "Max", 900f);
SetProp(obj4, "RequiresRestart", false);
object obj5 = New("LethalConfig.ConfigItems.Options.FloatSliderOptions");
SetProp(obj5, "Min", 0f);
SetProp(obj5, "Max", 700f);
SetProp(obj5, "RequiresRestart", false);
object obj6 = New("LethalConfig.ConfigItems.Options.IntSliderOptions");
SetProp(obj6, "Min", 10);
SetProp(obj6, "Max", 40);
SetProp(obj6, "RequiresRestart", false);
object obj7 = New("LethalConfig.ConfigItems.Options.TextInputFieldOptions");
SetProp(obj7, "RequiresRestart", false);
Add(NewItem("LethalConfig.ConfigItems.BoolCheckBoxConfigItem", _enabled, obj2));
Add(NewItem("LethalConfig.ConfigItems.FloatSliderConfigItem", _refreshInterval, obj3));
Add(NewItem("LethalConfig.ConfigItems.BoolCheckBoxConfigItem", _showEmptySlots, obj2));
Add(NewItem("LethalConfig.ConfigItems.FloatSliderConfigItem", _posX, obj4));
Add(NewItem("LethalConfig.ConfigItems.FloatSliderConfigItem", _posY, obj5));
Add(NewItem("LethalConfig.ConfigItems.IntSliderConfigItem", _fontSize, obj6));
Add(NewItem("LethalConfig.ConfigItems.TextInputFieldConfigItem", _toggleOverlayKey, obj7));
Add(NewItem("LethalConfig.ConfigItems.TextInputFieldConfigItem", _cycleModeKey, obj7));
Log.LogInfo((object)"LethalConfig UI registered (reflection).");
}
}
void Add(object item)
{
if (item != null)
{
addMethod.Invoke(null, new object[1] { item });
}
}
object New(string typeName)
{
return Activator.CreateInstance(lcAsm.GetType(typeName, throwOnError: false));
}
object NewItem(string typeName, object entry, object options)
{
return Activator.CreateInstance(lcAsm.GetType(typeName, throwOnError: false), entry, options);
}
}
catch (Exception arg)
{
Log.LogWarning((object)$"LethalConfig UI registration failed: {arg}");
}
static void SetProp(object obj, string prop, object val)
{
if (obj != null)
{
PropertyInfo property = obj.GetType().GetProperty(prop, BindingFlags.Instance | BindingFlags.Public);
if (property != null && property.CanWrite)
{
property.SetValue(obj, val);
}
}
}
}
}