using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.SceneManagement;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("SoundEffectVolumeLimiter")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Sound Effect Volume Limiter")]
[assembly: AssemblyTitle("SoundEffectVolumeLimiter")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[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 SoundEffectVolumeLimiter
{
[BepInPlugin("com.Exocet.SoundEffectVolumeLimiter", "Sound Effect Volume Limiter", "1.0.2")]
public class SoundEffectVolumeLimiterPlugin : BaseUnityPlugin
{
public const string PLUGIN_GUID = "com.Exocet.SoundEffectVolumeLimiter";
public const string PLUGIN_NAME = "Sound Effect Volume Limiter";
public const string PLUGIN_VERSION = "1.0.2";
private void Awake()
{
ShipSoundCaps.Bind(((BaseUnityPlugin)this).Config);
((Component)this).gameObject.AddComponent<ShipSoundCaps>();
}
}
internal sealed class ConfigurationManagerAttributes
{
public int? Order;
}
public class ShipSoundCaps : MonoBehaviour
{
private sealed class SoundGroup
{
public string Name;
public string[] Keywords;
}
private static readonly string[] DefaultGroupNames = new string[10] { "Footsteps", "Helm Creak", "Boat Creaking", "Hull Wash", "Waves", "Rigging", "Weather", "Misc Effects", "Custom 1", "Custom 2" };
private static readonly string[][] DefaultGroupKeywords = new string[10][]
{
new string[5] { "footstep", "footsteps", "foot", "step", "steps" },
new string[1] { "wheel creak" },
new string[1] { "boat creak" },
new string[3] { "hull", "hitting-bow", "bow" },
new string[5] { "oceanwave", "wave", "splash", "ocean", "shore" },
new string[4] { "sail", "rope", "flap", "snap" },
new string[4] { "rain", "thunder", "storm", "wind" },
new string[6] { "click", "eat", "swallow", "scrape", "fishing", "seagulls" },
new string[1] { "bell" },
new string[1] { "pump" }
};
private static readonly SoundGroup[] DefaultGroups = CreateDefaultGroups();
private static SoundGroup[] _groups = CreateDefaultGroups();
private static ConfigEntry<string>[] _groupNames;
private static ConfigEntry<string>[] _groupKeywords;
private static ConfigEntry<float>[] _caps;
private static ConfigEntry<KeyboardShortcut> _dumpKey;
private static ConfigEntry<KeyboardShortcut> _refreshGroupsKey;
private static ConfigEntry<KeyboardShortcut> _restoreDefaultGroupsKey;
private static readonly HashSet<ShipSoundCaps> Instances = new HashSet<ShipSoundCaps>();
private static readonly List<AudioSource> SceneAudioSources = new List<AudioSource>();
private readonly List<AudioSource>[] _byGroup = new List<AudioSource>[DefaultGroups.Length];
private readonly HashSet<AudioSource> _mutedByUs = new HashSet<AudioSource>();
private float _nextScan;
private static SoundGroup[] CreateDefaultGroups()
{
SoundGroup[] array = new SoundGroup[DefaultGroupNames.Length];
for (int i = 0; i < DefaultGroupNames.Length; i++)
{
array[i] = new SoundGroup
{
Name = DefaultGroupNames[i],
Keywords = CopyKeywords(DefaultGroupKeywords[i])
};
}
return array;
}
private static string[] CopyKeywords(string[] keywords)
{
string[] array = new string[keywords.Length];
for (int i = 0; i < keywords.Length; i++)
{
array[i] = keywords[i].ToLowerInvariant();
}
return array;
}
public static void Bind(ConfigFile cfg)
{
//IL_007e: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Expected O, but got Unknown
//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
//IL_00f0: Expected O, but got Unknown
//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
//IL_01e0: Expected O, but got Unknown
//IL_020b: Unknown result type (might be due to invalid IL or missing references)
//IL_0234: Unknown result type (might be due to invalid IL or missing references)
//IL_023e: Expected O, but got Unknown
//IL_0258: Unknown result type (might be due to invalid IL or missing references)
//IL_0281: Unknown result type (might be due to invalid IL or missing references)
//IL_028b: Expected O, but got Unknown
//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
//IL_02d8: Expected O, but got Unknown
_groupNames = new ConfigEntry<string>[DefaultGroupNames.Length];
_groupKeywords = new ConfigEntry<string>[DefaultGroupNames.Length];
for (int i = 0; i < DefaultGroupNames.Length; i++)
{
_groupNames[i] = cfg.Bind<string>("Ship sound", "Group " + (i + 1) + " name", DefaultGroupNames[i], new ConfigDescription("Display name for this ship sound group.", (AcceptableValueBase)null, new object[1]
{
new ConfigurationManagerAttributes
{
Order = GroupOrder(i, 0)
}
}));
_groupKeywords[i] = cfg.Bind<string>("Ship sound", "Group " + (i + 1) + " keywords", string.Join(";", DefaultGroupKeywords[i]), new ConfigDescription("Semicolon-separated clip fragments used to detect sounds for this group. Example: wave; splash", (AcceptableValueBase)null, new object[1]
{
new ConfigurationManagerAttributes
{
Order = GroupOrder(i, 1)
}
}));
_groupNames[i].SettingChanged += delegate
{
RefreshGroupsFromConfig();
};
_groupKeywords[i].SettingChanged += delegate
{
RefreshGroupsFromConfig();
};
}
RefreshGroupsFromConfig();
_caps = new ConfigEntry<float>[_groups.Length];
for (int num = 0; num < _groups.Length; num++)
{
_caps[num] = cfg.Bind<float>("Ship sound", _groups[num].Name + " volume ceiling", 1f, new ConfigDescription("1 = untouched, 0 = silent. This is a ceiling: anything already quieter than this is left alone.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), new object[1]
{
new ConfigurationManagerAttributes
{
Order = GroupOrder(num, 2)
}
}));
}
_dumpKey = cfg.Bind<KeyboardShortcut>("Ship sound", "List the clips on this ship", new KeyboardShortcut((KeyCode)292, Array.Empty<KeyCode>()), new ConfigDescription("Press this key in-game to list matching and ungrouped audio clips.", (AcceptableValueBase)null, new object[1]
{
new ConfigurationManagerAttributes
{
Order = 520
}
}));
_refreshGroupsKey = cfg.Bind<KeyboardShortcut>("Ship sound", "Refresh groups key", new KeyboardShortcut((KeyCode)290, Array.Empty<KeyCode>()), new ConfigDescription("Press this key in-game to rebuild the configured groups and rescan all active audio sources.", (AcceptableValueBase)null, new object[1]
{
new ConfigurationManagerAttributes
{
Order = 540
}
}));
_restoreDefaultGroupsKey = cfg.Bind<KeyboardShortcut>("Ship sound", "Restore default groups key", new KeyboardShortcut((KeyCode)289, Array.Empty<KeyCode>()), new ConfigDescription("Press this key in-game to restore the default group names and keyword sets without changing volume ceilings.", (AcceptableValueBase)null, new object[1]
{
new ConfigurationManagerAttributes
{
Order = 560
}
}));
}
private static int GroupOrder(int groupIndex, int settingOffset)
{
return 1000 - groupIndex * 30 - settingOffset;
}
private static void RefreshGroupsFromConfig()
{
if (_groupNames == null || _groupKeywords == null)
{
return;
}
_groups = new SoundGroup[_groupNames.Length];
for (int i = 0; i < _groupNames.Length; i++)
{
string text = ((_groupNames[i] != null && !string.IsNullOrWhiteSpace(_groupNames[i].Value)) ? _groupNames[i].Value.Trim() : DefaultGroups[i].Name);
List<string> list = new List<string>();
list.Add(text.ToLowerInvariant());
if (_groupKeywords[i] != null && !string.IsNullOrEmpty(_groupKeywords[i].Value))
{
string[] array = _groupKeywords[i].Value.Split(new char[3] { ';', ',', '|' }, StringSplitOptions.RemoveEmptyEntries);
for (int j = 0; j < array.Length; j++)
{
string text2 = array[j].Trim();
if (!string.IsNullOrEmpty(text2))
{
list.Add(text2.ToLowerInvariant());
}
}
}
if (list.Count == 1)
{
for (int k = 0; k < DefaultGroups[i].Keywords.Length; k++)
{
list.Add(DefaultGroups[i].Keywords[k]);
}
}
_groups[i] = new SoundGroup
{
Name = text,
Keywords = list.ToArray()
};
}
}
private void Awake()
{
Instances.Add(this);
for (int i = 0; i < _groups.Length; i++)
{
_byGroup[i] = new List<AudioSource>();
}
Rescan();
}
private void OnDestroy()
{
Instances.Remove(this);
}
private static List<AudioSource> FindSceneAudioSources()
{
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
AudioSource[] array = Resources.FindObjectsOfTypeAll<AudioSource>();
SceneAudioSources.Clear();
foreach (AudioSource val in array)
{
if ((Object)(object)val != (Object)null)
{
Scene scene = ((Component)val).gameObject.scene;
if (((Scene)(ref scene)).IsValid())
{
SceneAudioSources.Add(val);
}
}
}
return SceneAudioSources;
}
private void Rescan()
{
_mutedByUs.RemoveWhere(IsDestroyedAudioSource);
for (int i = 0; i < _byGroup.Length; i++)
{
_byGroup[i].Clear();
}
List<AudioSource> list = FindSceneAudioSources();
for (int j = 0; j < list.Count; j++)
{
AudioSource val = list[j];
if (!((Object)(object)val == (Object)null) && !((Object)(object)val.clip == (Object)null) && ((Object)val.clip).name != null)
{
string clipName = ((Object)val.clip).name.ToLowerInvariant();
int num = FindMatchingGroup(clipName);
if (num >= 0)
{
_byGroup[num].Add(val);
}
}
}
}
private static int FindMatchingGroup(string clipName)
{
for (int i = 0; i < _groups.Length; i++)
{
SoundGroup soundGroup = _groups[i];
for (int j = 0; j < soundGroup.Keywords.Length; j++)
{
string value = soundGroup.Keywords[j];
if (!string.IsNullOrEmpty(value) && clipName.Contains(value))
{
return i;
}
}
}
return -1;
}
private void LateUpdate()
{
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_0073: Unknown result type (might be due to invalid IL or missing references)
//IL_0078: Unknown result type (might be due to invalid IL or missing references)
//IL_009c: Unknown result type (might be due to invalid IL or missing references)
//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
if (_caps == null)
{
return;
}
if (Time.time >= _nextScan)
{
_nextScan = Time.time + 5f;
Rescan();
}
KeyboardShortcut value;
if (_dumpKey != null)
{
value = _dumpKey.Value;
if (((KeyboardShortcut)(ref value)).IsDown())
{
Dump();
}
}
if (_refreshGroupsKey != null)
{
value = _refreshGroupsKey.Value;
if (((KeyboardShortcut)(ref value)).IsDown())
{
Rescan();
}
}
if (_restoreDefaultGroupsKey != null)
{
value = _restoreDefaultGroupsKey.Value;
if (((KeyboardShortcut)(ref value)).IsDown())
{
RestoreDefaultGroups();
}
}
for (int i = 0; i < _byGroup.Length; i++)
{
float value2 = _caps[i].Value;
List<AudioSource> list = _byGroup[i];
for (int j = 0; j < list.Count; j++)
{
AudioSource val = list[j];
if ((Object)(object)val == (Object)null)
{
continue;
}
if (value2 <= 0.001f)
{
if (!val.mute)
{
val.mute = true;
_mutedByUs.Add(val);
}
continue;
}
if (_mutedByUs.Contains(val))
{
val.mute = false;
_mutedByUs.Remove(val);
}
if (!(value2 >= 0.999f))
{
val.volume = Mathf.Min(val.volume, value2);
}
}
}
}
private static bool IsDestroyedAudioSource(AudioSource source)
{
return (Object)(object)source == (Object)null;
}
private static void RestoreDefaultGroups()
{
if (_groupNames != null && _groupKeywords != null)
{
for (int i = 0; i < DefaultGroupNames.Length; i++)
{
_groupNames[i].Value = DefaultGroupNames[i];
_groupKeywords[i].Value = string.Join(";", DefaultGroupKeywords[i]);
}
RefreshGroupsFromConfig();
RescanAllInstances();
Debug.Log((object)"[ShipSound] Restored default group order and keyword sets.");
}
}
private static void RescanAllInstances()
{
foreach (ShipSoundCaps instance in Instances)
{
if ((Object)(object)instance != (Object)null)
{
instance.Rescan();
}
}
}
private void Dump()
{
Rescan();
for (int i = 0; i < _byGroup.Length; i++)
{
StringBuilder stringBuilder = new StringBuilder();
for (int j = 0; j < _byGroup[i].Count; j++)
{
if ((Object)(object)_byGroup[i][j] != (Object)null && (Object)(object)_byGroup[i][j].clip != (Object)null)
{
stringBuilder.Append(((Object)_byGroup[i][j].clip).name).Append(" ");
}
}
Debug.Log((object)("[ShipSound] " + _groups[i].Name + " (" + _byGroup[i].Count + "): " + stringBuilder));
}
List<AudioSource> list = FindSceneAudioSources();
StringBuilder stringBuilder2 = new StringBuilder();
for (int k = 0; k < list.Count; k++)
{
if ((Object)(object)list[k] == (Object)null || (Object)(object)list[k].clip == (Object)null)
{
continue;
}
bool flag = false;
for (int l = 0; l < _byGroup.Length; l++)
{
if (flag)
{
break;
}
flag = _byGroup[l].Contains(list[k]);
}
if (!flag)
{
stringBuilder2.Append(((Object)list[k].clip).name).Append(" ");
}
}
Debug.Log((object)("[ShipSound] UNGROUPED: " + stringBuilder2));
}
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "SoundEffectVolumeLimiter";
public const string PLUGIN_NAME = "Sound Effect Volume Limiter";
public const string PLUGIN_VERSION = "1.0.0";
}
}