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 SilksongFocusQoL v1.0.1
SilksongFocusQoL.dll
Decompiled 9 months 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 UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("SilksongFocusQoL")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.1.0")] [assembly: AssemblyInformationalVersion("1.0.1+8bbdc76b8b2ca802848b84675715a160716bb538")] [assembly: AssemblyProduct("SilksongFocusQoL")] [assembly: AssemblyTitle("SilksongFocusQoL")] [assembly: AssemblyVersion("1.0.1.0")] [BepInPlugin("com.zlq.silksongfocusqol", "Silksong Focus QoL", "1.0.1")] public class SilksongFocusQoL : BaseUnityPlugin { private class FocusQoLBehaviour : MonoBehaviour { [CompilerGenerated] private sealed class <TimeoutTracking>d__20 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public FocusQoLBehaviour <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <TimeoutTracking>d__20(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown int num = <>1__state; FocusQoLBehaviour focusQoLBehaviour = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSecondsRealtime(focusQoLBehaviour.autoUnpauseWindow.Value); <>1__state = 1; return true; case 1: <>1__state = -1; focusQoLBehaviour.isTrackingTime = false; focusQoLBehaviour.timeoutCoroutine = null; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private bool wasPausedByMod; private bool wasAlreadyPaused; private float focusLostTime; private bool isTrackingTime; private Coroutine timeoutCoroutine; private bool wantsToPause; private ConfigEntry<bool> enableAutoPause; private ConfigEntry<bool> enableAutoUnpause; private ConfigEntry<float> autoUnpauseWindow; private ConfigEntry<bool> enableAutoMute; private Type gameManagerType; private PropertyInfo instanceProp; private MethodInfo isGamePausedMethod; private MethodInfo pauseGameToggle; private ParameterInfo[] pauseMethodParameters; public void SetConfig(ConfigEntry<bool> enableAutoPause, ConfigEntry<bool> enableAutoUnpause, ConfigEntry<float> autoUnpauseWindow, ConfigEntry<bool> enableAutoMute) { this.enableAutoPause = enableAutoPause; this.enableAutoUnpause = enableAutoUnpause; this.autoUnpauseWindow = autoUnpauseWindow; this.enableAutoMute = enableAutoMute; CacheGameManagerMethods(); } private void CacheGameManagerMethods() { gameManagerType = Type.GetType("GameManager") ?? FindTypeByName("GameManager"); if (gameManagerType != null) { instanceProp = gameManagerType.GetProperty("instance", BindingFlags.Static | BindingFlags.Public) ?? gameManagerType.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public); isGamePausedMethod = gameManagerType.GetMethod("IsGamePaused", BindingFlags.Instance | BindingFlags.Public); pauseGameToggle = gameManagerType.GetMethod("PauseGameToggle", BindingFlags.Instance | BindingFlags.Public); if (pauseGameToggle != null) { pauseMethodParameters = pauseGameToggle.GetParameters(); } } } private void Update() { if (wantsToPause && !IsGamePaused()) { AttemptToPauseGame(); } } private void OnApplicationFocus(bool hasFocus) { if (!((Behaviour)this).isActiveAndEnabled) { return; } try { if (!hasFocus) { focusLostTime = Time.unscaledTime; wasAlreadyPaused = IsGamePaused(); if (enableAutoPause.Value) { wantsToPause = true; if (!wasAlreadyPaused) { AttemptToPauseGame(); } } if (enableAutoUnpause.Value && autoUnpauseWindow.Value > 0f) { isTrackingTime = true; StopTrackingCoroutine(); timeoutCoroutine = ((MonoBehaviour)this).StartCoroutine(TimeoutTracking()); } } else { wantsToPause = false; StopTrackingCoroutine(); if (enableAutoUnpause.Value && wasPausedByMod) { bool flag = true; if (autoUnpauseWindow.Value > 0f) { flag = isTrackingTime && Time.unscaledTime - focusLostTime <= autoUnpauseWindow.Value; } if (flag) { AttemptToUnpauseGame(); } } wasPausedByMod = false; wasAlreadyPaused = false; isTrackingTime = false; } if (enableAutoMute.Value) { AudioListener.pause = !hasFocus; } } catch (Exception) { } } private void StopTrackingCoroutine() { if (timeoutCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(timeoutCoroutine); timeoutCoroutine = null; } } [IteratorStateMachine(typeof(<TimeoutTracking>d__20))] private IEnumerator TimeoutTracking() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <TimeoutTracking>d__20(0) { <>4__this = this }; } private bool IsGamePaused() { try { if (gameManagerType == null || instanceProp == null || isGamePausedMethod == null) { return false; } object value = instanceProp.GetValue(null); if (value == null) { return false; } return (bool)isGamePausedMethod.Invoke(value, null); } catch { return false; } } private void AttemptToPauseGame() { try { if (gameManagerType == null || instanceProp == null || pauseGameToggle == null) { return; } object value = instanceProp.GetValue(null); if (value != null && !IsGamePaused()) { object obj = null; if (pauseMethodParameters.Length == 1 && pauseMethodParameters[0].ParameterType == typeof(bool)) { obj = pauseGameToggle.Invoke(value, new object[1] { true }); } else if (pauseMethodParameters.Length == 0) { obj = pauseGameToggle.Invoke(value, null); } if (obj != null && obj is IEnumerator) { ((MonoBehaviour)this).StartCoroutine((IEnumerator)obj); wasPausedByMod = true; } } } catch { } } private void AttemptToUnpauseGame() { try { if (gameManagerType == null || instanceProp == null || pauseGameToggle == null) { return; } object value = instanceProp.GetValue(null); if (value != null && IsGamePaused() && wasPausedByMod) { object obj = null; if (pauseMethodParameters.Length == 1 && pauseMethodParameters[0].ParameterType == typeof(bool)) { obj = pauseGameToggle.Invoke(value, new object[1] { false }); } else if (pauseMethodParameters.Length == 0) { obj = pauseGameToggle.Invoke(value, null); } if (obj != null && obj is IEnumerator) { ((MonoBehaviour)this).StartCoroutine((IEnumerator)obj); } } } catch { } } private Type FindTypeByName(string typeName) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { try { Type[] types = assembly.GetTypes(); foreach (Type type in types) { if (type.Name == typeName) { return type; } } } catch (ReflectionTypeLoadException) { } } return null; } private void OnDisable() { StopTrackingCoroutine(); } } private GameObject focusQoLBehaviourObject; private ConfigEntry<bool> configEnableAutoPause; private ConfigEntry<bool> configEnableAutoUnpause; private ConfigEntry<float> configAutoUnpauseWindow; private ConfigEntry<bool> configEnableAutoMute; private void Awake() { //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Expected O, but got Unknown //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Expected O, but got Unknown ValidateConfig(); configEnableAutoMute = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "EnableAutoMute", true, "Mute audio when window loses focus"); configEnableAutoPause = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "EnableAutoPause", true, "Pause game when window loses focus"); configEnableAutoUnpause = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "EnableAutoUnpause", true, "Unpause when focus returns"); configAutoUnpauseWindow = ((BaseUnityPlugin)this).Config.Bind<float>("Settings", "AutoUnpauseWindow", 3f, new ConfigDescription("Time window to auto-unpause\n0 = always unpause when focus returns; >0 = only if refocus occurs within this many seconds", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 30f), Array.Empty<object>())); ((BaseUnityPlugin)this).Config.SettingChanged += OnConfigChanged; focusQoLBehaviourObject = new GameObject("SilksongFocusQoLBehaviour", new Type[1] { typeof(FocusQoLBehaviour) }); Object.DontDestroyOnLoad((Object)(object)focusQoLBehaviourObject); focusQoLBehaviourObject.GetComponent<FocusQoLBehaviour>().SetConfig(configEnableAutoPause, configEnableAutoUnpause, configAutoUnpauseWindow, configEnableAutoMute); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Silksong Focus QoL loaded"); } private void ValidateConfig() { ConfigEntry<float> obj = configAutoUnpauseWindow; if (obj != null && obj.Value < 0f) { configAutoUnpauseWindow.Value = 0f; } } private void OnConfigChanged(object sender, SettingChangedEventArgs e) { try { ((BaseUnityPlugin)this).Logger.LogInfo((object)("Config updated: [" + e.ChangedSetting.Definition.Section + "] " + e.ChangedSetting.Definition.Key)); GameObject obj = focusQoLBehaviourObject; FocusQoLBehaviour focusQoLBehaviour = ((obj != null) ? obj.GetComponent<FocusQoLBehaviour>() : null); if ((Object)(object)focusQoLBehaviour != (Object)null) { focusQoLBehaviour.SetConfig(configEnableAutoPause, configEnableAutoUnpause, configAutoUnpauseWindow, configEnableAutoMute); } } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"Error applying config change: {arg}"); } } private void OnDestroy() { ((BaseUnityPlugin)this).Config.SettingChanged -= OnConfigChanged; if ((Object)(object)focusQoLBehaviourObject != (Object)null) { Object.Destroy((Object)(object)focusQoLBehaviourObject); } } }