using System;
using System.Buffers;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using Cysharp.Threading.Tasks;
using Cysharp.Threading.Tasks.CompilerServices;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
using loaforcsSoundAPI.API;
using loaforcsSoundAPI.Behaviours;
using loaforcsSoundAPI.Data;
using loaforcsSoundAPI.LethalCompany;
using loaforcsSoundAPI.LethalCompany.Conditions;
using loaforcsSoundAPI.Patches;
using loaforcsSoundAPI.Providers.Conditions;
using loaforcsSoundAPI.Providers.Formats;
using loaforcsSoundAPI.Utils;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("AmazingAssets.TerrainToMesh")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("ClientNetworkTransform")]
[assembly: IgnoresAccessChecksTo("DissonanceVoip")]
[assembly: IgnoresAccessChecksTo("Facepunch Transport for Netcode for GameObjects")]
[assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")]
[assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging.DocCodeExamples")]
[assembly: IgnoresAccessChecksTo("Unity.Burst")]
[assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")]
[assembly: IgnoresAccessChecksTo("Unity.Collections")]
[assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")]
[assembly: IgnoresAccessChecksTo("Unity.Jobs")]
[assembly: IgnoresAccessChecksTo("Unity.Mathematics")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.Common")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.MetricTypes")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStats")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Component")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Configuration")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Implementation")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsReporting")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkProfiler.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkSolutionInterface")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Components")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Networking.Transport")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Csg")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.KdTree")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Poly2Tri")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Stl")]
[assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Config.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Authentication")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Analytics")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Configuration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Device")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Networking")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Registration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Scheduler")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Telemetry")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Threading")]
[assembly: IgnoresAccessChecksTo("Unity.Services.QoS")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Relay")]
[assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")]
[assembly: IgnoresAccessChecksTo("Unity.Timeline")]
[assembly: IgnoresAccessChecksTo("Unity.VisualEffectGraph.Runtime")]
[assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UI")]
[assembly: AssemblyCompany("me.loaforc.soundapi")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.7.0")]
[assembly: AssemblyInformationalVersion("1.1.7+db5507b4bca7431455f856c23063a1fa6eb0843a")]
[assembly: AssemblyProduct("loaforcsSoundAPI")]
[assembly: AssemblyTitle("me.loaforc.soundapi")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.7.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 loaforcsSoundAPI
{
public static class SoundLoader
{
public static bool GetAudioClip(string packName, string folder, string soundName, out AudioClip clip)
{
if (SoundPluginConfig.LOGGING_LEVEL.Value == SoundPluginConfig.LoggingLevel.IM_GOING_TO_LOSE_IT)
{
SoundPlugin.logger.LogLosingIt("Loading sound: " + packName + "/" + folder + "/" + soundName);
}
clip = null;
if (!GetAudioPath(packName, folder, soundName, out var path))
{
((ManualLogSource)SoundPlugin.logger).LogError((object)"Failed getting path, check above for more detailed error!");
return false;
}
clip = SoundAPI.FileFormats[Path.GetExtension(path).ToLower()].LoadAudioClip(path);
if ((Object)(object)clip == (Object)null)
{
((ManualLogSource)SoundPlugin.logger).LogError((object)"Failed getting clip from disk, check above for more detailed error!");
return false;
}
if (string.IsNullOrEmpty(clip.GetName()))
{
((Object)clip).name = soundName;
}
return true;
}
private static bool GetAudioPath(string packName, string folder, string soundName, out string path)
{
string text = Path.Combine(Paths.PluginPath, packName, "sounds", folder);
path = Path.Combine(text, soundName);
if (!Directory.Exists(text))
{
((ManualLogSource)SoundPlugin.logger).LogError((object)(text + " doesn't exist! (failed loading: " + soundName + ")"));
path = null;
return false;
}
if (!File.Exists(path))
{
((ManualLogSource)SoundPlugin.logger).LogError((object)(path + " is a valid folder but the sound contained doesn't exist!"));
path = null;
return false;
}
return true;
}
}
[BepInPlugin("me.loaforc.soundapi", "loaforcsSoundAPI", "1.1.7")]
public class SoundPlugin : BaseUnityPlugin
{
internal static List<SoundPack> SoundPacks = new List<SoundPack>();
internal List<UniTask> loadingTasks = new List<UniTask>();
public static SoundPlugin Instance { get; private set; }
internal static LoafLogger logger { get; private set; }
[Obsolete]
internal static ManualLogSource Logger => (ManualLogSource)(object)logger;
private void Awake()
{
//IL_0229: Unknown result type (might be due to invalid IL or missing references)
logger = new LoafLogger("me.loaforc.soundapi");
Logger.Sources.Add((ILogSource)(object)logger);
Instance = this;
((ManualLogSource)logger).LogInfo((object)"Patching...");
Harmony val = Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "me.loaforc.soundapi");
((ManualLogSource)logger).LogInfo((object)"Setting up config...");
new SoundPluginConfig(((BaseUnityPlugin)this).Config);
((ManualLogSource)logger).LogInfo((object)("Logging Level at: " + SoundPluginConfig.LOGGING_LEVEL.Value));
((ManualLogSource)logger).LogInfo((object)"Searching for soundpacks...");
string[] directories = Directory.GetDirectories(Paths.PluginPath);
((ManualLogSource)logger).LogInfo((object)"Beginning Bindings");
((ManualLogSource)logger).LogInfo((object)"Bindings => General => Audio Formats");
SoundAPI.RegisterAudioFormatProvider(".mp3", new Mp3AudioFormat());
SoundAPI.RegisterAudioFormatProvider(".ogg", new OggAudioFormat());
SoundAPI.RegisterAudioFormatProvider(".wav", new WavAudioFormat());
((ManualLogSource)logger).LogInfo((object)"Bindings => General => Conditions");
SoundAPI.RegisterConditionProvider("config", new ConfigCondition());
SoundAPI.RegisterConditionProvider("mod_installed", new ModInstalledConditionProvider());
SoundAPI.RegisterConditionProvider("and", new AndCondition());
SoundAPI.RegisterConditionProvider("not", new NotCondition());
SoundAPI.RegisterConditionProvider("or", new OrCondition());
LethalCompanyBindings.Bind();
string[] array = directories;
foreach (string text in array)
{
string[] directories2 = Directory.GetDirectories(text);
foreach (string text2 in directories2)
{
string path = Path.Combine(text2, "sound_pack.json");
((ManualLogSource)logger).LogDebug((object)text2);
if (File.Exists(path))
{
SoundPacks.Add(new SoundPack(text2));
break;
}
}
string path2 = Path.Combine(text, "sound_pack.json");
if (File.Exists(path2))
{
SoundPacks.Add(new SoundPack(text));
}
}
((ManualLogSource)logger).LogInfo((object)"Starting up JoinableThreadPool.");
foreach (SoundPack soundPack in SoundPacks)
{
if (SoundPluginConfig.ENABLE_MULTITHREADING.Value)
{
loadingTasks.Add(soundPack.AsyncQueueLoad());
}
else
{
soundPack.QueueLoad();
}
}
logger.LogLosingIt($"Created {loadingTasks.Count} loading tasks!");
((ManualLogSource)logger).LogInfo((object)"Registering onSceneLoaded");
SceneManager.sceneLoaded += delegate(Scene scene, LoadSceneMode __)
{
//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)
logger.LogLosingIt("NEW SCENE LOADED! Scanning for inital playOnAwake sounds...");
logger.LogLosingIt("scene.name: " + ((Scene)(ref scene)).name);
AudioSourcePatch.TrimmedGameobjectNames.Clear();
AudioSource[] array2 = Object.FindObjectsOfType<AudioSource>(true);
foreach (AudioSource val2 in array2)
{
if (!(((Component)val2).gameObject.scene != scene))
{
if (val2.playOnAwake)
{
logger.LogLosingIt($"source: {val2}");
logger.LogLosingIt($"source.gameObject: {((Component)val2).gameObject}");
logger.LogLosingIt($"source.clip: {(Object)(object)val2.clip == (Object)null}");
logger.LogLosingIt(((Object)((Component)val2).gameObject).name + ":" + (((Object)(object)val2.clip == (Object)null) ? "null" : ((Object)val2.clip).name) + " calling Stop() because its play on awake.");
val2.Stop();
}
AudioSourceReplaceHelper audioSourceReplaceHelper = ((Component)val2).gameObject.AddComponent<AudioSourceReplaceHelper>();
audioSourceReplaceHelper.source = val2;
}
}
};
((ManualLogSource)logger).LogInfo((object)"me.loaforc.soundapi:1.1.7 has loaded!");
}
internal void EnsureSoundsAreLoaded()
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
if (!SoundPluginConfig.ENABLE_MULTITHREADING.Value)
{
return;
}
((ManualLogSource)logger).LogInfo((object)"Ensuring all sounds are loaded...");
foreach (UniTask loadingTask in loadingTasks)
{
UniTask current = loadingTask;
int num = 0;
while (!UniTaskStatusExtensions.IsCompleted(((UniTask)(ref current)).Status))
{
Thread.Sleep(100);
num++;
logger.LogLosingIt("Still waiting...");
if (num > 100)
{
((ManualLogSource)logger).LogWarning((object)"AAAAAAAAAAAAAAAAAAAAAAA ITS BEEN LONGER THAN 10 SECONDS THIS ISN'T GOODD!!");
}
if (num % 10 == 0)
{
((ManualLogSource)logger).LogInfo((object)"Things are still happening don't worry.");
}
}
}
((ManualLogSource)logger).LogInfo((object)"it's all good :3");
}
}
internal class SoundPluginConfig
{
internal enum LoggingLevel
{
NORMAL,
EXTENDED,
IM_GOING_TO_LOSE_IT
}
internal static ConfigEntry<bool> ENABLE_MULTITHREADING;
internal static ConfigEntry<int> THREADPOOL_MAX_THREADS;
internal static ConfigEntry<bool> SKIP_LOADING_UNUSED_SOUNDS;
internal static ConfigEntry<LoggingLevel> LOGGING_LEVEL;
internal static ConfigEntry<bool> EXPERIMENTAL_HANDLE_LOOPING_SOUNDS;
private static ConfigEntry<int> CONFIG_VERSION;
internal SoundPluginConfig(ConfigFile config)
{
ENABLE_MULTITHREADING = config.Bind<bool>("SoundLoading", "Multithreading", true, "Whether or not to use multithreading when loading a sound pack. If you haven't been told that you should disable multithreading, you probably don't need to!\nThis setting may not be needed with the new 1.0.0 rewrite of multithreading.");
THREADPOOL_MAX_THREADS = config.Bind<int>("SoundLoading", "MaxThreadsInThreadPool", 4, "Max amount of threads the loading thread pool can create at once.\nIncreasing this number will decrease loading of non-startup packs but may be unsupported by your CPU.");
SKIP_LOADING_UNUSED_SOUNDS = config.Bind<bool>("SoundLoading", "SkipLikelyUnusedSounds", true, "When using only a config loaforcsSoundAPI will be able to skip loading some sounds. This means mods that let you change config mid-game will not take affect until a restart.");
LOGGING_LEVEL = config.Bind<LoggingLevel>("Logging", "LoggingLevel", LoggingLevel.NORMAL, "What level should sound api log at?");
EXPERIMENTAL_HANDLE_LOOPING_SOUNDS = config.Bind<bool>("Experimental", "HandleLoopingSounds", false, "Enable experimental support to replace sounds everytime they loop?");
CONFIG_VERSION = config.Bind<int>("INTERNAL_DO_NOT_TOUCH", "CONFIG_VERSION_DO_NOT_TOUCH", 1, "Don't touch this. This is for internal use only.");
if (CONFIG_VERSION.Value == 1)
{
CONFIG_VERSION.Value = 2;
if (THREADPOOL_MAX_THREADS.Value == 32)
{
THREADPOOL_MAX_THREADS.Value = 4;
((ManualLogSource)SoundPlugin.logger).LogInfo((object)"Migrated config info.");
}
}
}
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "me.loaforc.soundapi";
public const string PLUGIN_NAME = "loaforcsSoundAPI";
public const string PLUGIN_VERSION = "1.1.7";
}
}
namespace loaforcsSoundAPI.Utils
{
public static class ExtensionMethods
{
public static T GetValueOrDefault<T>(this JObject jsonObject, string key, T defaultValue = default(T))
{
JToken val = ((jsonObject != null) ? jsonObject.GetValue(key, StringComparison.OrdinalIgnoreCase) : null);
if (val == null)
{
return defaultValue;
}
return val.ToObject<T>();
}
public static TValue GetValueOrDefault<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key, TValue defaultValue)
{
if (!dictionary.TryGetValue(key, out var value))
{
return defaultValue;
}
return value;
}
public static TValue GetValueOrDefault<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key, Func<TValue> defaultValueProvider)
{
if (!dictionary.TryGetValue(key, out var value))
{
return defaultValueProvider();
}
return value;
}
public static bool IsNumber(this object @object)
{
if (@object is int || @object is double || @object is float)
{
return true;
}
return false;
}
}
internal class LoafLogger : ManualLogSource
{
public LoafLogger(string sourceName)
: base(sourceName)
{
}
internal void LogExtended(object message)
{
if (SoundPluginConfig.LOGGING_LEVEL.Value == SoundPluginConfig.LoggingLevel.EXTENDED || SoundPluginConfig.LOGGING_LEVEL.Value == SoundPluginConfig.LoggingLevel.IM_GOING_TO_LOSE_IT)
{
((ManualLogSource)this).LogDebug((object)$"[EXTENDED] {message}");
}
}
internal void LogLosingIt(object message)
{
if (SoundPluginConfig.LOGGING_LEVEL.Value == SoundPluginConfig.LoggingLevel.IM_GOING_TO_LOSE_IT)
{
((ManualLogSource)this).LogDebug((object)$"[IM_GOING_TO_LOSE_IT] {message}");
}
}
internal void LogTraceback()
{
LogLosingIt(new StackTrace().ToString());
}
}
}
namespace loaforcsSoundAPI.Providers.Formats
{
internal class Mp3AudioFormat : AudioFormatProvider
{
public override AudioClip LoadAudioClip(string path)
{
return LoadFromUWR(path, (AudioType)24);
}
}
internal class OggAudioFormat : AudioFormatProvider
{
public override AudioClip LoadAudioClip(string path)
{
return LoadFromUWR(path, (AudioType)14);
}
}
internal class WavAudioFormat : AudioFormatProvider
{
public override AudioClip LoadAudioClip(string path)
{
return LoadFromUWR(path, (AudioType)20);
}
}
}
namespace loaforcsSoundAPI.Providers.Conditions
{
internal class AndCondition : ConditionProvider
{
public override bool Evaluate(SoundReplaceGroup pack, JObject conditionDef)
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Expected O, but got Unknown
foreach (JObject item in (IEnumerable<JToken>)conditionDef["conditions"])
{
JObject val = item;
if (!SoundAPI.ConditionProviders[(string)val["type"]].Evaluate(pack, val))
{
return false;
}
}
return true;
}
}
internal class ConfigCondition : ConditionProvider
{
public override bool Evaluate(SoundReplaceGroup group, JObject conditionDef)
{
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Invalid comparison between Unknown and I4
//IL_0092: Unknown result type (might be due to invalid IL or missing references)
//IL_0098: Invalid comparison between Unknown and I4
if (!conditionDef.ContainsKey("value"))
{
return group.pack.GetConfigOption<bool>((string)conditionDef["config"]);
}
if ((int)conditionDef["value"].Type == 9)
{
return group.pack.GetConfigOption<bool>((string)conditionDef["config"]) == (bool)conditionDef["value"];
}
object rawConfigOption = group.pack.GetRawConfigOption((string)conditionDef["config"]);
if ((int)conditionDef["value"].Type == 8)
{
if (rawConfigOption is ConfigEntry<float>)
{
return EvaluateRangeOperator((rawConfigOption as ConfigEntry<float>).Value, (string)conditionDef["value"]);
}
return (string)rawConfigOption == (string)conditionDef["value"];
}
return false;
}
}
internal class ModInstalledConditionProvider : ConditionProvider
{
public override bool Evaluate(SoundReplaceGroup group, JObject conditionDef)
{
return Chainloader.PluginInfos.ContainsKey((string)conditionDef["value"]);
}
}
internal class NotCondition : ConditionProvider
{
public override bool Evaluate(SoundReplaceGroup pack, JObject conditionDef)
{
ConditionProvider conditionProvider = SoundAPI.ConditionProviders[(string)conditionDef["condition"][(object)"type"]];
JToken obj = conditionDef["condition"];
return !conditionProvider.Evaluate(pack, (JObject)(object)((obj is JObject) ? obj : null));
}
}
internal class OrCondition : ConditionProvider
{
public override bool Evaluate(SoundReplaceGroup pack, JObject conditionDef)
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Expected O, but got Unknown
foreach (JObject item in (IEnumerable<JToken>)conditionDef["conditions"])
{
JObject val = item;
if (SoundAPI.ConditionProviders[(string)val["type"]].Evaluate(pack, val))
{
return true;
}
}
return false;
}
}
}
namespace loaforcsSoundAPI.Patches
{
[HarmonyPatch(typeof(AudioSource))]
internal static class AudioSourcePatch
{
private const int TOKEN_PARENT_NAME = 0;
private const int TOKEN_OBJECT_NAME = 1;
private const int TOKEN_CLIP_NAME = 2;
private static string[] SUFFIXES_TO_REMOVE = new string[4] { "(Clone)", "(1)", "(2)", "(3)" };
internal static Dictionary<int, string> TrimmedGameobjectNames = new Dictionary<int, string>();
private static StringBuilder builder = new StringBuilder();
[HarmonyPrefix]
[HarmonyPatch("Play", new Type[] { })]
[HarmonyPatch("Play", new Type[] { typeof(ulong) })]
[HarmonyPatch("Play", new Type[] { typeof(double) })]
private static bool Play(AudioSource __instance)
{
if (TryReplaceAudio(__instance, __instance.clip, out var replacement))
{
if ((Object)(object)replacement == (Object)null)
{
return false;
}
__instance.clip = replacement;
}
if (AudioSourceReplaceHelper.helpers.TryGetValue(__instance, out var value))
{
value._isPlaying = true;
}
return true;
}
[HarmonyPrefix]
[HarmonyPatch("PlayOneShot", new Type[]
{
typeof(AudioClip),
typeof(float)
})]
private static bool PlayOneShot(AudioSource __instance, ref AudioClip clip)
{
if (TryReplaceAudio(__instance, clip, out var replacement))
{
if ((Object)(object)replacement == (Object)null)
{
return false;
}
clip = replacement;
}
return true;
}
[HarmonyPostfix]
[HarmonyPatch("Stop", new Type[] { typeof(bool) })]
private static void UpdateIsPlayingForHelper(AudioSource __instance)
{
if (SoundPluginConfig.EXPERIMENTAL_HANDLE_LOOPING_SOUNDS.Value && AudioSourceReplaceHelper.helpers.TryGetValue(__instance, out var value) && value._isPlaying)
{
value._isPlaying = false;
if (SoundPluginConfig.LOGGING_LEVEL.Value == SoundPluginConfig.LoggingLevel.IM_GOING_TO_LOSE_IT)
{
SoundPlugin.logger.LogLosingIt(".Stop() updated ._isPlaying to false");
}
}
}
[HarmonyPrefix]
[HarmonyPatch(/*Could not decode attribute arguments.*/)]
private static bool SetAudioSourceLooping(AudioSource __instance, bool value)
{
if (!SoundPluginConfig.EXPERIMENTAL_HANDLE_LOOPING_SOUNDS.Value)
{
return true;
}
if (AudioSourceReplaceHelper.helpers.TryGetValue(__instance, out var value2))
{
if (SoundPluginConfig.LOGGING_LEVEL.Value == SoundPluginConfig.LoggingLevel.IM_GOING_TO_LOSE_IT)
{
SoundPlugin.logger.LogLosingIt($"updating looping for {((Component)__instance).gameObject}, value: {value}");
}
value2.Loop = value;
return false;
}
return true;
}
[HarmonyPostfix]
[HarmonyPatch(/*Could not decode attribute arguments.*/)]
private static void GetAudioSourceLooping(AudioSource __instance, ref bool __result)
{
if (SoundPluginConfig.EXPERIMENTAL_HANDLE_LOOPING_SOUNDS.Value && AudioSourceReplaceHelper.helpers.TryGetValue(__instance, out var value))
{
if (SoundPluginConfig.LOGGING_LEVEL.Value == SoundPluginConfig.LoggingLevel.IM_GOING_TO_LOSE_IT)
{
SoundPlugin.logger.LogLosingIt("swapping out result of AudioSource.loop :3");
}
__result = value.Loop;
}
}
internal static bool TryReplaceAudio(AudioSource __instance, AudioClip clip, out AudioClip replacement)
{
replacement = null;
if ((Object)(object)((Component)__instance).gameObject == (Object)null)
{
if (SoundPluginConfig.LOGGING_LEVEL.Value == SoundPluginConfig.LoggingLevel.IM_GOING_TO_LOSE_IT)
{
SoundPlugin.logger.LogLosingIt("AudioSource has no GameObject!!");
}
return false;
}
if (AudioSourceReplaceHelper.helpers.TryGetValue(__instance, out var value) && value.DisableReplacing)
{
return false;
}
string[] name = ArrayPool<string>.Shared.Rent(3);
if (!TryProcessName(ref name, __instance, clip))
{
ArrayPool<string>.Shared.Return(name);
return false;
}
if (!TryGetReplacementClip(name, out var collection, out var clip2))
{
ArrayPool<string>.Shared.Return(name);
return false;
}
ArrayPool<string>.Shared.Return(name);
if ((Object)(object)value == (Object)null)
{
if (__instance.playOnAwake)
{
__instance.Stop();
}
value = ((Component)__instance).gameObject.AddComponent<AudioSourceReplaceHelper>();
value.source = __instance;
}
((Object)clip2).name = ((Object)clip).name;
replacement = clip2;
value.replacedWith = collection;
return true;
}
private static string TrimGameObjectName(GameObject gameObject)
{
if (TrimmedGameobjectNames.ContainsKey(((object)gameObject).GetHashCode()))
{
return TrimmedGameobjectNames[((object)gameObject).GetHashCode()];
}
builder.Clear();
builder.Append(((Object)gameObject).name);
string[] sUFFIXES_TO_REMOVE = SUFFIXES_TO_REMOVE;
foreach (string oldValue in sUFFIXES_TO_REMOVE)
{
builder.Replace(oldValue, string.Empty);
}
int num = builder.Length;
while (num > 0 && builder[num - 1] == ' ')
{
num--;
}
builder.Remove(num, builder.Length - num);
string text = builder.ToString();
TrimmedGameobjectNames[((object)gameObject).GetHashCode()] = text;
if (SoundPluginConfig.LOGGING_LEVEL.Value == SoundPluginConfig.LoggingLevel.IM_GOING_TO_LOSE_IT)
{
SoundPlugin.logger.LogLosingIt("trimmed `" + ((Object)gameObject).name + "` to `" + text + "`");
}
return text;
}
private static bool TryProcessName(ref string[] name, AudioSource source, AudioClip clip)
{
if ((Object)(object)clip == (Object)null)
{
return false;
}
if ((Object)(object)((Component)source).transform.parent == (Object)null)
{
name[0] = "*";
}
else
{
name[0] = TrimGameObjectName(((Component)((Component)source).transform.parent).gameObject);
}
name[1] = TrimGameObjectName(((Component)source).gameObject);
name[2] = ((Object)clip).name;
return true;
}
private static bool TryGetReplacementClip(string[] name, out SoundReplacementCollection collection, out AudioClip clip)
{
collection = null;
clip = null;
if (name == null)
{
return false;
}
SoundPluginConfig.LoggingLevel value = SoundPluginConfig.LOGGING_LEVEL.Value;
if ((uint)(value - 1) <= 1u)
{
SoundPlugin.logger.LogExtended("Getting replacement for: " + string.Join(":", name));
}
if (!SoundAPI.SoundReplacements.TryGetValue(name[2], out var value2))
{
return false;
}
value2 = (from x in value2
where x.MatchesWith(name)
where x.TestCondition()
select x).ToList();
if (value2.Count == 0)
{
return false;
}
collection = value2[Random.Range(0, value2.Count)];
List<SoundReplacement> list = collection.replacements.Where((SoundReplacement x) => x.TestCondition()).ToList();
if (list.Count == 0)
{
return false;
}
int totalWeight = 0;
list.ForEach(delegate(SoundReplacement replacement)
{
totalWeight += replacement.Weight;
});
int num = Random.Range(0, totalWeight);
int index = 0;
while (num > 0)
{
index = Random.Range(0, list.Count);
num -= Random.Range(1, list[index].Weight);
}
clip = list[index].Clip;
return true;
}
}
[HarmonyPatch(typeof(GameObject))]
internal class GameObjectPatch
{
[HarmonyPostfix]
[HarmonyPatch("AddComponent", new Type[] { typeof(Type) })]
internal static void NewAudioSource(GameObject __instance, ref Component __result)
{
if (__result is AudioSource)
{
Component obj = __result;
AudioSource val = (AudioSource)(object)((obj is AudioSource) ? obj : null);
if (val.playOnAwake)
{
val.Stop();
}
AudioSourceReplaceHelper audioSourceReplaceHelper = __instance.AddComponent<AudioSourceReplaceHelper>();
audioSourceReplaceHelper.source = val;
if (SoundPluginConfig.LOGGING_LEVEL.Value == SoundPluginConfig.LoggingLevel.IM_GOING_TO_LOSE_IT)
{
SoundPlugin.logger.LogLosingIt("Handled AudioSource created via .AddComponent()");
}
}
}
}
[HarmonyPatch(typeof(Logger))]
internal static class LoggerPatch
{
[HarmonyPrefix]
[HarmonyPatch("LogMessage")]
private static void ReenableAndSaveConfigs(object data)
{
if (data is string text && text == "Chainloader startup complete")
{
SoundPlugin.Instance.EnsureSoundsAreLoaded();
}
}
}
[HarmonyPatch(typeof(Object))]
internal static class UnityObjectPatch
{
[HarmonyPostfix]
[HarmonyPatch("Instantiate", new Type[] { typeof(Object) })]
[HarmonyPatch("Instantiate", new Type[]
{
typeof(Object),
typeof(Transform),
typeof(bool)
})]
[HarmonyPatch("Instantiate", new Type[]
{
typeof(Object),
typeof(Vector3),
typeof(Quaternion)
})]
[HarmonyPatch("Instantiate", new Type[]
{
typeof(Object),
typeof(Vector3),
typeof(Quaternion),
typeof(Transform)
})]
internal static void FixPlayOnAwake(ref Object __result)
{
if (__result is GameObject)
{
Object obj = __result;
CheckGameObject((GameObject)(object)((obj is GameObject) ? obj : null));
}
}
private static void CheckGameObject(GameObject @object)
{
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: Expected O, but got Unknown
AudioSourceReplaceHelper audioSourceReplaceHelper = default(AudioSourceReplaceHelper);
if (@object.TryGetComponent<AudioSourceReplaceHelper>(ref audioSourceReplaceHelper))
{
return;
}
AudioSource[] components = @object.GetComponents<AudioSource>();
AudioSource[] array = components;
foreach (AudioSource val in array)
{
if (val.playOnAwake)
{
val.Stop();
}
AudioSourceReplaceHelper audioSourceReplaceHelper2 = @object.AddComponent<AudioSourceReplaceHelper>();
audioSourceReplaceHelper2.source = val;
if (SoundPluginConfig.LOGGING_LEVEL.Value == SoundPluginConfig.LoggingLevel.IM_GOING_TO_LOSE_IT)
{
SoundPlugin.logger.LogLosingIt("Handled AudioSource created via prefab instantiate");
}
}
foreach (Transform item in @object.transform)
{
Transform val2 = item;
CheckGameObject(((Component)val2).gameObject);
}
}
}
}
namespace loaforcsSoundAPI.LethalCompany
{
internal static class LethalCompanyBindings
{
internal static void Bind()
{
SoundAPI.RegisterConditionProvider("LethalCompany:dungeon_name", new DungeonConditionProvider());
SoundAPI.RegisterConditionProvider("LethalCompany:moon_name", new MoonConditionProvider());
SoundAPI.RegisterConditionProvider("LethalCompany:player_health", new PlayerHealthConditionProvider());
SoundAPI.RegisterConditionProvider("LethalCompany:time_of_day", new TimeOfDayConditionProvider());
SoundAPI.RegisterConditionProvider("LethalCompany:player_location", new PlayerLocationTypeConditionProvider());
}
}
}
namespace loaforcsSoundAPI.LethalCompany.Conditions
{
internal class DungeonConditionProvider : ConditionProvider
{
public override bool Evaluate(SoundReplaceGroup group, JObject conditionDef)
{
SoundPlugin.logger.LogExtended("LethalCompany:dungeon_name value: " + ((Object)RoundManager.Instance.dungeonGenerator.Generator.DungeonFlow).name);
return Extensions.Value<string>((IEnumerable<JToken>)conditionDef["value"]) == ((Object)RoundManager.Instance.dungeonGenerator.Generator.DungeonFlow).name;
}
}
internal class MoonConditionProvider : ConditionProvider
{
public override bool Evaluate(SoundReplaceGroup group, JObject conditionDef)
{
SoundPlugin.logger.LogExtended("LethalCompany:moon_name value: " + ((Object)StartOfRound.Instance.currentLevel).name);
return Extensions.Value<string>((IEnumerable<JToken>)conditionDef["value"]) == ((Object)StartOfRound.Instance.currentLevel).name;
}
}
internal class PlayerHealthConditionProvider : ConditionProvider
{
public override bool Evaluate(SoundReplaceGroup group, JObject conditionDef)
{
return EvaluateRangeOperator(GameNetworkManager.Instance.localPlayerController.health, Extensions.Value<string>((IEnumerable<JToken>)conditionDef["value"]));
}
}
internal class PlayerLocationTypeConditionProvider : ConditionProvider
{
public override bool Evaluate(SoundReplaceGroup group, JObject varDef)
{
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0060: Unknown result type (might be due to invalid IL or missing references)
if (GameNetworkManager.Instance.localPlayerController.isPlayerDead)
{
return false;
}
if (GameNetworkManager.Instance.localPlayerController.isInsideFactory)
{
return Extensions.Value<string>((IEnumerable<JToken>)varDef["value"]) == "inside";
}
Bounds bounds = StartOfRound.Instance.shipBounds.bounds;
if (((Bounds)(ref bounds)).Contains(((Component)GameNetworkManager.Instance.localPlayerController).transform.position))
{
return Extensions.Value<string>((IEnumerable<JToken>)varDef["value"]) == "on_ship";
}
return Extensions.Value<string>((IEnumerable<JToken>)varDef["value"]) == "outside";
}
}
internal class TimeOfDayConditionProvider : ConditionProvider
{
public override bool Evaluate(SoundReplaceGroup group, JObject varDef)
{
return Extensions.Value<string>((IEnumerable<JToken>)varDef["value"]) == ((object)(DayMode)(ref TimeOfDay.Instance.dayMode)).ToString().ToLower();
}
}
}
namespace loaforcsSoundAPI.Data
{
public class SoundPack
{
[StructLayout(LayoutKind.Auto)]
[CompilerGenerated]
private struct <AsyncParseReplacer>d__18 : IAsyncStateMachine
{
public int <>1__state;
public AsyncUniTaskMethodBuilder <>t__builder;
public SoundPack <>4__this;
public string replacer;
private Awaiter <>u__1;
private void MoveNext()
{
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
int num = <>1__state;
SoundPack soundPack = <>4__this;
try
{
Awaiter awaiter;
if (num != 0)
{
SwitchToTaskPoolAwaitable val = UniTask.SwitchToTaskPool();
awaiter = ((SwitchToTaskPoolAwaitable)(ref val)).GetAwaiter();
if (!((Awaiter)(ref awaiter)).IsCompleted)
{
num = (<>1__state = 0);
<>u__1 = awaiter;
((AsyncUniTaskMethodBuilder)(ref <>t__builder)).AwaitUnsafeOnCompleted<Awaiter, <AsyncParseReplacer>d__18>(ref awaiter, ref this);
return;
}
}
else
{
awaiter = <>u__1;
<>u__1 = default(Awaiter);
num = (<>1__state = -1);
}
((Awaiter)(ref awaiter)).GetResult();
Thread.Sleep(new Random().Next(100, 500));
soundPack.ParseReplacer(replacer);
}
catch (Exception exception)
{
<>1__state = -2;
((AsyncUniTaskMethodBuilder)(ref <>t__builder)).SetException(exception);
return;
}
<>1__state = -2;
((AsyncUniTaskMethodBuilder)(ref <>t__builder)).SetResult();
}
void IAsyncStateMachine.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
this.MoveNext();
}
[DebuggerHidden]
private void SetStateMachine(IAsyncStateMachine stateMachine)
{
((AsyncUniTaskMethodBuilder)(ref <>t__builder)).SetStateMachine(stateMachine);
}
void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine)
{
//ILSpy generated this explicit interface implementation from .override directive in SetStateMachine
this.SetStateMachine(stateMachine);
}
}
[StructLayout(LayoutKind.Auto)]
[CompilerGenerated]
private struct <AsyncQueueLoad>d__17 : IAsyncStateMachine
{
public int <>1__state;
public AsyncUniTaskMethodBuilder <>t__builder;
public SoundPack <>4__this;
private Stopwatch <loadTime>5__2;
private Awaiter <>u__1;
private Awaiter <>u__2;
private void MoveNext()
{
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_0060: Unknown result type (might be due to invalid IL or missing references)
//IL_010c: Unknown result type (might be due to invalid IL or missing references)
//IL_0111: Unknown result type (might be due to invalid IL or missing references)
//IL_0119: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: 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)
//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: 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)
//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
int num = <>1__state;
SoundPack soundPack = <>4__this;
try
{
Awaiter awaiter;
Awaiter awaiter2;
if (num != 0)
{
if (num == 1)
{
awaiter = <>u__2;
<>u__2 = default(Awaiter);
num = (<>1__state = -1);
goto IL_0128;
}
SwitchToTaskPoolAwaitable val = UniTask.SwitchToTaskPool();
awaiter2 = ((SwitchToTaskPoolAwaitable)(ref val)).GetAwaiter();
if (!((Awaiter)(ref awaiter2)).IsCompleted)
{
num = (<>1__state = 0);
<>u__1 = awaiter2;
((AsyncUniTaskMethodBuilder)(ref <>t__builder)).AwaitUnsafeOnCompleted<Awaiter, <AsyncQueueLoad>d__17>(ref awaiter2, ref this);
return;
}
}
else
{
awaiter2 = <>u__1;
<>u__1 = default(Awaiter);
num = (<>1__state = -1);
}
((Awaiter)(ref awaiter2)).GetResult();
string[] array = Directory.GetFiles(Path.Combine(soundPack.PackPath, "replacers")).Select(Path.GetFileName).ToArray();
<loadTime>5__2 = Stopwatch.StartNew();
UniTask val2 = UniTask.WhenAll(EnumerableAsyncExtensions.Select<string>((IEnumerable<string>)array, (Func<string, UniTask>)soundPack.AsyncParseReplacer));
awaiter = ((UniTask)(ref val2)).GetAwaiter();
if (!((Awaiter)(ref awaiter)).IsCompleted)
{
num = (<>1__state = 1);
<>u__2 = awaiter;
((AsyncUniTaskMethodBuilder)(ref <>t__builder)).AwaitUnsafeOnCompleted<Awaiter, <AsyncQueueLoad>d__17>(ref awaiter, ref this);
return;
}
goto IL_0128;
IL_0128:
((Awaiter)(ref awaiter)).GetResult();
<loadTime>5__2.Stop();
((ManualLogSource)SoundPlugin.logger).LogInfo((object)$"Loaded {soundPack.Name}(sound-loading) in {<loadTime>5__2.ElapsedMilliseconds}ms.");
}
catch (Exception exception)
{
<>1__state = -2;
<loadTime>5__2 = null;
((AsyncUniTaskMethodBuilder)(ref <>t__builder)).SetException(exception);
return;
}
<>1__state = -2;
<loadTime>5__2 = null;
((AsyncUniTaskMethodBuilder)(ref <>t__builder)).SetResult();
}
void IAsyncStateMachine.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
this.MoveNext();
}
[DebuggerHidden]
private void SetStateMachine(IAsyncStateMachine stateMachine)
{
((AsyncUniTaskMethodBuilder)(ref <>t__builder)).SetStateMachine(stateMachine);
}
void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine)
{
//ILSpy generated this explicit interface implementation from .override directive in SetStateMachine
this.SetStateMachine(stateMachine);
}
}
private static List<SoundPack> LoadedSoundPacks = new List<SoundPack>();
private List<SoundReplaceGroup> replaceGroups = new List<SoundReplaceGroup>();
private Dictionary<string, object> Config = new Dictionary<string, object>();
public string Name { get; private set; }
public string PackPath { get; private set; }
public IReadOnlyCollection<SoundReplaceGroup> ReplaceGroups => replaceGroups.AsReadOnly();
public T GetConfigOption<T>(string configID)
{
return ((ConfigEntry<T>)Config[configID]).Value;
}
internal object GetRawConfigOption(string configID)
{
return Config[configID];
}
public SoundPack(string folder)
{
//IL_014d: Unknown result type (might be due to invalid IL or missing references)
//IL_0154: Expected O, but got Unknown
//IL_0172: Unknown result type (might be due to invalid IL or missing references)
//IL_0179: Expected O, but got Unknown
//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
//IL_0214: Expected I4, but got Unknown
//IL_0365: Unknown result type (might be due to invalid IL or missing references)
((ManualLogSource)SoundPlugin.logger).LogDebug((object)("Soundpack `" + folder + "` is being loaded."));
Stopwatch stopwatch = Stopwatch.StartNew();
PackPath = Path.Combine(Paths.PluginPath, folder);
string text = File.ReadAllText(Path.Combine(PackPath, "sound_pack.json"));
object obj = JsonConvert.DeserializeObject(text);
JObject val = (JObject)((obj is JObject) ? obj : null);
Name = (string)val["name"];
if (string.IsNullOrEmpty(Name))
{
((ManualLogSource)SoundPlugin.logger).LogError((object)("`name` is missing or empty in `" + folder + "/sound_pack.json`"));
return;
}
if (!Directory.Exists(Path.Combine(PackPath, "replacers")))
{
((ManualLogSource)SoundPlugin.logger).LogInfo((object)"You've succesfully made a Sound-Pack! Continue with the tutorial to learn how to begin replacing sounds.");
}
else if (val.ContainsKey("load_on_startup"))
{
((ManualLogSource)SoundPlugin.logger).LogWarning((object)("Soundpack '" + Name + "' is using 'load_on_startup' which is deprecated and doesn't do anything! (If you're the creator, you can safely delete that from your sound_pack.json)"));
}
if (val.ContainsKey("config"))
{
Stopwatch stopwatch2 = Stopwatch.StartNew();
ConfigFile val2 = new ConfigFile(Utility.CombinePaths(new string[2]
{
Paths.ConfigPath,
"soundpack." + Name + ".cfg"
}), false, MetadataHelper.GetMetadata((object)SoundPlugin.Instance));
foreach (JProperty item in (IEnumerable<JToken>)val["config"])
{
JProperty val3 = item;
JToken value = val3.Value;
JObject val4 = (JObject)(object)((value is JObject) ? value : null);
if (!val4.ContainsKey("default"))
{
((ManualLogSource)SoundPlugin.logger).LogError((object)("`" + val3.Name + " doesn't have a default value!"));
continue;
}
if (!val4.ContainsKey("description"))
{
((ManualLogSource)SoundPlugin.logger).LogWarning((object)("`" + val3.Name + " doesn't have a description, consider adding one!"));
}
JTokenType type = val4["default"].Type;
switch (type - 6)
{
case 3:
Config.Add(val3.Name, val2.Bind<bool>(val3.Name.Split(":")[0], val3.Name.Split(":")[1], (bool)val4["default"], val4.GetValueOrDefault("description", "[no description was provided]")));
break;
case 2:
Config.Add(val3.Name, val2.Bind<string>(val3.Name.Split(":")[0], val3.Name.Split(":")[1], (string)val4["default"], val4.GetValueOrDefault("description", "[no description was provided]")));
break;
case 0:
case 1:
Config.Add(val3.Name, val2.Bind<float>(val3.Name.Split(":")[0], val3.Name.Split(":")[1], (float)val4["default"], val4.GetValueOrDefault("description", "[no description was provided]")));
break;
default:
((ManualLogSource)SoundPlugin.logger).LogError((object)string.Format("`{0} configtype is currently unsupported! Supported values: bool, float, int, string", val4["default"].Type));
break;
}
}
stopwatch2.Stop();
((ManualLogSource)SoundPlugin.logger).LogInfo((object)$"Loaded {Name}(config) in {stopwatch2.ElapsedMilliseconds}ms.");
}
LoadedSoundPacks.Add(this);
stopwatch.Stop();
((ManualLogSource)SoundPlugin.logger).LogInfo((object)$"Loaded {Name}(init) in {stopwatch.ElapsedMilliseconds}ms.");
}
internal void QueueLoad()
{
if (Directory.Exists(Path.Combine(PackPath, "replacers")))
{
string[] array = Directory.GetFiles(Path.Combine(PackPath, "replacers")).Select(Path.GetFileName).ToArray();
Stopwatch stopwatch = Stopwatch.StartNew();
string[] array2 = array;
foreach (string replacer in array2)
{
ParseReplacer(replacer);
}
stopwatch.Stop();
((ManualLogSource)SoundPlugin.logger).LogInfo((object)$"Loaded {Name}(sound-loading) in {stopwatch.ElapsedMilliseconds}ms.");
}
}
[AsyncStateMachine(typeof(<AsyncQueueLoad>d__17))]
internal UniTask AsyncQueueLoad()
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
<AsyncQueueLoad>d__17 <AsyncQueueLoad>d__ = default(<AsyncQueueLoad>d__17);
<AsyncQueueLoad>d__.<>t__builder = AsyncUniTaskMethodBuilder.Create();
<AsyncQueueLoad>d__.<>4__this = this;
<AsyncQueueLoad>d__.<>1__state = -1;
((AsyncUniTaskMethodBuilder)(ref <AsyncQueueLoad>d__.<>t__builder)).Start<<AsyncQueueLoad>d__17>(ref <AsyncQueueLoad>d__);
return ((AsyncUniTaskMethodBuilder)(ref <AsyncQueueLoad>d__.<>t__builder)).Task;
}
[AsyncStateMachine(typeof(<AsyncParseReplacer>d__18))]
private UniTask AsyncParseReplacer(string replacer)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
<AsyncParseReplacer>d__18 <AsyncParseReplacer>d__ = default(<AsyncParseReplacer>d__18);
<AsyncParseReplacer>d__.<>t__builder = AsyncUniTaskMethodBuilder.Create();
<AsyncParseReplacer>d__.<>4__this = this;
<AsyncParseReplacer>d__.replacer = replacer;
<AsyncParseReplacer>d__.<>1__state = -1;
((AsyncUniTaskMethodBuilder)(ref <AsyncParseReplacer>d__.<>t__builder)).Start<<AsyncParseReplacer>d__18>(ref <AsyncParseReplacer>d__);
return ((AsyncUniTaskMethodBuilder)(ref <AsyncParseReplacer>d__.<>t__builder)).Task;
}
private void ParseReplacer(string replacer)
{
string path = Path.Combine(PackPath, "replacers", replacer);
((ManualLogSource)SoundPlugin.logger).LogDebug((object)("Parsing `" + Path.GetFileName(path) + "` as a sound replacer"));
object obj = JsonConvert.DeserializeObject(File.ReadAllText(path));
JObject data = (JObject)((obj is JObject) ? obj : null);
if (SoundPluginConfig.LOGGING_LEVEL.Value == SoundPluginConfig.LoggingLevel.IM_GOING_TO_LOSE_IT)
{
SoundPlugin.logger.LogLosingIt("JSON data desrialized!");
}
new SoundReplaceGroup(this, data);
}
}
public class SoundReplaceGroup : Conditonal
{
public SoundPack pack { get; private set; }
internal JObject RandomSettings { get; private set; }
internal bool UpdateEveryFrame { get; private set; }
internal bool IgnoreLooping { get; private set; }
public SoundReplaceGroup(SoundPack pack, JObject data)
{
//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
//IL_00c3: Expected O, but got Unknown
this.pack = pack;
if (data.ContainsKey("condition"))
{
JToken obj = data["condition"];
Setup(this, (JObject)(object)((obj is JObject) ? obj : null));
if ((string)data["condition"][(object)"type"] == "config" && SoundPluginConfig.SKIP_LOADING_UNUSED_SOUNDS.Value && !TestCondition())
{
if (SoundPluginConfig.LOGGING_LEVEL.Value == SoundPluginConfig.LoggingLevel.IM_GOING_TO_LOSE_IT)
{
SoundPlugin.logger.LogLosingIt("Skipping loading SoundReplaceGroup because the config is disabled..");
}
return;
}
}
if (SoundPluginConfig.LOGGING_LEVEL.Value == SoundPluginConfig.LoggingLevel.IM_GOING_TO_LOSE_IT)
{
SoundPlugin.logger.LogLosingIt("Loading audio");
}
foreach (JObject item in (IEnumerable<JToken>)data["replacements"])
{
JObject data2 = item;
new SoundReplacementCollection(this, data2);
}
if (SoundPluginConfig.LOGGING_LEVEL.Value == SoundPluginConfig.LoggingLevel.IM_GOING_TO_LOSE_IT)
{
SoundPlugin.logger.LogLosingIt("Done loading audio");
}
if (data.ContainsKey("update_every_frame"))
{
UpdateEveryFrame = (bool)data["update_every_frame"];
}
if (data.ContainsKey("ignore_looping"))
{
UpdateEveryFrame = (bool)data["ignore_looping"];
}
if (data.ContainsKey("randomnesss"))
{
((ManualLogSource)SoundPlugin.logger).LogWarning((object)("Found deprecated value `randomness` for pack `" + pack.Name + "`"));
}
}
}
internal class SoundReplacementCollection : Conditonal
{
internal readonly List<SoundReplacement> replacements = new List<SoundReplacement>();
private readonly List<string> matchers = new List<string>();
internal readonly SoundReplaceGroup group;
internal SoundReplacementCollection(SoundReplaceGroup group, JObject data)
{
//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
//IL_00d5: Expected O, but got Unknown
//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
//IL_00e8: Invalid comparison between Unknown and I4
this.group = group;
JToken val = default(JToken);
if (data.TryGetValue("condition", ref val))
{
Setup(group, (JObject)(object)((val is JObject) ? val : null));
}
if (((object)data["matches"]).GetType() == typeof(JValue))
{
RegisterWithMatch((string)data["matches"]);
}
else
{
foreach (JToken item in (IEnumerable<JToken>)data["matches"])
{
string matchString = (string)item;
RegisterWithMatch(matchString);
}
}
foreach (JObject item2 in (IEnumerable<JToken>)data["sounds"])
{
JObject val2 = item2;
if ((int)val2["sound"].Type == 10)
{
SoundPlugin.logger.LogExtended("Adding null sound, will remove the sound when chosen");
replacements.Add(new SoundReplacement(group, val2)
{
Weight = val2.GetValueOrDefault("weight", 1)
});
continue;
}
SoundReplacement soundReplacement = new SoundReplacement(group, val2)
{
Weight = val2.GetValueOrDefault("weight", 1)
};
SoundLoader.GetAudioClip(group.pack.PackPath, Path.GetDirectoryName((string)val2["sound"]), Path.GetFileName((string)val2["sound"]), out var clip);
if ((Object)(object)clip == (Object)null)
{
((ManualLogSource)SoundPlugin.logger).LogError((object)"Failed to get audio clip, check above more detailed error");
continue;
}
soundReplacement.Clip = clip;
replacements.Add(soundReplacement);
}
}
internal bool MatchesWith(string[] a)
{
foreach (string matcher in matchers)
{
if (SoundAPI.MatchStrings(a, matcher))
{
return true;
}
}
return false;
}
private void RegisterWithMatch(string matchString)
{
string key = SoundAPI.FormatMatchString(matchString).Split(":")[2];
List<SoundReplacementCollection> valueOrDefault = SoundAPI.SoundReplacements.GetValueOrDefault(key, new List<SoundReplacementCollection>());
valueOrDefault.Add(this);
matchers.Add(SoundAPI.FormatMatchString(matchString));
SoundAPI.SoundReplacements[key] = valueOrDefault;
}
public override bool TestCondition()
{
if (base.TestCondition())
{
return group.TestCondition();
}
return false;
}
}
internal class SoundReplacement : Conditonal
{
public int Weight = 1;
public AudioClip Clip { get; set; }
public SoundReplacement(SoundReplaceGroup group, JObject data)
{
if (data.ContainsKey("condition"))
{
JToken obj = data["condition"];
Setup(group, (JObject)(object)((obj is JObject) ? obj : null));
}
}
}
}
namespace loaforcsSoundAPI.Behaviours
{
public class AudioSourceReplaceHelper : MonoBehaviour
{
internal AudioSource source;
internal SoundReplacementCollection replacedWith;
internal static Dictionary<AudioSource, AudioSourceReplaceHelper> helpers = new Dictionary<AudioSource, AudioSourceReplaceHelper>();
private bool _loop;
internal bool _isPlaying;
public bool DisableReplacing { get; private set; }
public bool Loop
{
get
{
return _loop;
}
set
{
if (SoundPluginConfig.LOGGING_LEVEL.Value == SoundPluginConfig.LoggingLevel.IM_GOING_TO_LOSE_IT)
{
SoundPlugin.logger.LogLosingIt($"AudioSourceReplaceHelper looping is now at: {value}");
}
_loop = value;
}
}
private void Start()
{
if ((Object)(object)source == (Object)null)
{
((ManualLogSource)SoundPlugin.logger).LogWarning((object)("AudioSource (on gameobject: " + ((Object)((Component)this).gameObject).name + ") became null between the OnSceneLoaded callback and Start."));
return;
}
string text = (((Object)(object)source.clip == (Object)null) ? "null" : ((Object)source.clip).name);
if (SoundPluginConfig.LOGGING_LEVEL.Value == SoundPluginConfig.LoggingLevel.IM_GOING_TO_LOSE_IT)
{
SoundPlugin.logger.LogLosingIt("AudioSourceReplaceHelper.Start(), gameObject: " + ((Object)((Component)this).gameObject).name + ", audioClip.name: " + text);
}
if (source.playOnAwake)
{
if (((Behaviour)source).enabled)
{
if ((Object)(object)source.clip != (Object)null)
{
source.Play();
if (SoundPluginConfig.LOGGING_LEVEL.Value == SoundPluginConfig.LoggingLevel.IM_GOING_TO_LOSE_IT)
{
SoundPlugin.logger.LogLosingIt(((Object)((Component)this).gameObject).name + ":" + text + " calling source.Play() because its playOnAwake and enabled.");
}
_isPlaying = true;
}
if (SoundPluginConfig.LOGGING_LEVEL.Value == SoundPluginConfig.LoggingLevel.IM_GOING_TO_LOSE_IT)
{
SoundPlugin.logger.LogLosingIt(((Object)((Component)this).gameObject).name + ":" + text + " play on awake + enabled + null audio clip. WHYYYYYYY");
}
}
else if (SoundPluginConfig.LOGGING_LEVEL.Value == SoundPluginConfig.LoggingLevel.IM_GOING_TO_LOSE_IT)
{
SoundPlugin.logger.LogLosingIt(((Object)((Component)this).gameObject).name + ":" + text + " not calling Play() because its playOnAwake but not enabled.");
}
}
if (SoundPluginConfig.EXPERIMENTAL_HANDLE_LOOPING_SOUNDS.Value)
{
Loop = source.loop;
source.loop = false;
if (SoundPluginConfig.LOGGING_LEVEL.Value == SoundPluginConfig.LoggingLevel.IM_GOING_TO_LOSE_IT)
{
SoundPlugin.logger.LogLosingIt($"{((Object)((Component)this).gameObject).name}:{text}, Looping? {Loop}");
}
}
helpers[source] = this;
}
private void OnEnable()
{
if (!((Object)(object)source == (Object)null))
{
helpers[source] = this;
}
}
private void OnDestroy()
{
if (!((Object)(object)source == (Object)null) && helpers.ContainsKey(source))
{
helpers.Remove(source);
}
}
private void HandleLoopingSounds()
{
if (!_isPlaying)
{
return;
}
if ((Object)(object)source.clip == (Object)null)
{
if (SoundPluginConfig.LOGGING_LEVEL.Value == SoundPluginConfig.LoggingLevel.IM_GOING_TO_LOSE_IT)
{
SoundPlugin.logger.LogLosingIt(((Object)((Component)this).gameObject).name + ":" + (((Object)(object)source.clip == (Object)null) ? "null" : ((Object)source.clip).name) + " has a null clipp!!!!!");
}
_isPlaying = false;
}
else
{
if (source.isPlaying)
{
return;
}
if (Loop)
{
source.Play();
if (SoundPluginConfig.LOGGING_LEVEL.Value == SoundPluginConfig.LoggingLevel.IM_GOING_TO_LOSE_IT)
{
SoundPlugin.logger.LogLosingIt(((Object)((Component)this).gameObject).name + ":" + (((Object)(object)source.clip == (Object)null) ? "null" : ((Object)source.clip).name) + " succesfully looped!");
}
}
else
{
_isPlaying = false;
}
}
}
private void LateUpdate()
{
if ((Object)(object)source == (Object)null || !((Behaviour)source).enabled)
{
return;
}
if (SoundPluginConfig.EXPERIMENTAL_HANDLE_LOOPING_SOUNDS.Value)
{
HandleLoopingSounds();
}
if (replacedWith == null)
{
return;
}
DisableReplacing = replacedWith.group.UpdateEveryFrame || replacedWith.group.IgnoreLooping;
if (!replacedWith.group.UpdateEveryFrame)
{
return;
}
float time = source.time;
SoundReplacement soundReplacement = replacedWith.replacements.Where((SoundReplacement x) => x.TestCondition()).ToList()[0];
if (!((Object)(object)soundReplacement.Clip == (Object)(object)source.clip))
{
source.clip = soundReplacement.Clip;
source.Play();
source.time = time;
if (!source.isPlaying)
{
SoundPlugin.logger.LogExtended("Sound ended, resetting update_every_frame");
DisableReplacing = false;
replacedWith = null;
}
}
}
}
}
namespace loaforcsSoundAPI.API
{
public abstract class AudioFormatProvider
{
public abstract AudioClip LoadAudioClip(string path);
protected AudioClip LoadFromUWR(string path, AudioType type)
{
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Invalid comparison between Unknown and I4
AudioClip result = null;
UnityWebRequest audioClip = UnityWebRequestMultimedia.GetAudioClip(path, type);
try
{
audioClip.SendWebRequest();
try
{
while (!audioClip.isDone)
{
}
if ((int)audioClip.result != 1)
{
((ManualLogSource)SoundPlugin.logger).LogError((object)"============");
((ManualLogSource)SoundPlugin.logger).LogError((object)("UnityWebRequest failed while trying to get " + path + ". Full error below"));
((ManualLogSource)SoundPlugin.logger).LogError((object)audioClip.error);
((ManualLogSource)SoundPlugin.logger).LogError((object)"============");
}
else
{
result = DownloadHandlerAudioClip.GetContent(audioClip);
}
}
catch (Exception ex)
{
((ManualLogSource)SoundPlugin.logger).LogError((object)(ex.Message + ", " + ex.StackTrace));
}
}
finally
{
((IDisposable)audioClip)?.Dispose();
}
return result;
}
}
public abstract class ConditionProvider
{
public abstract bool Evaluate(SoundReplaceGroup group, JObject conditionDef);
public bool EvaluateRangeOperator(JToken number, string condition)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Invalid comparison between Unknown and I4
if ((int)number.Type == 7)
{
return EvaluateRangeOperator(Extensions.Value<float>((IEnumerable<JToken>)number), condition);
}
return EvaluateRangeOperator(Extensions.Value<int>((IEnumerable<JToken>)number), condition);
}
public bool EvaluateRangeOperator(int number, string condition)
{
return EvaluateRangeOperator((double)number, condition);
}
public bool EvaluateRangeOperator(float number, string condition)
{
return EvaluateRangeOperator((double)number, condition);
}
public bool EvaluateRangeOperator(double number, string condition)
{
string[] array = condition.Split("..");
if (array.Length == 1)
{
if (double.TryParse(array[0], out var result))
{
return number == result;
}
return false;
}
if (array.Length == 2)
{
double result2;
if (array[0] == "")
{
result2 = double.MinValue;
}
else if (!double.TryParse(array[0], out result2))
{
return false;
}
double result3;
if (array[1] == "")
{
result3 = double.MaxValue;
}
else if (!double.TryParse(array[1], out result3))
{
return false;
}
if (number >= result2)
{
return number <= result3;
}
return false;
}
return false;
}
}
public abstract class Conditonal
{
private ConditionProvider GroupCondition;
private SoundReplaceGroup group;
internal JObject ConditionSettings { get; private set; }
protected void Setup(SoundReplaceGroup group, JObject settings)
{
this.group = group;
if (settings != null)
{
ConditionSettings = settings;
GroupCondition = SoundAPI.ConditionProviders[(string)ConditionSettings["type"]];
}
}
public virtual bool TestCondition()
{
if (GroupCondition == null)
{
return true;
}
return GroupCondition.Evaluate(group, ConditionSettings);
}
}
public static class SoundAPI
{
internal static Dictionary<string, AudioFormatProvider> FileFormats = new Dictionary<string, AudioFormatProvider>();
internal static Dictionary<string, ConditionProvider> ConditionProviders = new Dictionary<string, ConditionProvider>();
internal static ConcurrentDictionary<string, List<SoundReplacementCollection>> SoundReplacements = new ConcurrentDictionary<string, List<SoundReplacementCollection>>();
public static void RegisterAudioFormatProvider(string extension, AudioFormatProvider provider)
{
FileFormats.Add(extension, provider);
}
public static void RegisterConditionProvider(string extension, ConditionProvider provider)
{
ConditionProviders.Add(extension, provider);
}
public static string FormatMatchString(string input)
{
if (input.Split(":").Length == 2)
{
input = "*:" + input;
}
return input;
}
public static bool MatchStrings(string[] a, string b)
{
string[] array = b.Split(":");
if (array[0] != "*" && array[0] != a[0])
{
return false;
}
if (array[1] != "*" && array[1] != a[1])
{
return false;
}
return a[2] == array[2];
}
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}