using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using System.Threading;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyCompany("VoiceFixMod")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("My first plugin")]
[assembly: AssemblyTitle("VoiceFixMod")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.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 VoiceFixMod
{
[BepInPlugin("com.Kingo.voicefix", "VoiceFixMod", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
public const string GUID = "com.Kingo.voicefix";
public const string Name = "VoiceFixMod";
public const string Version = "1.0.0";
internal static ManualLogSource LogS;
private Harmony _harmony;
private static ConfigEntry<float> _silenceSecondsBeforeReinit;
private static ConfigEntry<float> _keepAliveEverySeconds;
private static ConfigEntry<float> _reinitCooldownSeconds;
private static ConfigEntry<bool> _enableAutoReinit;
private static ConfigEntry<bool> _enableKeepAlive;
private static ConfigEntry<bool> _verboseLogs;
private static ConfigEntry<KeyCode> _forceReinitKey;
private VoiceFixController _controller;
private GameObject _controllerGO;
private void Awake()
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Expected O, but got Unknown
//IL_011e: Unknown result type (might be due to invalid IL or missing references)
//IL_0128: Expected O, but got Unknown
//IL_0180: Unknown result type (might be due to invalid IL or missing references)
LogS = ((BaseUnityPlugin)this).Logger;
_harmony = new Harmony("com.Kingo.voicefix");
_harmony.PatchAll();
_silenceSecondsBeforeReinit = ((BaseUnityPlugin)this).Config.Bind<float>("Watchdog", "SilenceSecondsBeforeReinit", 35f, "If no inbound voice is heard for this many seconds, re-initialize voice.");
_keepAliveEverySeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Watchdog", "KeepAliveEverySeconds", 8f, "How often to send a tiny keep-alive (quick mic toggle) to prevent idle timeouts.");
_reinitCooldownSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Watchdog", "ReinitCooldownSeconds", 20f, "Minimum time between automatic re-inits.");
_enableAutoReinit = ((BaseUnityPlugin)this).Config.Bind<bool>("Watchdog", "EnableAutoReinit", true, "Automatically re-initialize voice when silence threshold is reached.");
_enableKeepAlive = ((BaseUnityPlugin)this).Config.Bind<bool>("Watchdog", "EnableKeepAlive", true, "Periodically nudge the voice backend so it doesn't sleep.");
_verboseLogs = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "VerboseLogs", false, "Extra debug logs.");
_forceReinitKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Hotkeys", "ForceReinitKey", (KeyCode)291, "Hold LeftShift + press this key to force a voice re-init.");
_controllerGO = new GameObject("VoiceFixMod_Controller");
_controller = _controllerGO.AddComponent<VoiceFixController>();
_controller.Init(_silenceSecondsBeforeReinit.Value, _keepAliveEverySeconds.Value, _reinitCooldownSeconds.Value, _enableAutoReinit.Value, _enableKeepAlive.Value, _verboseLogs.Value, _forceReinitKey.Value);
Object.DontDestroyOnLoad((Object)(object)_controllerGO);
LogS.LogInfo((object)("VoiceFixMod 1.0.0 loaded. GameRoot: " + Paths.GameRootPath));
}
private void OnDestroy()
{
try
{
Harmony harmony = _harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
}
catch
{
}
if (!((Object)(object)_controller != (Object)null))
{
return;
}
try
{
Object.Destroy((Object)(object)_controller);
}
catch
{
}
try
{
if (Object.op_Implicit((Object)(object)_controllerGO))
{
Object.Destroy((Object)(object)_controllerGO);
}
}
catch
{
}
}
}
internal class VoiceFixController : MonoBehaviour
{
[CompilerGenerated]
private sealed class <LateStart>d__18 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
public VoiceFixController <>4__this;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <LateStart>d__18(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Expected O, but got Unknown
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<>2__current = (object)new WaitForSeconds(2f);
<>1__state = 1;
return true;
case 1:
<>1__state = -1;
<>4__this.DiscoverBackend();
<>4__this.AttachAudioTaps();
<>4__this._inited = true;
Plugin.LogS.LogInfo((object)"[VoiceFix] Initialization complete.");
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();
}
}
[CompilerGenerated]
private sealed class <ReinitializeVoice>d__25 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
public string reason;
public VoiceFixController <>4__this;
private Behaviour[] <comps>5__1;
private Behaviour[] <>s__2;
private int <>s__3;
private Behaviour <comp>5__4;
private Type <t>5__5;
private bool <invokedAny>5__6;
private bool <needDelay>5__7;
private string[] <tries>5__8;
private string[] <>s__9;
private int <>s__10;
private string <name>5__11;
private MethodInfo <m>5__12;
private Exception <ex>5__13;
private Exception <ex>5__14;
private bool <disabled>5__15;
private Exception <ex>5__16;
private Exception <ex>5__17;
private int <i>5__18;
private AudioActivityTap <tap>5__19;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <ReinitializeVoice>d__25(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<comps>5__1 = null;
<>s__2 = null;
<comp>5__4 = null;
<t>5__5 = null;
<tries>5__8 = null;
<>s__9 = null;
<name>5__11 = null;
<m>5__12 = null;
<ex>5__13 = null;
<ex>5__14 = null;
<ex>5__16 = null;
<ex>5__17 = null;
<tap>5__19 = null;
<>1__state = -2;
}
private bool MoveNext()
{
//IL_0358: Unknown result type (might be due to invalid IL or missing references)
//IL_0362: Expected O, but got Unknown
//IL_03e5: Unknown result type (might be due to invalid IL or missing references)
//IL_03ef: Expected O, but got Unknown
//IL_0509: Unknown result type (might be due to invalid IL or missing references)
//IL_0513: Expected O, but got Unknown
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<>4__this._lastReinit = Time.realtimeSinceStartup;
Plugin.LogS.LogWarning((object)("[VoiceFix] Re-initializing voice (" + reason + ")."));
<comps>5__1 = (Behaviour[])(object)new Behaviour[3] { <>4__this._dissonanceComms, <>4__this._vivoxMgr, <>4__this._genericVoiceMgr };
<>s__2 = <comps>5__1;
<>s__3 = 0;
goto IL_045d;
case 1:
<>1__state = -1;
goto IL_0372;
case 2:
<>1__state = -1;
try
{
<comp>5__4.enabled = true;
}
catch (Exception ex)
{
<ex>5__17 = ex;
Plugin.LogS.LogWarning((object)("[VoiceFix] Soft-enable failed: " + <ex>5__17.Message));
}
goto IL_0440;
case 3:
{
<>1__state = -1;
<>4__this.AttachAudioTaps();
<>4__this._lastHeardTime = Time.realtimeSinceStartup;
Plugin.LogS.LogInfo((object)"[VoiceFix] Voice re-init attempt complete.");
return false;
}
IL_045d:
if (<>s__3 < <>s__2.Length)
{
<comp>5__4 = <>s__2[<>s__3];
if ((Object)(object)<comp>5__4 == (Object)null)
{
goto IL_044f;
}
<t>5__5 = ((object)<comp>5__4).GetType();
<invokedAny>5__6 = false;
<needDelay>5__7 = false;
try
{
<tries>5__8 = new string[10] { "Reset", "Reinit", "ReInitialize", "Initialize", "Init", "Shutdown", "Stop", "Start", "Login", "Reconnect" };
<>s__9 = <tries>5__8;
for (<>s__10 = 0; <>s__10 < <>s__9.Length; <>s__10++)
{
<name>5__11 = <>s__9[<>s__10];
<m>5__12 = <t>5__5.GetMethod(<name>5__11, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
if ((object)<m>5__12 != null)
{
if (<>4__this._verbose)
{
Plugin.LogS.LogDebug((object)("[VoiceFix] Calling " + <t>5__5.Name + "." + <name>5__11 + "()"));
}
try
{
<m>5__12.Invoke(<comp>5__4, null);
<invokedAny>5__6 = true;
if (<name>5__11.Equals("Shutdown", StringComparison.OrdinalIgnoreCase) || <name>5__11.Equals("Stop", StringComparison.OrdinalIgnoreCase))
{
<needDelay>5__7 = true;
}
}
catch (Exception ex)
{
<ex>5__13 = ex;
Plugin.LogS.LogWarning((object)("[VoiceFix] " + <t>5__5.Name + "." + <name>5__11 + "() invocation failed: " + <ex>5__13.Message));
}
}
<m>5__12 = null;
<name>5__11 = null;
}
<>s__9 = null;
<tries>5__8 = null;
}
catch (Exception ex)
{
<ex>5__14 = ex;
Plugin.LogS.LogWarning((object)("[VoiceFix] Reinit reflection on " + <t>5__5.FullName + " failed: " + <ex>5__14.Message));
}
if (<needDelay>5__7)
{
<>2__current = (object)new WaitForSeconds(0.15f);
<>1__state = 1;
return true;
}
goto IL_0372;
}
<>s__2 = null;
<i>5__18 = 0;
while (<i>5__18 < <>4__this._taps.Count)
{
<tap>5__19 = <>4__this._taps[<i>5__18];
if (Object.op_Implicit((Object)(object)<tap>5__19))
{
Object.Destroy((Object)(object)<tap>5__19);
}
<tap>5__19 = null;
<i>5__18++;
}
<>4__this._taps.Clear();
<>2__current = (object)new WaitForSeconds(0.25f);
<>1__state = 3;
return true;
IL_0440:
<t>5__5 = null;
<comp>5__4 = null;
goto IL_044f;
IL_0372:
if (!<invokedAny>5__6)
{
<disabled>5__15 = false;
try
{
<comp>5__4.enabled = false;
<disabled>5__15 = true;
}
catch (Exception ex)
{
<ex>5__16 = ex;
Plugin.LogS.LogWarning((object)("[VoiceFix] Soft-disable failed: " + <ex>5__16.Message));
}
if (<disabled>5__15)
{
<>2__current = (object)new WaitForSeconds(0.05f);
<>1__state = 2;
return true;
}
}
goto IL_0440;
IL_044f:
<>s__3++;
goto IL_045d;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
[CompilerGenerated]
private sealed class <SendKeepAlive>d__24 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
public VoiceFixController <>4__this;
private bool <nudged>5__1;
private Type <t>5__2;
private PropertyInfo <prop>5__3;
private object <currObj>5__4;
private bool <curr>5__5;
private bool <setOk>5__6;
private Exception <ex>5__7;
private Exception <ex>5__8;
private Exception <ex>5__9;
private bool <disabled>5__10;
private Exception <ex>5__11;
private Exception <ex>5__12;
private bool <disabled>5__13;
private Exception <ex>5__14;
private Exception <ex>5__15;
private bool <disabled>5__16;
private Exception <ex>5__17;
private Exception <ex>5__18;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <SendKeepAlive>d__24(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<t>5__2 = null;
<prop>5__3 = null;
<currObj>5__4 = null;
<ex>5__7 = null;
<ex>5__8 = null;
<ex>5__9 = null;
<ex>5__11 = null;
<ex>5__12 = null;
<ex>5__14 = null;
<ex>5__15 = null;
<ex>5__17 = null;
<ex>5__18 = null;
<>1__state = -2;
}
private bool MoveNext()
{
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
if (<>4__this._verbose)
{
Plugin.LogS.LogDebug((object)"[VoiceFix] Keep-alive tick.");
}
<nudged>5__1 = false;
if ((Object)(object)<>4__this._dissonanceComms != (Object)null)
{
<t>5__2 = ((object)<>4__this._dissonanceComms).GetType();
<prop>5__3 = <>4__this.FindFirstProperty(<t>5__2, new string[5] { "IsMuted", "IsMicMuted", "Muted", "isMuted", "muted" });
if ((object)<prop>5__3 != null)
{
<currObj>5__4 = null;
try
{
<currObj>5__4 = <prop>5__3.GetValue(<>4__this._dissonanceComms, null);
}
catch (Exception ex)
{
<ex>5__7 = ex;
Plugin.LogS.LogDebug((object)("[VoiceFix] prop.GetValue failed: " + <ex>5__7.Message));
}
<curr>5__5 = <>4__this.SafeConvertToBool(<currObj>5__4, fallback: false);
<setOk>5__6 = false;
try
{
<prop>5__3.SetValue(<>4__this._dissonanceComms, !<curr>5__5, null);
<setOk>5__6 = true;
}
catch (Exception ex)
{
<ex>5__8 = ex;
Plugin.LogS.LogDebug((object)("[VoiceFix] prop.SetValue failed (set): " + <ex>5__8.Message));
}
if (<setOk>5__6)
{
<>2__current = null;
<>1__state = 1;
return true;
}
goto IL_0243;
}
<disabled>5__10 = false;
try
{
<>4__this._dissonanceComms.enabled = false;
<disabled>5__10 = true;
}
catch (Exception ex)
{
<ex>5__11 = ex;
Plugin.LogS.LogDebug((object)("[VoiceFix] Dissonance disable failed: " + <ex>5__11.Message));
}
if (<disabled>5__10)
{
<>2__current = null;
<>1__state = 2;
return true;
}
goto IL_0314;
}
if ((Object)(object)<>4__this._vivoxMgr != (Object)null)
{
<disabled>5__13 = false;
try
{
<>4__this._vivoxMgr.enabled = false;
<disabled>5__13 = true;
}
catch (Exception ex)
{
<ex>5__14 = ex;
Plugin.LogS.LogDebug((object)("[VoiceFix] Vivox disable failed: " + <ex>5__14.Message));
}
if (<disabled>5__13)
{
<>2__current = null;
<>1__state = 3;
return true;
}
}
else if ((Object)(object)<>4__this._genericVoiceMgr != (Object)null)
{
<disabled>5__16 = false;
try
{
<>4__this._genericVoiceMgr.enabled = false;
<disabled>5__16 = true;
}
catch (Exception ex)
{
<ex>5__17 = ex;
Plugin.LogS.LogDebug((object)("[VoiceFix] Generic disable failed: " + <ex>5__17.Message));
}
if (<disabled>5__16)
{
<>2__current = null;
<>1__state = 4;
return true;
}
}
break;
case 1:
<>1__state = -1;
try
{
<prop>5__3.SetValue(<>4__this._dissonanceComms, <curr>5__5, null);
<nudged>5__1 = true;
}
catch (Exception ex)
{
<ex>5__9 = ex;
Plugin.LogS.LogDebug((object)("[VoiceFix] prop.SetValue failed (restore): " + <ex>5__9.Message));
}
goto IL_0243;
case 2:
<>1__state = -1;
try
{
<>4__this._dissonanceComms.enabled = true;
<nudged>5__1 = true;
}
catch (Exception ex)
{
<ex>5__12 = ex;
Plugin.LogS.LogDebug((object)("[VoiceFix] Dissonance enable failed: " + <ex>5__12.Message));
}
goto IL_0314;
case 3:
<>1__state = -1;
try
{
<>4__this._vivoxMgr.enabled = true;
<nudged>5__1 = true;
}
catch (Exception ex)
{
<ex>5__15 = ex;
Plugin.LogS.LogDebug((object)("[VoiceFix] Vivox enable failed: " + <ex>5__15.Message));
}
break;
case 4:
{
<>1__state = -1;
try
{
<>4__this._genericVoiceMgr.enabled = true;
<nudged>5__1 = true;
}
catch (Exception ex)
{
<ex>5__18 = ex;
Plugin.LogS.LogDebug((object)("[VoiceFix] Generic enable failed: " + <ex>5__18.Message));
}
break;
}
IL_0314:
<t>5__2 = null;
<prop>5__3 = null;
break;
IL_0243:
<currObj>5__4 = null;
goto IL_0314;
}
if (<>4__this._verbose)
{
Plugin.LogS.LogDebug((object)(<nudged>5__1 ? "[VoiceFix] Keep-alive nudge sent." : "[VoiceFix] Keep-alive skipped (no backend)."));
}
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 float _silenceSecondsBeforeReinit;
private float _keepAliveEverySeconds;
private float _reinitCooldownSeconds;
private bool _enableAutoReinit;
private bool _enableKeepAlive;
private bool _verbose;
private KeyCode _forceKey;
private float _lastHeardTime;
private float _lastKeepAlive;
private float _lastReinit;
private bool _inited;
private Behaviour _dissonanceComms;
private Behaviour _vivoxMgr;
private Behaviour _genericVoiceMgr;
private readonly List<AudioActivityTap> _taps = new List<AudioActivityTap>();
private const float DiscoveryInterval = 12f;
private float _lastDiscovery;
public void Init(float silence, float keepalive, float cooldown, bool autoReinit, bool keepAlive, bool verbose, KeyCode forceKey)
{
//IL_004d: 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)
_silenceSecondsBeforeReinit = Mathf.Max(5f, silence);
_keepAliveEverySeconds = Mathf.Max(5f, keepalive);
_reinitCooldownSeconds = Mathf.Max(5f, cooldown);
_enableAutoReinit = autoReinit;
_enableKeepAlive = keepAlive;
_verbose = verbose;
_forceKey = forceKey;
_lastHeardTime = Time.realtimeSinceStartup;
_lastKeepAlive = 0f;
_lastReinit = -999f;
_lastDiscovery = -999f;
((MonoBehaviour)this).StartCoroutine(LateStart());
}
private IEnumerator LateStart()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <LateStart>d__18(0)
{
<>4__this = this
};
}
private void Update()
{
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
if (!_inited)
{
return;
}
if (Input.GetKey((KeyCode)304) && Input.GetKeyDown(_forceKey))
{
Plugin.LogS.LogWarning((object)"[VoiceFix] Manual re-init requested.");
((MonoBehaviour)this).StartCoroutine(ReinitializeVoice("manual-hotkey"));
}
bool flag = false;
for (int i = 0; i < _taps.Count; i++)
{
AudioActivityTap audioActivityTap = _taps[i];
if (!((Object)(object)audioActivityTap == (Object)null) && audioActivityTap.ConsumeActivity())
{
flag = true;
break;
}
}
if (flag)
{
HeardActivity();
}
if (_enableKeepAlive && Time.realtimeSinceStartup - _lastKeepAlive >= _keepAliveEverySeconds)
{
_lastKeepAlive = Time.realtimeSinceStartup;
((MonoBehaviour)this).StartCoroutine(SendKeepAlive());
}
if (_enableAutoReinit && Time.realtimeSinceStartup - _lastHeardTime >= _silenceSecondsBeforeReinit && Time.realtimeSinceStartup - _lastReinit >= _reinitCooldownSeconds)
{
Plugin.LogS.LogWarning((object)"[VoiceFix] No inbound voice detected for threshold; attempting re-init.");
((MonoBehaviour)this).StartCoroutine(ReinitializeVoice("silence-watchdog"));
}
if (Time.realtimeSinceStartup - _lastDiscovery >= 12f)
{
_lastDiscovery = Time.realtimeSinceStartup;
DiscoverBackend();
}
}
private void DiscoverBackend()
{
try
{
_dissonanceComms = null;
_vivoxMgr = null;
_genericVoiceMgr = null;
_dissonanceComms = FindBehaviourByTypeName("DissonanceComms");
if ((Object)(object)_dissonanceComms != (Object)null)
{
Plugin.LogS.LogInfo((object)"[VoiceFix] Found DissonanceComms.");
}
_vivoxMgr = FindBehaviourByTypeName("VivoxVoiceManager");
if ((Object)(object)_vivoxMgr != (Object)null)
{
Plugin.LogS.LogInfo((object)"[VoiceFix] Found VivoxVoiceManager.");
}
if ((Object)(object)_dissonanceComms == (Object)null && (Object)(object)_vivoxMgr == (Object)null)
{
Behaviour genericVoiceMgr = ((IEnumerable<Behaviour>)Object.FindObjectsOfType<Behaviour>()).FirstOrDefault((Func<Behaviour, bool>)((Behaviour c) => (Object)(object)c != (Object)null && ((object)c).GetType().Name.IndexOf("Voice", StringComparison.OrdinalIgnoreCase) >= 0 && ((object)c).GetType().Name.IndexOf("Manager", StringComparison.OrdinalIgnoreCase) >= 0));
_genericVoiceMgr = genericVoiceMgr;
if ((Object)(object)_genericVoiceMgr != (Object)null)
{
Plugin.LogS.LogInfo((object)("[VoiceFix] Found generic voice manager: " + ((object)_genericVoiceMgr).GetType().FullName));
}
else
{
Plugin.LogS.LogWarning((object)"[VoiceFix] No obvious voice backend found; watchdog will still monitor audio sources.");
}
}
}
catch (Exception arg)
{
Plugin.LogS.LogError((object)$"[VoiceFix] Discovery error: {arg}");
}
}
private Behaviour FindBehaviourByTypeName(string typeName)
{
Behaviour[] array = Object.FindObjectsOfType<Behaviour>();
foreach (Behaviour val in array)
{
if (!((Object)(object)val == (Object)null))
{
Type type = ((object)val).GetType();
if (type.Name.Equals(typeName, StringComparison.OrdinalIgnoreCase) || (type.FullName != null && type.FullName.EndsWith("." + typeName, StringComparison.OrdinalIgnoreCase)))
{
return val;
}
}
}
return null;
}
private void AttachAudioTaps()
{
List<GameObject> list = new List<GameObject>();
try
{
GameObject[] array = GameObject.FindGameObjectsWithTag("Player");
if (array != null && array.Length != 0)
{
list.AddRange(array);
}
}
catch
{
}
AudioSource[] array2 = Object.FindObjectsOfType<AudioSource>();
foreach (AudioSource val in array2)
{
if (!((Object)(object)val == (Object)null) && ((Behaviour)val).enabled && ((Component)val).gameObject.activeInHierarchy)
{
string text = ((Object)((Component)val).gameObject).name.ToLowerInvariant();
if (text.Contains("voice") || text.Contains("dissonance") || text.Contains("vivox") || text.Contains("radio") || text.Contains("prox"))
{
list.Add(((Component)val).gameObject);
}
else if ((Object)(object)val.clip == (Object)null)
{
list.Add(((Component)val).gameObject);
}
}
}
list = list.Distinct().ToList();
int num = 0;
foreach (GameObject item in list)
{
if (!((Object)(object)item == (Object)null))
{
AudioActivityTap audioActivityTap = item.GetComponent<AudioActivityTap>();
if ((Object)(object)audioActivityTap == (Object)null)
{
audioActivityTap = item.AddComponent<AudioActivityTap>();
}
if (!_taps.Contains(audioActivityTap))
{
_taps.Add(audioActivityTap);
}
num++;
}
}
Plugin.LogS.LogInfo((object)$"[VoiceFix] Attached audio activity taps to {num} object(s).");
}
private void HeardActivity()
{
_lastHeardTime = Time.realtimeSinceStartup;
if (_verbose)
{
Plugin.LogS.LogDebug((object)$"[VoiceFix] Heard inbound audio @ {_lastHeardTime:F1}s");
}
}
private IEnumerator SendKeepAlive()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <SendKeepAlive>d__24(0)
{
<>4__this = this
};
}
private IEnumerator ReinitializeVoice(string reason)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <ReinitializeVoice>d__25(0)
{
<>4__this = this,
reason = reason
};
}
private PropertyInfo FindFirstProperty(Type t, string[] candidates)
{
foreach (string name in candidates)
{
PropertyInfo property = t.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if ((object)property != null)
{
return property;
}
}
return null;
}
private bool SafeConvertToBool(object o, bool fallback)
{
if (o == null)
{
return fallback;
}
try
{
return Convert.ToBoolean(o);
}
catch
{
return fallback;
}
}
}
internal class AudioActivityTap : MonoBehaviour
{
private const float Threshold = 0.0005f;
private volatile int _activityFlag = 0;
private void OnAudioFilterRead(float[] data, int channels)
{
if (data != null && data.Length != 0)
{
int num = Math.Max(1, channels);
double num2 = 0.0;
for (int i = 0; i < data.Length; i += num)
{
num2 += (double)Math.Abs(data[i]);
}
double num3 = Math.Max(1, data.Length / num);
double num4 = num2 / num3;
if (num4 > 0.0005000000237487257)
{
Interlocked.Exchange(ref _activityFlag, 1);
}
}
}
public bool ConsumeActivity()
{
int num = Interlocked.Exchange(ref _activityFlag, 0);
return num != 0;
}
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "VoiceFixMod";
public const string PLUGIN_NAME = "My first plugin";
public const string PLUGIN_VERSION = "1.0.0";
}
}