using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Realtime;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.Networking;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("Omniscye")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("JoinNotifier")]
[assembly: AssemblyTitle("JoinNotifier")]
[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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[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 JoinNotifier
{
[BepInPlugin("Omniscye.JoinNotifier", "JoinNotifier", "1.1.1")]
public class JoinNotifier : BaseUnityPlugin
{
[CompilerGenerated]
private sealed class <LoadClipFromConfig>d__26 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
public JoinNotifier <>4__this;
private string <resolved>5__1;
private string <ext>5__2;
private AudioType <at>5__3;
private string <uri>5__4;
private string <path>5__5;
private string <dllDir>5__6;
private Exception <ex>5__7;
private UnityWebRequest <req>5__8;
private bool <ok>5__9;
private AudioClip <clip>5__10;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <LoadClipFromConfig>d__26(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
int num = <>1__state;
if (num == -3 || num == 1)
{
try
{
}
finally
{
<>m__Finally1();
}
}
<resolved>5__1 = null;
<ext>5__2 = null;
<uri>5__4 = null;
<path>5__5 = null;
<dllDir>5__6 = null;
<ex>5__7 = null;
<req>5__8 = null;
<clip>5__10 = null;
<>1__state = -2;
}
private bool MoveNext()
{
//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
//IL_01dc: Invalid comparison between Unknown and I4
//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
//IL_0236: Unknown result type (might be due to invalid IL or missing references)
//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
bool result;
try
{
switch (<>1__state)
{
default:
result = false;
break;
case 0:
{
<>1__state = -1;
<resolved>5__1 = null;
try
{
<path>5__5 = <>4__this._audioFilePath.Value?.Trim() ?? string.Empty;
if (!string.IsNullOrEmpty(<path>5__5))
{
<dllDir>5__6 = Path.GetDirectoryName(((BaseUnityPlugin)<>4__this).Info.Location);
<resolved>5__1 = (Path.IsPathRooted(<path>5__5) ? <path>5__5 : Path.Combine(<dllDir>5__6 ?? Paths.PluginPath, <path>5__5));
<dllDir>5__6 = null;
}
<path>5__5 = null;
}
catch (Exception ex)
{
<ex>5__7 = ex;
Logger.LogWarning((object)("Path resolution failed: " + <ex>5__7.Message));
<resolved>5__1 = null;
}
if (string.IsNullOrEmpty(<resolved>5__1) || !File.Exists(<resolved>5__1))
{
Logger.LogWarning((object)("Join alert file not found: '" + (<resolved>5__1 ?? "<null>") + "'. Using fallback beep."));
<>4__this.BuildFallbackBeep();
result = false;
break;
}
<ext>5__2 = Path.GetExtension(<resolved>5__1).ToLowerInvariant();
if (1 == 0)
{
}
AudioType val = (AudioType)(<ext>5__2 switch
{
".wav" => 20,
".ogg" => 14,
".mp3" => 13,
_ => 0,
});
if (1 == 0)
{
}
<at>5__3 = val;
if ((int)<at>5__3 == 0)
{
Logger.LogWarning((object)("Unsupported extension '" + <ext>5__2 + "'. Using fallback beep."));
<>4__this.BuildFallbackBeep();
result = false;
break;
}
<uri>5__4 = new Uri(<resolved>5__1).AbsoluteUri;
<req>5__8 = UnityWebRequestMultimedia.GetAudioClip(<uri>5__4, <at>5__3);
<>1__state = -3;
<>2__current = <req>5__8.SendWebRequest();
<>1__state = 1;
result = true;
break;
}
case 1:
<>1__state = -3;
<ok>5__9 = !<req>5__8.isNetworkError && !<req>5__8.isHttpError;
if (!<ok>5__9)
{
Logger.LogWarning((object)("Failed to load join alert clip: " + <req>5__8.error + ". Using fallback beep."));
<>4__this.BuildFallbackBeep();
result = false;
}
else
{
<clip>5__10 = DownloadHandlerAudioClip.GetContent(<req>5__8);
if (!((Object)(object)<clip>5__10 == (Object)null))
{
<>4__this._clip = <clip>5__10;
Logger.LogInfo((object)$"Loaded join alert clip: {Path.GetFileName(<resolved>5__1)} ({<>4__this._clip.frequency}Hz, {<>4__this._clip.channels}ch, {<>4__this._clip.samples} samples)");
<clip>5__10 = null;
<>m__Finally1();
<req>5__8 = null;
result = false;
break;
}
Logger.LogWarning((object)"AudioClip load returned null. Using fallback beep.");
<>4__this.BuildFallbackBeep();
result = false;
}
<>m__Finally1();
break;
}
}
catch
{
//try-fault
((IDisposable)this).Dispose();
throw;
}
return result;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
private void <>m__Finally1()
{
<>1__state = -1;
if (<req>5__8 != null)
{
((IDisposable)<req>5__8).Dispose();
}
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
private ConfigEntry<bool> _enabled = null;
private ConfigEntry<string> _audioFilePath = null;
private ConfigEntry<float> _volume = null;
private ConfigEntry<float> _pitch = null;
private ConfigEntry<float> _throttleSeconds = null;
private const string HostName = "JoinNotifier.AudioHost";
private AudioSource _source = null;
private AudioClip? _clip;
private float _lastPlay;
internal static JoinNotifier Instance { get; private set; }
internal static ManualLogSource Logger => Instance._logger;
private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger;
internal Harmony? Harmony { get; set; }
private void Awake()
{
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_0087: Expected O, but got Unknown
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
//IL_00c5: Expected O, but got Unknown
//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
//IL_0103: Expected O, but got Unknown
Instance = this;
_enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master toggle for the join sound.");
_audioFilePath = ((BaseUnityPlugin)this).Config.Bind<string>("General", "AudioFile", "JoinAlert.ogg", "Path to the audio file (.wav, .ogg, .mp3). Relative paths resolve next to this plugin DLL.");
_volume = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Volume", 0.85f, new ConfigDescription("Playback volume (0..1).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
_pitch = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Pitch", 1f, new ConfigDescription("Playback pitch multiplier.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 3f), Array.Empty<object>()));
_throttleSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ThrottleSeconds", 0.35f, new ConfigDescription("Minimum seconds between join sounds to avoid spam if multiple players connect at once.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>()));
EnsureAudioHost();
TryHookMixer();
((MonoBehaviour)this).StartCoroutine(LoadClipFromConfig());
_audioFilePath.SettingChanged += delegate
{
((MonoBehaviour)this).StartCoroutine(LoadClipFromConfig());
};
Patch();
Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} has loaded!");
}
private void TryHookMixer()
{
try
{
Type type = AccessTools.TypeByName("AudioManager");
object obj = (type?.GetField("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))?.GetValue(null);
object? obj2 = (type?.GetProperty("SoundMasterGroup", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))?.GetValue(obj, null);
AudioMixerGroup val = (AudioMixerGroup)((obj2 is AudioMixerGroup) ? obj2 : null);
if ((Object)(object)val != (Object)null && (Object)(object)_source != (Object)null)
{
_source.outputAudioMixerGroup = val;
}
}
catch
{
}
}
private void EnsureAudioHost()
{
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Expected O, but got Unknown
if ((Object)(object)_source != (Object)null)
{
return;
}
GameObject val = GameObject.Find("JoinNotifier.AudioHost");
if ((Object)(object)val != (Object)null)
{
_source = val.GetComponent<AudioSource>();
if ((Object)(object)_source == (Object)null)
{
_source = val.AddComponent<AudioSource>();
}
}
else
{
GameObject val2 = new GameObject("JoinNotifier.AudioHost");
val2.transform.SetParent((Transform)null);
Object.DontDestroyOnLoad((Object)(object)val2);
_source = val2.AddComponent<AudioSource>();
}
_source.spatialBlend = 0f;
_source.playOnAwake = false;
_source.loop = false;
((Object)_source).hideFlags = (HideFlags)61;
}
internal void Patch()
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Expected O, but got Unknown
//IL_0026: Expected O, but got Unknown
if (Harmony == null)
{
Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID);
Harmony val2 = val;
Harmony = val;
}
Harmony.PatchAll();
}
internal void Unpatch()
{
Harmony? harmony = Harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
}
[IteratorStateMachine(typeof(<LoadClipFromConfig>d__26))]
private IEnumerator LoadClipFromConfig()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <LoadClipFromConfig>d__26(0)
{
<>4__this = this
};
}
private void BuildFallbackBeep()
{
int num = Mathf.CeilToInt(12000f);
float[] array = new float[num];
for (int i = 0; i < num; i++)
{
array[i] = Mathf.Sin(MathF.PI * 1760f * (float)i / 48000f) * 0.5f;
}
_clip = AudioClip.Create("JoinNotifier.Beep", num, 1, 48000, false);
_clip.SetData(array, 0);
}
internal void PlayJoinSound()
{
if (!_enabled.Value)
{
return;
}
if ((Object)(object)_source == (Object)null)
{
Logger.LogWarning((object)"AudioSource was null at playback time. Recreating host.");
EnsureAudioHost();
TryHookMixer();
}
if ((Object)(object)_clip == (Object)null)
{
Logger.LogDebug((object)"No clip loaded yet; skipping join sound.");
}
else if ((Object)(object)_source == (Object)null)
{
Logger.LogError((object)"Failed to create AudioSource; join sound aborted.");
}
else if (!(Time.realtimeSinceStartup - _lastPlay < _throttleSeconds.Value))
{
try
{
_source.pitch = Mathf.Clamp(_pitch.Value, 0.1f, 3f);
_source.PlayOneShot(_clip, Mathf.Clamp01(_volume.Value));
_lastPlay = Time.realtimeSinceStartup;
}
catch (Exception arg)
{
Logger.LogError((object)$"PlayJoinSound failed: {arg}");
}
}
}
private void Update()
{
}
}
[HarmonyPatch]
internal static class JoinNotifier_JoinPatch
{
[CompilerGenerated]
private sealed class <TargetMethods>d__0 : IEnumerable<MethodBase>, IEnumerable, IEnumerator<MethodBase>, IEnumerator, IDisposable
{
private int <>1__state;
private MethodBase <>2__current;
private int <>l__initialThreadId;
private Type <playerType>5__1;
private Assembly[] <>s__2;
private int <>s__3;
private Assembly <asm>5__4;
private Type[] <types>5__5;
private ReflectionTypeLoadException <rtl>5__6;
private Type[] <>s__7;
private int <>s__8;
private Type <t>5__9;
private MethodInfo <m>5__10;
private MethodInfo <mi>5__11;
private bool <hasBody>5__12;
private MethodImplAttributes <impl>5__13;
MethodBase IEnumerator<MethodBase>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <TargetMethods>d__0(int <>1__state)
{
this.<>1__state = <>1__state;
<>l__initialThreadId = Environment.CurrentManagedThreadId;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<playerType>5__1 = null;
<>s__2 = null;
<asm>5__4 = null;
<types>5__5 = null;
<rtl>5__6 = null;
<>s__7 = null;
<t>5__9 = null;
<m>5__10 = null;
<mi>5__11 = null;
<>1__state = -2;
}
private bool MoveNext()
{
int num = <>1__state;
if (num != 0)
{
if (num != 1)
{
return false;
}
<>1__state = -1;
<m>5__10 = null;
<mi>5__11 = null;
<t>5__9 = null;
goto IL_0226;
}
<>1__state = -1;
<playerType>5__1 = typeof(Player);
<>s__2 = AppDomain.CurrentDomain.GetAssemblies();
<>s__3 = 0;
goto IL_026b;
IL_026b:
if (<>s__3 < <>s__2.Length)
{
<asm>5__4 = <>s__2[<>s__3];
try
{
<types>5__5 = <asm>5__4.GetTypes();
}
catch (ReflectionTypeLoadException ex)
{
<rtl>5__6 = ex;
<types>5__5 = <rtl>5__6.Types.Where((Type t) => t != null).Cast<Type>().ToArray();
}
catch
{
goto IL_025d;
}
<>s__7 = <types>5__5;
<>s__8 = 0;
goto IL_0234;
}
<>s__2 = null;
return false;
IL_0226:
<>s__8++;
goto IL_0234;
IL_025d:
<>s__3++;
goto IL_026b;
IL_0234:
if (<>s__8 < <>s__7.Length)
{
<t>5__9 = <>s__7[<>s__8];
if (!(<t>5__9 == null) && !<t>5__9.IsInterface)
{
<m>5__10 = <t>5__9.GetMethod("OnPlayerEnteredRoom", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { <playerType>5__1 }, null);
if ((object)<m>5__10 != null)
{
<mi>5__11 = <m>5__10;
if (true && !<mi>5__11.IsAbstract && !<mi>5__11.ContainsGenericParameters)
{
<hasBody>5__12 = false;
try
{
<hasBody>5__12 = <mi>5__11.GetMethodBody() != null;
}
catch
{
<hasBody>5__12 = false;
}
if (<hasBody>5__12)
{
<impl>5__13 = <mi>5__11.MethodImplementationFlags;
if ((<impl>5__13 & (MethodImplAttributes)4101) == 0)
{
<>2__current = <mi>5__11;
<>1__state = 1;
return true;
}
}
}
}
}
goto IL_0226;
}
<>s__7 = null;
<types>5__5 = null;
<asm>5__4 = null;
goto IL_025d;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
[DebuggerHidden]
IEnumerator<MethodBase> IEnumerable<MethodBase>.GetEnumerator()
{
if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
{
<>1__state = 0;
return this;
}
return new <TargetMethods>d__0(0);
}
[DebuggerHidden]
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable<MethodBase>)this).GetEnumerator();
}
}
[IteratorStateMachine(typeof(<TargetMethods>d__0))]
private static IEnumerable<MethodBase> TargetMethods()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <TargetMethods>d__0(-2);
}
private static void Postfix([HarmonyArgument(0)] Player player)
{
JoinNotifier.Instance?.PlayJoinSound();
}
}
}