using 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 HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Voice;
using Photon.Voice.Unity;
using UnityEngine;
[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("MicGain")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("MicGain")]
[assembly: AssemblyTitle("MicGain")]
[assembly: AssemblyVersion("1.0.0.0")]
[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 MicGain
{
public class ModConfig
{
public readonly ConfigEntry<float> Gain;
public ModConfig(ConfigFile cfg)
{
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Expected O, but got Unknown
cfg.SaveOnConfigSet = false;
Gain = cfg.Bind<float>("General", "Mic Gain", 1f, new ConfigDescription("Microphone gain multiplier. 1.0 = normal, 0.5 = half volume, 0.0 = muted.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
ClearOrphanedEntries(cfg);
cfg.Save();
cfg.SaveOnConfigSet = true;
}
private static void ClearOrphanedEntries(ConfigFile cfg)
{
((Dictionary<ConfigDefinition, string>)AccessTools.Property(typeof(ConfigFile), "OrphanedEntries").GetValue(cfg)).Clear();
}
}
public class GainProcessorFloat : IProcessor<float>, IDisposable
{
public Func<float> GetGain;
public float[] Process(float[] buf)
{
float num = GetGain();
if (Math.Abs(num - 1f) < 0.001f)
{
return buf;
}
for (int i = 0; i < buf.Length; i++)
{
buf[i] *= num;
}
return buf;
}
public void Dispose()
{
}
}
public class GainProcessorShort : IProcessor<short>, IDisposable
{
public Func<float> GetGain;
public short[] Process(short[] buf)
{
float num = GetGain();
if (Math.Abs(num - 1f) < 0.001f)
{
return buf;
}
for (int i = 0; i < buf.Length; i++)
{
buf[i] = (short)Math.Max(-32768f, Math.Min(32767f, (float)buf[i] * num));
}
return buf;
}
public void Dispose()
{
}
}
[HarmonyPatch(typeof(CharacterVoiceHandler), "Start")]
public static class PatchVoiceHandlerStart
{
[CompilerGenerated]
private sealed class <WaitAndInjectProcessor>d__1 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
public Recorder recorder;
private float <timeout>5__2;
private float <elapsed>5__3;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <WaitAndInjectProcessor>d__1(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: Expected O, but got Unknown
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<timeout>5__2 = 30f;
<elapsed>5__3 = 0f;
break;
case 1:
{
<>1__state = -1;
<elapsed>5__3 += 0.5f;
object value = Traverse.Create((object)recorder).Field("voice").GetValue();
if (value == null)
{
break;
}
Type type = value.GetType();
if (type.Name.Contains("Dummy"))
{
break;
}
MethodInfo methodInfo = null;
Type type2 = type;
while (type2 != null && methodInfo == null)
{
methodInfo = type2.GetMethod("AddPostProcessor", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public);
type2 = type2.BaseType;
}
if (methodInfo == null)
{
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogWarning((object)"AddPostProcessor not found on LocalVoice.");
}
return false;
}
bool flag = type.FullName.Contains("Short");
try
{
if (flag)
{
GainProcessorShort value2 = new GainProcessorShort
{
GetGain = () => Plugin.BoundConfig.Gain.Value
};
Array array = Array.CreateInstance(typeof(IProcessor<short>), 1);
array.SetValue(value2, 0);
methodInfo.Invoke(value, new object[1] { array });
}
else
{
GainProcessorFloat value3 = new GainProcessorFloat
{
GetGain = () => Plugin.BoundConfig.Gain.Value
};
Array array2 = Array.CreateInstance(typeof(IProcessor<float>), 1);
array2.SetValue(value3, 0);
methodInfo.Invoke(value, new object[1] { array2 });
}
ManualLogSource log2 = Plugin.Log;
if (log2 != null)
{
log2.LogInfo((object)("Gain processor injected successfully! (type: " + (flag ? "short" : "float") + ")"));
}
}
catch (Exception arg)
{
ManualLogSource log3 = Plugin.Log;
if (log3 != null)
{
log3.LogError((object)$"Failed to invoke AddPostProcessor: {arg}");
}
}
return false;
}
}
if (<elapsed>5__3 < <timeout>5__2)
{
<>2__current = (object)new WaitForSeconds(0.5f);
<>1__state = 1;
return true;
}
ManualLogSource log4 = Plugin.Log;
if (log4 != null)
{
log4.LogWarning((object)"Timed out waiting for real LocalVoice.");
}
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 static void Postfix(CharacterVoiceHandler __instance)
{
try
{
Character componentInParent = ((Component)__instance).GetComponentInParent<Character>();
if (!((Object)(object)componentInParent == (Object)null) && componentInParent.IsLocal)
{
Recorder component = ((Component)__instance).GetComponent<Recorder>();
if (!((Object)(object)component == (Object)null))
{
((MonoBehaviour)Plugin.Instance).StartCoroutine(WaitAndInjectProcessor(component));
}
}
}
catch (Exception arg)
{
ManualLogSource log = Plugin.Log;
if (log != null)
{
log.LogError((object)$"MicGain patch error: {arg}");
}
}
}
[IteratorStateMachine(typeof(<WaitAndInjectProcessor>d__1))]
private static IEnumerator WaitAndInjectProcessor(Recorder recorder)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <WaitAndInjectProcessor>d__1(0)
{
recorder = recorder
};
}
}
[BepInPlugin("MicGain", "MicGain", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
public const string Id = "MicGain";
private readonly Harmony harmony = new Harmony("MicGain");
internal static ManualLogSource Log { get; private set; }
internal static Plugin Instance { get; private set; }
internal static ModConfig BoundConfig { get; private set; }
private void Awake()
{
if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this)
{
Object.Destroy((Object)(object)this);
return;
}
Instance = this;
Log = ((BaseUnityPlugin)this).Logger;
BoundConfig = new ModConfig(((BaseUnityPlugin)this).Config);
harmony.PatchAll();
Log.LogInfo((object)"MicGain loaded.");
}
}
}