Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of AfkEyes v0.1.0
AfkEyes.dll
Decompiled 3 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("AfkEyes")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.0.0")] [assembly: AssemblyInformationalVersion("0.1.0+9688d4009f6fef42019e05f3adc2e94f83cd9091")] [assembly: AssemblyProduct("AfkEyes")] [assembly: AssemblyTitle("AfkEyes")] [assembly: AssemblyVersion("0.1.0.0")] [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 AfkEyes { public class AfkEyesBehavior : MonoBehaviour { private static readonly string[] ClosedNameHints = new string[3] { "clos", "shut", "sleep" }; private float lastActivityTime; private Vector3 lastMousePosition; private bool mouseInit; private bool afkSustaining; private int closedEyesIndex = -2; private bool loggedNames; private bool overrideMissingLogged; private bool broadcastAfk; private void Awake() { lastActivityTime = Time.time; } private void Update() { bool flag = true; float num = 60f; int configIndex = -1; try { if (ConfigSettings.Enabled != null) { flag = ConfigSettings.Enabled.Value; } if (ConfigSettings.AfkSeconds != null) { num = ConfigSettings.AfkSeconds.Value; } if (ConfigSettings.ClosedEyesIndex != null) { configIndex = ConfigSettings.ClosedEyesIndex.Value; } } catch { } if (!flag) { SetBroadcast(afk: false); afkSustaining = false; return; } float time = Time.time; if (!InGameplayLevel() || MenuOpen() || !LocalAvatarAlive(out var avatar)) { lastActivityTime = time; SetBroadcast(afk: false); afkSustaining = false; return; } if (ActivityNow()) { lastActivityTime = time; } if (time - lastActivityTime < num) { SetBroadcast(afk: false); afkSustaining = false; return; } object value; try { value = Traverse.Create((object)avatar).Field("playerExpression").GetValue(); } catch { return; } if (value == null) { return; } int num2 = ResolveIndex(value, configIndex); if (num2 < 0) { return; } if (!afkSustaining) { if (IsExpressing(value, num2)) { return; } afkSustaining = true; SetBroadcast(afk: true); Plugin.Log("AfkEyes: AFK " + num.ToString("F0") + "s, ojos cerrados (gesto " + num2 + ")"); } AfkEyesNetworking.RefreshIfNeeded(sustaining: true); try { Traverse.Create(value).Method("OverrideExpressionSet", new object[2] { num2, 100f }).GetValue(); } catch (Exception ex) { afkSustaining = false; if (!overrideMissingLogged) { overrideMissingLogged = true; Plugin.Log("AfkEyes: OverrideExpressionSet no disponible (" + ex.Message + ")"); } } } private void SetBroadcast(bool afk) { if (broadcastAfk != afk) { broadcastAfk = afk; AfkEyesNetworking.BroadcastAfk(afk); } } private int ResolveIndex(object expression, int configIndex) { if (configIndex >= 0) { return configIndex; } if (closedEyesIndex != -2) { return closedEyesIndex; } try { if (Traverse.Create(expression).Field("expressions").GetValue() is IList list) { string text = ""; for (int i = 0; i < list.Count; i++) { string text2 = Traverse.Create(list[i]).Field("expressionName").GetValue<string>() ?? ""; text = text + ((i > 0) ? ", " : "") + i + ":" + text2; string text3 = text2.ToLowerInvariant(); string[] closedNameHints = ClosedNameHints; foreach (string value in closedNameHints) { if (text3.Contains(value)) { closedEyesIndex = i; Plugin.Log("AfkEyes: gesto ojos cerrados = " + i + " (" + text2 + ")"); return closedEyesIndex; } } } if (!loggedNames) { loggedNames = true; Plugin.Log("AfkEyes: no se encontro gesto de ojos cerrados en [" + text + "], fijar ClosedEyesIndex manual"); } } } catch (Exception ex) { if (!loggedNames) { loggedNames = true; Plugin.Log("AfkEyes: no se pudo leer expresiones (" + ex.Message + ")"); } } closedEyesIndex = -1; return -1; } private static bool IsExpressing(object expression, int index) { try { if (!(Traverse.Create(expression).Field("expressions").GetValue() is IList list) || index < 0 || index >= list.Count) { return false; } return Traverse.Create(list[index]).Field("isExpressing").GetValue<bool>(); } catch { return false; } } private bool ActivityNow() { //IL_000b: 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_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0060: 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_0046: Unknown result type (might be due to invalid IL or missing references) try { if (Input.anyKey) { return true; } Vector3 mousePosition = Input.mousePosition; if (!mouseInit) { lastMousePosition = mousePosition; mouseInit = true; } else { Vector3 val = mousePosition - lastMousePosition; if (((Vector3)(ref val)).sqrMagnitude > 0.5f) { lastMousePosition = mousePosition; return true; } } Vector2 mouseScrollDelta = Input.mouseScrollDelta; if (Mathf.Abs(mouseScrollDelta.x) + Mathf.Abs(mouseScrollDelta.y) > 0.01f) { return true; } } catch { } return false; } internal static bool InGameplayLevel() { try { if ((Object)(object)LevelGenerator.Instance == (Object)null || !LevelGenerator.Instance.Generated) { return false; } RunManager instance = RunManager.instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance.levelCurrent == (Object)null) { return false; } return instance.levelCurrent.HasEnemies; } catch { return false; } } private static bool MenuOpen() { try { MenuManager instance = MenuManager.instance; if ((Object)(object)instance == (Object)null) { return false; } return Traverse.Create((object)instance).Field("currentMenuPage").GetValue() != null; } catch { return false; } } private static bool LocalAvatarAlive(out PlayerAvatar avatar) { avatar = null; try { avatar = PlayerAvatar.instance; if ((Object)(object)avatar == (Object)null) { avatar = null; return false; } Traverse val = Traverse.Create((object)avatar); if (!val.Field("isLocal").GetValue<bool>()) { avatar = null; return false; } if (val.Field("isDisabled").GetValue<bool>()) { return false; } if (val.Field("deadSet").GetValue<bool>()) { return false; } return true; } catch { avatar = null; return false; } } } public class AfkEyesNetworking : MonoBehaviour, IOnEventCallback { private const byte AfkStateEvent = 76; private const float RefreshInterval = 5f; private const float EntryTimeout = 12f; private const float LabelHeight = 2.2f; private readonly Dictionary<int, float> afkSince = new Dictionary<int, float>(); private readonly Dictionary<PlayerAvatar, TextMeshPro> labels = new Dictionary<PlayerAvatar, TextMeshPro>(); private readonly List<PlayerAvatar> deadScratch = new List<PlayerAvatar>(); private bool registered; private float nextRefresh; private float nextLabelPoll; public static AfkEyesNetworking Instance { get; private set; } private void Awake() { Instance = this; } private void OnDisable() { Unregister(); ClearLabels(); afkSince.Clear(); } private void EnsureRegistered() { if (!registered && PhotonNetwork.InRoom) { PhotonNetwork.AddCallbackTarget((object)this); registered = true; } } private void Unregister() { if (registered) { PhotonNetwork.RemoveCallbackTarget((object)this); registered = false; } } private static bool ShouldNetwork() { Room currentRoom = PhotonNetwork.CurrentRoom; if (currentRoom != null) { return currentRoom.PlayerCount > 1; } return false; } public static void BroadcastAfk(bool afk) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004a: 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_0059: Expected O, but got Unknown if ((Object)(object)Instance == (Object)null || !ShouldNetwork()) { return; } int num = ((PhotonNetwork.LocalPlayer != null) ? PhotonNetwork.LocalPlayer.ActorNumber : (-1)); if (num < 0) { return; } try { PhotonNetwork.RaiseEvent((byte)76, (object)new int[2] { num, afk ? 1 : 0 }, new RaiseEventOptions { Receivers = (ReceiverGroup)0 }, SendOptions.SendReliable); } catch { } } public static void RefreshIfNeeded(bool sustaining) { if (!((Object)(object)Instance == (Object)null) && sustaining && ShouldNetwork() && !(Time.time < Instance.nextRefresh)) { Instance.nextRefresh = Time.time + 5f; BroadcastAfk(afk: true); } } public void OnEvent(EventData eventData) { if (eventData.Code != 76 || !(eventData.CustomData is int[] array) || array.Length < 2) { return; } int num = array[0]; if (num != ((PhotonNetwork.LocalPlayer != null) ? PhotonNetwork.LocalPlayer.ActorNumber : (-1))) { if (array[1] == 1) { afkSince[num] = Time.time; } else { afkSince.Remove(num); } } } private void Update() { //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)RunManager.instance == (Object)null || (Object)(object)GameDirector.instance == (Object)null || !SemiFunc.RunIsLevel()) { Unregister(); ClearLabels(); afkSince.Clear(); return; } EnsureRegistered(); ExpireEntries(); Camera main = Camera.main; deadScratch.Clear(); foreach (KeyValuePair<PlayerAvatar, TextMeshPro> label in labels) { if ((Object)(object)label.Key == (Object)null || (Object)(object)label.Value == (Object)null) { deadScratch.Add(label.Key); } else if ((Object)(object)main != (Object)null && ((Component)label.Value).gameObject.activeSelf) { Vector3 val = label.Value.transform.position - ((Component)main).transform.position; if (((Vector3)(ref val)).sqrMagnitude > 0.001f) { label.Value.transform.rotation = Quaternion.LookRotation(val); } } } foreach (PlayerAvatar item in deadScratch) { labels.Remove(item); } deadScratch.Clear(); if (!(Time.time < nextLabelPoll)) { nextLabelPoll = Time.time + 0.25f; PollLabels(); } } private void ExpireEntries() { List<int> list = new List<int>(); foreach (KeyValuePair<int, float> item in afkSince) { if (Time.time - item.Value > 12f) { list.Add(item.Key); } } foreach (int item2 in list) { afkSince.Remove(item2); } } private void PollLabels() { //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: 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) if (!AfkEyesBehavior.InGameplayLevel()) { ClearLabels(); return; } PlayerAvatar[] array; try { array = Object.FindObjectsOfType<PlayerAvatar>(); } catch { return; } HashSet<PlayerAvatar> hashSet = new HashSet<PlayerAvatar>(); int num = ((PhotonNetwork.LocalPlayer != null) ? PhotonNetwork.LocalPlayer.ActorNumber : (-1)); PlayerAvatar[] array2 = array; foreach (PlayerAvatar val in array2) { if ((Object)(object)val == (Object)null) { continue; } int num2 = ActorOf(val); if (num2 >= 0 && num2 != num && afkSince.TryGetValue(num2, out var value) && !(Time.time - value > 12f)) { hashSet.Add(val); TextMeshPro val2 = Ensure(val); val2.transform.position = ((Component)val).transform.position + Vector3.up * 2.2f; if (!((Component)val2).gameObject.activeSelf) { ((Component)val2).gameObject.SetActive(true); } } } deadScratch.Clear(); foreach (KeyValuePair<PlayerAvatar, TextMeshPro> label in labels) { if (!hashSet.Contains(label.Key) && (Object)(object)label.Value != (Object)null && ((Component)label.Value).gameObject.activeSelf) { ((Component)label.Value).gameObject.SetActive(false); } } deadScratch.Clear(); } private static int ActorOf(PlayerAvatar avatar) { try { PhotonView value = Traverse.Create((object)avatar).Field("photonView").GetValue<PhotonView>(); if ((Object)(object)value == (Object)null || value.IsMine) { return -1; } return (value.Owner != null) ? value.Owner.ActorNumber : (-1); } catch { return -1; } } private TextMeshPro Ensure(PlayerAvatar avatar) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) if (labels.TryGetValue(avatar, out var value) && (Object)(object)value != (Object)null) { return value; } GameObject val = new GameObject("AfkEyesLabel"); TextMeshPro val2 = val.AddComponent<TextMeshPro>(); ((TMP_Text)val2).alignment = (TextAlignmentOptions)514; ((TMP_Text)val2).fontSize = 48f; ((Graphic)val2).color = new Color(1f, 0.85f, 0.2f); ((TMP_Text)val2).text = "AFK"; val.transform.localScale = Vector3.one * 0.04f; val.SetActive(false); labels[avatar] = val2; return val2; } private void ClearLabels() { foreach (KeyValuePair<PlayerAvatar, TextMeshPro> label in labels) { if ((Object)(object)label.Value != (Object)null) { Object.Destroy((Object)(object)((Component)label.Value).gameObject); } } labels.Clear(); } } public static class ConfigSettings { public static ConfigEntry<bool> Enabled { get; private set; } public static ConfigEntry<float> AfkSeconds { get; private set; } public static ConfigEntry<int> ClosedEyesIndex { get; private set; } public static void Bind(ConfigFile config) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown Enabled = config.Bind<bool>("AfkEyes", "Enabled", true, "Pone el gesto vainilla de ojos cerrados tras el tiempo AFK configurado."); AfkSeconds = config.Bind<float>("AfkEyes", "AfkSeconds", 60f, new ConfigDescription("Segundos sin input (teclas, mouse, scroll) antes de cerrar los ojos. Solo en niveles con enemigos.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 600f), Array.Empty<object>())); ClosedEyesIndex = config.Bind<int>("AfkEyes", "ClosedEyesIndex", -1, new ConfigDescription("-1 = detectar el gesto por nombre (sleep/closed/shut). Si la deteccion falla (ver log), fijar el indice manual.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(-1, 20), Array.Empty<object>())); } } [BepInPlugin("yo.AfkEyes", "AfkEyes", "0.1.0")] [BepInProcess("REPO.exe")] public class Plugin : BaseUnityPlugin { private static ManualLogSource logSource; public static Plugin Instance { get; private set; } private void Awake() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) Instance = this; ConfigSettings.Bind(((BaseUnityPlugin)this).Config); logSource = Logger.CreateLogSource("AfkEyes"); GameObject val = new GameObject("AfkEyes"); Object.DontDestroyOnLoad((Object)val); ((Object)val).hideFlags = (HideFlags)61; val.AddComponent<AfkEyesBehavior>(); val.AddComponent<AfkEyesNetworking>(); Log("AfkEyes v0.1.0 loaded | Enabled=" + ConfigSettings.Enabled.Value); } public static void Log(string message) { logSource.LogInfo((object)message); } } public static class PluginInfo { public const string PLUGIN_GUID = "yo.AfkEyes"; public const string PLUGIN_NAME = "AfkEyes"; public const string PLUGIN_VERSION = "0.1.0"; } }