Decompiled source of Dialogue Audio Addon v1.0.2

DialogueAudioAddon.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Localizer;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("OutwardModTemplate")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("OutwardModTemplate")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("c5450fe0-edcf-483f-b9ea-4b1ef9d36da7")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace SideLoader.DialogueAudioAddon
{
	internal static class AudioFormatsBridge
	{
		private static Func<string, bool> s_contains;

		private static Action<string> s_prefetch;

		private static Func<string, AudioClip> s_getLoaded;

		private static Func<string, AudioClip> s_getNow;

		private static bool s_bound;

		public static bool Available { get; private set; }

		private static void Bind()
		{
			if (s_bound)
			{
				return;
			}
			s_bound = true;
			Type type = Type.GetType("Tchernobill.AudioFormats.LazyAudioClips, AudioFormats", throwOnError: false);
			if (type == null)
			{
				return;
			}
			try
			{
				s_contains = (Func<string, bool>)Delegate.CreateDelegate(typeof(Func<string, bool>), type.GetMethod("Contains", BindingFlags.Static | BindingFlags.Public));
				s_prefetch = (Action<string>)Delegate.CreateDelegate(typeof(Action<string>), type.GetMethod("Prefetch", BindingFlags.Static | BindingFlags.Public));
				s_getLoaded = (Func<string, AudioClip>)Delegate.CreateDelegate(typeof(Func<string, AudioClip>), type.GetMethod("GetLoaded", BindingFlags.Static | BindingFlags.Public));
				s_getNow = (Func<string, AudioClip>)Delegate.CreateDelegate(typeof(Func<string, AudioClip>), type.GetMethod("GetNow", BindingFlags.Static | BindingFlags.Public));
				Available = true;
			}
			catch (Exception ex)
			{
				SL.LogWarning("[DialogueAudioAddon] Audio Formats is installed but its lazy clip index could not be reached (" + ex.Message + "). Large packs will keep loading up front.");
			}
		}

		public static bool Knows(string clipName)
		{
			Bind();
			return Available && s_contains(clipName);
		}

		public static void Prefetch(string clipName)
		{
			Bind();
			if (Available)
			{
				s_prefetch(clipName);
			}
		}

		public static AudioClip GetLoaded(string clipName)
		{
			Bind();
			return Available ? s_getLoaded(clipName) : null;
		}

		public static AudioClip GetNow(string clipName)
		{
			Bind();
			return Available ? s_getNow(clipName) : null;
		}
	}
	public static class DialogueAudioAddonConfig
	{
		public static ConfigEntry<bool> DebugLogClipNames;

		public static void Bind(ConfigFile config)
		{
			DebugLogClipNames = config.Bind<bool>("Debug", "LogDialogueClipNames", false, "If active, log the exact name of each dialogue clip played (useful to find the right sound file name to use.).");
		}
	}
	[BepInPlugin("Tchernobill.DialogueAudioAddon", "Dialogue Audio Addon", "1.0.2")]
	public class DialogueAudioAddonPlugin : BaseUnityPlugin
	{
		public const string GUID = "Tchernobill.DialogueAudioAddon";

		public const string NAME = "Dialogue Audio Addon";

		public const string VERSION = "1.0.2";

		public static DialogueAudioAddonPlugin Instance { get; private set; }

		private void Awake()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			Instance = this;
			DialogueAudioAddonConfig.Bind(((BaseUnityPlugin)this).Config);
			Harmony val = new Harmony("Tchernobill.DialogueAudioAddon");
			val.PatchAll();
		}
	}
	public static class DialogueAudioRegistry
	{
		private static readonly Dictionary<string, AudioClip> Clips = new Dictionary<string, AudioClip>();

		public static void Register(string clipName, AudioClip clip)
		{
			if (!string.IsNullOrEmpty(clipName) && !((Object)(object)clip == (Object)null))
			{
				if (Clips.ContainsKey(clipName) && DialogueAudioAddonConfig.DebugLogClipNames.Value)
				{
					SL.Log("[DialogueAudioAddon] Remplacement override for '" + clipName + "' (multiple replacements!).");
				}
				Clips[clipName] = clip;
				if (DialogueAudioAddonConfig.DebugLogClipNames.Value)
				{
					SL.Log("[DialogueAudioAddon] Dialogue clip stored : '" + clipName + "'");
				}
			}
		}

		public static bool TryGetReplacement(string originalClipName, out AudioClip replacement, bool decodeNow = false)
		{
			if (Clips.TryGetValue(originalClipName, out replacement))
			{
				return true;
			}
			replacement = AudioFormatsBridge.GetLoaded(originalClipName);
			if ((Object)(object)replacement != (Object)null)
			{
				return true;
			}
			if (!decodeNow || !AudioFormatsBridge.Knows(originalClipName))
			{
				return false;
			}
			replacement = AudioFormatsBridge.GetNow(originalClipName);
			if ((Object)(object)replacement != (Object)null)
			{
				SL.Log("[DialogueAudioAddon] Decoded '" + originalClipName + "' on the spot: no prefetch covered that name.");
			}
			return (Object)(object)replacement != (Object)null;
		}

		public static void Prefetch(string clipName)
		{
			if (!string.IsNullOrEmpty(clipName) && !Clips.ContainsKey(clipName))
			{
				AudioFormatsBridge.Prefetch(clipName);
			}
		}

		public static bool HasReplacement(string originalClipName)
		{
			return Clips.ContainsKey(originalClipName) || AudioFormatsBridge.Knows(originalClipName);
		}
	}
	public static class PendingDialogueAudio
	{
		public static string ClipName { get; private set; }

		public static bool HasClipName => !string.IsNullOrEmpty(ClipName);

		public static void Set(string clipName)
		{
			ClipName = clipName;
		}

		public static void Clear()
		{
			ClipName = null;
		}

		public static bool Consume(out string clipName, out AudioClip clip)
		{
			clipName = ClipName;
			Clear();
			clip = null;
			if (string.IsNullOrEmpty(clipName))
			{
				return false;
			}
			DialogueAudioRegistry.TryGetReplacement(clipName, out clip, decodeNow: true);
			return (Object)(object)clip != (Object)null;
		}
	}
}
namespace SideLoader.DialogueAudioAddon.Patches
{
	[HarmonyPatch(typeof(CustomAudio), "FinalizeAudioClip")]
	public static class Patch_CustomAudio_FinalizeAudioClip
	{
		[HarmonyPostfix]
		public static void Postfix(string name, AudioClip __result)
		{
			if ((Object)(object)__result != (Object)null)
			{
				DialogueAudioRegistry.Register(name, __result);
			}
		}
	}
	[HarmonyPatch(typeof(DialogueAudio), "SetSound")]
	public static class Patch_DialogueAudio_SetSound
	{
		[HarmonyPrefix]
		public static void Prefix(ref AudioClip _clip)
		{
			if ((Object)(object)_clip == (Object)null)
			{
				return;
			}
			if (DialogueAudioAddonConfig.DebugLogClipNames.Value)
			{
				SL.Log("[DialogueAudioAddon] Reading dialogue : '" + ((Object)_clip).name + "'");
			}
			string clipName;
			AudioClip clip;
			if (DialogueAudioRegistry.TryGetReplacement(((Object)_clip).name, out var replacement, decodeNow: true))
			{
				if (DialogueAudioAddonConfig.DebugLogClipNames.Value)
				{
					SL.Log("[DialogueAudioAddon] Replacing dialogue '" + ((Object)_clip).name + "'.");
				}
				_clip = replacement;
				PendingDialogueAudio.Clear();
			}
			else if (PendingDialogueAudio.Consume(out clipName, out clip))
			{
				if (DialogueAudioAddonConfig.DebugLogClipNames.Value)
				{
					SL.Log("[DialogueAudioAddon] Replacing bark '" + ((Object)_clip).name + "' with pending '" + clipName + "'.");
				}
				_clip = clip;
			}
		}
	}
	[HarmonyPatch(typeof(SNPCManager), "SNPCTalking", new Type[]
	{
		typeof(Character),
		typeof(string),
		typeof(DialogueLocalization),
		typeof(bool)
	})]
	public class Patch_SNPCManager_SNPCTalking
	{
		private static int s_lineToken;

		private const int MaxWaitFrames = 60;

		[HarmonyPrefix]
		public static void Prefix(ref SNPCManager __instance, ref Character _player, ref string _npcLocKey, ref DialogueLocalization _dialogueData, ref bool _isVinicity)
		{
			PendingDialogueAudio.Clear();
			s_lineToken++;
			if (_dialogueData == null || string.IsNullOrEmpty(_dialogueData.Key))
			{
				return;
			}
			string text = $"dlg_&{_dialogueData.Key}";
			DialogueAudioRegistry.Prefetch(text);
			if (!string.IsNullOrEmpty(_dialogueData.UniqueAudioName) && _dialogueData.UniqueAudioName.Length > 1)
			{
				DialogueAudioRegistry.Prefetch(_dialogueData.UniqueAudioName);
				DialogueAudioRegistry.Prefetch($"dlg_&{_dialogueData.UniqueAudioName}");
			}
			else
			{
				if (!DialogueAudioRegistry.HasReplacement(text))
				{
					return;
				}
				if (_dialogueData.EmoteTags != null && _dialogueData.EmoteTags.Length != 0)
				{
					PendingDialogueAudio.Set(text);
					if (DialogueAudioAddonConfig.DebugLogClipNames.Value)
					{
						SL.Log("[DialogueAudioAddon] Pending replacement '" + text + "' for '" + _npcLocKey + "' (bark expected).");
					}
				}
				else if ((Object)(object)__instance.m_diagAudio != (Object)null)
				{
					PlayWhenReady(__instance.m_diagAudio, text, _npcLocKey);
				}
			}
		}

		private static void PlayWhenReady(DialogueAudio diagAudio, string clipName, string npcLocKey)
		{
			if (DialogueAudioRegistry.TryGetReplacement(clipName, out var replacement))
			{
				Play(diagAudio, replacement, clipName, npcLocKey);
				return;
			}
			DialogueAudioAddonPlugin instance = DialogueAudioAddonPlugin.Instance;
			if (!Object.op_Implicit((Object)(object)instance))
			{
				if (DialogueAudioRegistry.TryGetReplacement(clipName, out var replacement2, decodeNow: true))
				{
					Play(diagAudio, replacement2, clipName, npcLocKey);
				}
			}
			else
			{
				((MonoBehaviour)instance).StartCoroutine(PlayWhenReadyCoroutine(diagAudio, clipName, npcLocKey, s_lineToken));
			}
		}

		private static IEnumerator PlayWhenReadyCoroutine(DialogueAudio diagAudio, string clipName, string npcLocKey, int token)
		{
			for (int frame = 0; frame < 60; frame++)
			{
				yield return null;
				if (token != s_lineToken || !Object.op_Implicit((Object)(object)diagAudio))
				{
					yield break;
				}
				if (DialogueAudioRegistry.TryGetReplacement(clipName, out var clip))
				{
					Play(diagAudio, clip, clipName, npcLocKey);
					yield break;
				}
				clip = null;
			}
			if (token == s_lineToken && Object.op_Implicit((Object)(object)diagAudio) && DialogueAudioRegistry.TryGetReplacement(clipName, out var late, decodeNow: true))
			{
				Play(diagAudio, late, clipName, npcLocKey);
			}
		}

		private static void Play(DialogueAudio diagAudio, AudioClip clip, string clipName, string npcLocKey)
		{
			diagAudio.SetSound(clip);
			diagAudio.Play();
			if (DialogueAudioAddonConfig.DebugLogClipNames.Value)
			{
				SL.Log("[DialogueAudioAddon] Played '" + clipName + "' directly for '" + npcLocKey + "' (no game audio expected).");
			}
		}
	}
	[HarmonyPatch(typeof(VicinityDialoguePanel), "ShowDialogue")]
	public class Patch_VicinityDialoguePanel_ShowDialogue
	{
		[HarmonyPrefix]
		public static void Prefix(ref VicinityDialoguePanel __instance, ref string _instigatorUID, ref string _dialogueLocKey, ref string _npcLocKey)
		{
			if (DialogueAudioAddonConfig.DebugLogClipNames.Value)
			{
				SL.Log("[DialogueAudioAddon] VicinityDialoguePanel.ShowDialogue '" + _instigatorUID + "' '" + _dialogueLocKey + "' '" + _npcLocKey + "'.");
			}
		}
	}
}