using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
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 Gloomwood.Saving;
using Gloomwood.Sound;
using Gloomwood.UI;
using Gloomwood.World;
using HarmonyLib;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Networking;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: AssemblyCompany("PhonographSoundMod")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("PhonographSoundMod")]
[assembly: AssemblyTitle("PhonographSoundMod")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace PhonographSoundMod;
public static class AudioLoader
{
[CompilerGenerated]
private sealed class <LoadClipCoroutine>d__2 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
public string filePath;
public ManualLogSource log;
public Action<AudioClip> onLoaded;
private UnityWebRequest <request>5__2;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <LoadClipCoroutine>d__2(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();
}
}
<request>5__2 = null;
<>1__state = -2;
}
private bool MoveNext()
{
//IL_0060: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_00ce: 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;
if (!File.Exists(filePath))
{
log.LogError((object)("[AudioLoader] File not found: " + filePath));
onLoaded(null);
result = false;
break;
}
AudioType audioType = GetAudioType(filePath);
if ((int)audioType == 0)
{
log.LogError((object)("[AudioLoader] Unsupported file type: " + Path.GetExtension(filePath)));
onLoaded(null);
result = false;
break;
}
string text = "file:///" + filePath.Replace('\\', '/');
log.LogInfo((object)("[AudioLoader] Loading: " + text));
<request>5__2 = UnityWebRequestMultimedia.GetAudioClip(text, audioType);
<>1__state = -3;
<>2__current = <request>5__2.SendWebRequest();
<>1__state = 1;
result = true;
break;
}
case 1:
<>1__state = -3;
if (<request>5__2.isNetworkError || <request>5__2.isHttpError)
{
log.LogError((object)("[AudioLoader] Failed to load audio: " + <request>5__2.error));
onLoaded(null);
result = false;
}
else
{
AudioClip content = DownloadHandlerAudioClip.GetContent(<request>5__2);
if (!((Object)(object)content == (Object)null))
{
((Object)content).name = Path.GetFileNameWithoutExtension(filePath);
log.LogInfo((object)$"[AudioLoader] Loaded clip '{((Object)content).name}' ({content.length:F2}s, {content.channels}ch, {content.frequency}Hz)");
onLoaded(content);
<>m__Finally1();
<request>5__2 = null;
result = false;
break;
}
log.LogError((object)"[AudioLoader] DownloadHandlerAudioClip returned null.");
onLoaded(null);
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 (<request>5__2 != null)
{
((IDisposable)<request>5__2).Dispose();
}
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
private static readonly string[] SupportedExtensions = new string[3] { ".wav", ".ogg", ".mp3" };
public static string FindAudioFile(string folder)
{
string[] supportedExtensions = SupportedExtensions;
foreach (string text in supportedExtensions)
{
string[] files = Directory.GetFiles(folder, "*" + text);
int num = 0;
if (num < files.Length)
{
return files[num];
}
}
return null;
}
[IteratorStateMachine(typeof(<LoadClipCoroutine>d__2))]
public static IEnumerator LoadClipCoroutine(string filePath, Action<AudioClip> onLoaded, ManualLogSource log)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <LoadClipCoroutine>d__2(0)
{
filePath = filePath,
onLoaded = onLoaded,
log = log
};
}
private static AudioType GetAudioType(string path)
{
return (AudioType)(Path.GetExtension(path).ToLowerInvariant() switch
{
".wav" => 20,
".ogg" => 14,
".mp3" => 13,
_ => 0,
});
}
}
[BepInPlugin("com.wanderan51.gloomwood.phonographsound", "PhonographSoundMod", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
internal static float SaveVolume = 1f;
internal static float AmbientVolume = 1f;
private static readonly Harmony _harmony = new Harmony("com.wanderan51.gloomwood.phonographsound");
internal static AudioClip SaveClip { get; private set; }
internal static AudioClip AmbientClip { get; private set; }
internal static ManualLogSource Log { get; private set; }
private void Awake()
{
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Expected O, but got Unknown
//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
//IL_00af: Expected O, but got Unknown
//IL_024f: Unknown result type (might be due to invalid IL or missing references)
//IL_025d: Expected O, but got Unknown
//IL_032c: Unknown result type (might be due to invalid IL or missing references)
//IL_033a: Expected O, but got Unknown
//IL_03f0: Unknown result type (might be due to invalid IL or missing references)
//IL_03fd: Expected O, but got Unknown
//IL_0493: Unknown result type (might be due to invalid IL or missing references)
//IL_04a0: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
ConfigEntry<float> saveVol = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "SaveVolumeMultiplier", 1f, new ConfigDescription("Volume for the save sound (0.0-2.0).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
SaveVolume = saveVol.Value;
saveVol.SettingChanged += delegate
{
SaveVolume = saveVol.Value;
};
ConfigEntry<float> ambVol = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "AmbientVolumeMultiplier", 1f, new ConfigDescription("Volume for the ambient loop (0.0-2.0).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
AmbientVolume = ambVol.Value;
ambVol.SettingChanged += delegate
{
AmbientVolume = ambVol.Value;
};
string path = Path.Combine(Paths.PluginPath, "PhonographSoundMod", "Sounds");
string text = Path.Combine(path, "Save");
string text2 = Path.Combine(path, "Ambient");
Directory.CreateDirectory(text);
Directory.CreateDirectory(text2);
string text3 = AudioLoader.FindAudioFile(text);
if (text3 != null)
{
((MonoBehaviour)this).StartCoroutine(AudioLoader.LoadClipCoroutine(text3, delegate(AudioClip c)
{
SaveClip = c;
if ((Object)(object)c != (Object)null)
{
Log.LogInfo((object)("[PhonographSoundMod] Save clip ready: " + ((Object)c).name));
}
}, Log));
}
else
{
Log.LogWarning((object)("[PhonographSoundMod] No save sound found in: " + text));
}
string text4 = AudioLoader.FindAudioFile(text2);
if (text4 != null)
{
((MonoBehaviour)this).StartCoroutine(AudioLoader.LoadClipCoroutine(text4, delegate(AudioClip c)
{
AmbientClip = c;
if ((Object)(object)c != (Object)null)
{
Log.LogInfo((object)("[PhonographSoundMod] Ambient clip ready: " + ((Object)c).name));
}
}, Log));
}
else
{
Log.LogWarning((object)("[PhonographSoundMod] No ambient sound found in: " + text2));
}
MethodInfo methodInfo = null;
MethodInfo[] methods = typeof(Phonograph).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (MethodInfo methodInfo2 in methods)
{
if (!(methodInfo2.Name != "SaveGame"))
{
ParameterInfo[] parameters = methodInfo2.GetParameters();
if (parameters.Length == 1 && parameters[0].ParameterType == typeof(int))
{
methodInfo = methodInfo2;
break;
}
}
}
if (methodInfo != null)
{
_harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(SaveGamePatch), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
Log.LogInfo((object)"[PhonographSoundMod] Patched Phonograph.SaveGame(int).");
}
else
{
Log.LogError((object)"[PhonographSoundMod] Could not find Phonograph.SaveGame(int)!");
}
MethodInfo methodInfo3 = null;
methods = typeof(SaveGameMenu).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (MethodInfo methodInfo4 in methods)
{
if (!(methodInfo4.Name != "TrySaveGame"))
{
ParameterInfo[] parameters2 = methodInfo4.GetParameters();
if (parameters2.Length == 2 && parameters2[0].ParameterType == typeof(int) && parameters2[1].ParameterType == typeof(bool))
{
methodInfo3 = methodInfo4;
break;
}
}
}
if (methodInfo3 != null)
{
_harmony.Patch((MethodBase)methodInfo3, new HarmonyMethod(typeof(TrySaveGamePatch), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
Log.LogInfo((object)"[PhonographSoundMod] Patched SaveGameMenu.TrySaveGame(int, bool).");
}
else
{
Log.LogError((object)"[PhonographSoundMod] Could not find SaveGameMenu.TrySaveGame(int, bool)!");
}
MethodInfo methodInfo5 = null;
methods = typeof(SaveLoadManager).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (MethodInfo methodInfo6 in methods)
{
if (!(methodInfo6.Name != "TryQuickSave"))
{
ParameterInfo[] parameters3 = methodInfo6.GetParameters();
if (parameters3.Length == 1 && parameters3[0].ParameterType == typeof(bool))
{
methodInfo5 = methodInfo6;
break;
}
}
}
if (methodInfo5 != null)
{
_harmony.Patch((MethodBase)methodInfo5, (HarmonyMethod)null, new HarmonyMethod(typeof(QuickSavePatch), "Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
Log.LogInfo((object)"[PhonographSoundMod] Patched SaveLoadManager.TryQuickSave.");
}
else
{
Log.LogError((object)"[PhonographSoundMod] Could not find SaveLoadManager.TryQuickSave!");
}
MethodInfo methodInfo7 = null;
methods = typeof(Phonograph).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (MethodInfo methodInfo8 in methods)
{
if (methodInfo8.Name == "Start" && methodInfo8.GetParameters().Length == 0)
{
methodInfo7 = methodInfo8;
break;
}
}
if (methodInfo7 != null)
{
_harmony.Patch((MethodBase)methodInfo7, (HarmonyMethod)null, new HarmonyMethod(typeof(PhonographStartPatch), "Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
Log.LogInfo((object)"[PhonographSoundMod] Patched Phonograph.Start().");
}
else
{
Log.LogError((object)"[PhonographSoundMod] Could not find Phonograph.Start()!");
}
}
}
internal static class SaveGamePatch
{
private static readonly FieldInfo UseSourceField = typeof(Phonograph).GetField("useSource", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
private static readonly FieldInfo AudioSourceField = typeof(SoundSource).GetField("audioSource", BindingFlags.Instance | BindingFlags.NonPublic);
private static readonly FieldInfo OnActivateField = typeof(Phonograph).GetField("OnActivate", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
public static void Prefix(Phonograph __instance, int saveSlot)
{
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Expected O, but got Unknown
//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
Plugin.Log.LogInfo((object)"[PhonographSoundMod] Phonograph.SaveGame fired!");
OnActivateField?.SetValue(__instance, (object?)new UnityEvent());
object? obj = UseSourceField?.GetValue(__instance);
SoundSource val = (SoundSource)((obj is SoundSource) ? obj : null);
AudioSource val2 = (AudioSource)(((Object)(object)val != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
UseSourceField?.SetValue(__instance, null);
if ((Object)(object)Plugin.SaveClip == (Object)null)
{
Plugin.Log.LogWarning((object)"[PhonographSoundMod] Save clip not ready.");
}
else if ((Object)(object)val2 != (Object)null)
{
val2.Stop();
val2.clip = Plugin.SaveClip;
val2.volume = Plugin.SaveVolume;
val2.loop = false;
val2.Play();
Plugin.Log.LogInfo((object)("[PhonographSoundMod] Playing save: " + ((Object)Plugin.SaveClip).name));
}
else
{
AudioSource.PlayClipAtPoint(Plugin.SaveClip, ((Component)__instance).transform.position, Plugin.SaveVolume);
Plugin.Log.LogInfo((object)"[PhonographSoundMod] PlayClipAtPoint fallback.");
}
}
}
internal static class TrySaveGamePatch
{
private static readonly FieldInfo SaveSlotSoundField = typeof(SaveGameMenu).GetField("saveSlotSound", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
public static void Prefix(SaveGameMenu __instance, int saveSlot, bool overwriteSave)
{
Plugin.Log.LogInfo((object)"[PhonographSoundMod] TrySaveGame fired – silencing saveSlotSound.");
SaveSlotSoundField?.SetValue(__instance, null);
}
}
internal static class QuickSavePatch
{
public static void Postfix(bool __result)
{
//IL_0030: 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_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
if (__result && !((Object)(object)Plugin.SaveClip == (Object)null))
{
Vector3 val = (((Object)(object)Camera.main != (Object)null) ? ((Component)Camera.main).transform.position : Vector3.zero);
AudioSource.PlayClipAtPoint(Plugin.SaveClip, val, Plugin.SaveVolume);
Plugin.Log.LogInfo((object)("[PhonographSoundMod] QuickSave – playing: " + ((Object)Plugin.SaveClip).name));
}
}
}
internal static class PhonographStartPatch
{
private static readonly FieldInfo AudioSourceField = typeof(SoundSource).GetField("audioSource", BindingFlags.Instance | BindingFlags.NonPublic);
private static readonly FieldInfo LoopSoundSourceField = typeof(Phonograph).GetField("loopSoundSource", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
private static readonly PropertyInfo MinRangeProp = typeof(SoundSource).GetProperty("MinRange", BindingFlags.Instance | BindingFlags.Public);
private static readonly PropertyInfo MaxRangeProp = typeof(SoundSource).GetProperty("MaxRange", BindingFlags.Instance | BindingFlags.Public);
private static readonly PropertyInfo SpatialBlendProp = typeof(SoundSource).GetProperty("SpatialBlend", BindingFlags.Instance | BindingFlags.Public);
public static void Postfix(Phonograph __instance)
{
Plugin.Log.LogInfo((object)("[PhonographSoundMod] Phonograph.Start() on: " + ((Object)((Component)__instance).gameObject).name));
if ((Object)(object)Plugin.AmbientClip == (Object)null)
{
Plugin.Log.LogWarning((object)"[PhonographSoundMod] Ambient clip not ready.");
return;
}
SoundSource loopSoundSource = __instance.loopSoundSource;
if ((Object)(object)loopSoundSource == (Object)null)
{
Plugin.Log.LogWarning((object)"[PhonographSoundMod] loopSoundSource is null.");
return;
}
float num = ((SpatialBlendProp != null) ? ((float)SpatialBlendProp.GetValue(loopSoundSource)) : 1f);
float num2 = ((MinRangeProp != null) ? ((float)MinRangeProp.GetValue(loopSoundSource)) : 1f);
float num3 = ((MaxRangeProp != null) ? ((float)MaxRangeProp.GetValue(loopSoundSource)) : 20f);
object? obj = AudioSourceField?.GetValue(loopSoundSource);
AudioSource val = (AudioSource)((obj is AudioSource) ? obj : null);
if ((Object)(object)val != (Object)null)
{
val.Stop();
((Behaviour)val).enabled = false;
}
LoopSoundSourceField?.SetValue(__instance, null);
((Behaviour)loopSoundSource).enabled = false;
AudioSource obj2 = ((Component)__instance).gameObject.AddComponent<AudioSource>();
obj2.clip = Plugin.AmbientClip;
obj2.volume = Plugin.AmbientVolume;
obj2.loop = true;
obj2.spatialBlend = num;
obj2.minDistance = num2;
obj2.maxDistance = num3;
obj2.rolloffMode = (AudioRolloffMode)0;
obj2.playOnAwake = false;
obj2.Play();
((Component)__instance).gameObject.AddComponent<PauseAwareAudio>();
Plugin.Log.LogInfo((object)$"[PhonographSoundMod] Ambient playing – blend:{num:F2} min:{num2:F1} max:{num3:F1} clip:{((Object)Plugin.AmbientClip).name}");
}
}
internal class PauseAwareAudio : MonoBehaviour
{
private AudioSource _source;
private bool _wasPaused;
private void Awake()
{
_source = ((Component)this).GetComponent<AudioSource>();
}
private void Update()
{
bool flag = Time.timeScale == 0f || AudioListener.pause;
if (flag && !_wasPaused)
{
if ((Object)(object)_source != (Object)null && _source.isPlaying)
{
_source.Pause();
}
_wasPaused = true;
}
else if (!flag && _wasPaused)
{
if ((Object)(object)_source != (Object)null)
{
_source.UnPause();
}
_wasPaused = false;
}
}
}
internal static class MyPluginInfo
{
internal const string PLUGIN_GUID = "com.wanderan51.gloomwood.phonographsound";
internal const string PLUGIN_NAME = "PhonographSoundMod";
internal const string PLUGIN_VERSION = "1.0.0";
}