Decompiled source of SCP087B Death Music Replacement v1.1.0

BepInEx/plugins/CustomSounds.dll

Decompiled 11 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using CustomSounds.Networking;
using CustomSounds.Patches;
using GameNetcodeStuff;
using HarmonyLib;
using LCSoundTool;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.InputSystem;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("CustomSounds")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("CustomSounds")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("9e086160-a7fd-4721-ba09-3e8534cb7011")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
internal class <Module>
{
	static <Module>()
	{
	}
}
namespace CustomSounds
{
	[BepInPlugin("CustomSounds", "Custom Sounds", "2.2.0")]
	public class Plugin : BaseUnityPlugin
	{
		private const string PLUGIN_GUID = "CustomSounds";

		private const string PLUGIN_NAME = "Custom Sounds";

		private const string PLUGIN_VERSION = "2.2.0";

		public static Plugin Instance;

		internal ManualLogSource logger;

		private Harmony harmony;

		public HashSet<string> currentSounds = new HashSet<string>();

		public HashSet<string> oldSounds = new HashSet<string>();

		public HashSet<string> modifiedSounds = new HashSet<string>();

		public Dictionary<string, string> soundHashes = new Dictionary<string, string>();

		public Dictionary<string, string> soundPacks = new Dictionary<string, string>();

		public static ConfigEntry<KeyboardShortcut> AcceptSyncKey;

		public ConfigEntry<bool> configUseNetworking;

		private Dictionary<string, string> customSoundNames = new Dictionary<string, string>();

		public static bool Initialized { get; private set; }

		private void Awake()
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Expected O, but got Unknown
			if (!((Object)(object)Instance == (Object)null))
			{
				return;
			}
			Instance = this;
			logger = Logger.CreateLogSource("CustomSounds");
			configUseNetworking = ((BaseUnityPlugin)this).Config.Bind<bool>("Experimental", "EnableNetworking", true, "Whether or not to use the networking built into this plugin. If set to true everyone in the lobby needs CustomSounds to join and also \"EnableNetworking\" set to true.");
			AcceptSyncKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Experimental", "AcceptSyncKey", new KeyboardShortcut((KeyCode)289, Array.Empty<KeyCode>()), "Key to accept audio sync.");
			harmony = new Harmony("CustomSounds");
			harmony.PatchAll(typeof(TerminalParsePlayerSentencePatch));
			harmony.PatchAll(typeof(RemapKeyPatch));
			if (configUseNetworking.Value)
			{
				harmony.PatchAll(typeof(NetworkObjectManager));
			}
			modifiedSounds = new HashSet<string>();
			string customSoundsFolderPath = GetCustomSoundsFolderPath();
			if (!Directory.Exists(customSoundsFolderPath))
			{
				logger.LogInfo((object)"\"CustomSounds\" folder not found. Creating it now.");
				Directory.CreateDirectory(customSoundsFolderPath);
			}
			string path = Path.Combine(Paths.BepInExConfigPath);
			try
			{
				List<string> list = File.ReadAllLines(path).ToList();
				int num = list.FindIndex((string line) => line.StartsWith("HideManagerGameObject"));
				if (num != -1)
				{
					logger.LogInfo((object)"\"hideManagerGameObject\" value not correctly set. Fixing it now.");
					list[num] = "HideManagerGameObject = true";
				}
				File.WriteAllLines(path, list);
			}
			catch (Exception ex)
			{
				logger.LogError((object)("Error modifying config file: " + ex.Message));
			}
			Type[] types = Assembly.GetExecutingAssembly().GetTypes();
			Type[] array = types;
			foreach (Type type in array)
			{
				MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic);
				MethodInfo[] array2 = methods;
				foreach (MethodInfo methodInfo in array2)
				{
					object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false);
					if (customAttributes.Length != 0)
					{
						methodInfo.Invoke(null, null);
					}
				}
			}
			logger.LogInfo((object)"Plugin CustomSounds is loaded!");
		}

		internal void Start()
		{
			Initialize();
		}

		internal void OnDestroy()
		{
			Initialize();
		}

		internal void Initialize()
		{
			if (!Initialized)
			{
				Initialized = true;
				DeleteTempFolder();
				ReloadSounds(serverSync: false, isTemporarySync: false);
			}
		}

		private void OnApplicationQuit()
		{
			DeleteTempFolder();
		}

		public GameObject LoadNetworkPrefabFromEmbeddedResource()
		{
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			string name = "CustomSounds.Bundle.audionetworkhandler";
			using Stream stream = executingAssembly.GetManifestResourceStream(name);
			if (stream == null)
			{
				Debug.LogError((object)"Asset bundle not found in embedded resources.");
				return null;
			}
			byte[] array = new byte[stream.Length];
			stream.Read(array, 0, array.Length);
			AssetBundle val = AssetBundle.LoadFromMemory(array);
			if ((Object)(object)val == (Object)null)
			{
				Debug.LogError((object)"Failed to load AssetBundle from memory.");
				return null;
			}
			return val.LoadAsset<GameObject>("audionetworkhandler");
		}

		public void DeleteTempFolder()
		{
			string customSoundsTempFolderPath = GetCustomSoundsTempFolderPath();
			if (Directory.Exists(customSoundsTempFolderPath))
			{
				try
				{
					Directory.Delete(customSoundsTempFolderPath, recursive: true);
					logger.LogInfo((object)"Temporary-Sync folder deleted successfully.");
				}
				catch (Exception ex)
				{
					logger.LogError((object)("Error deleting Temporary-Sync folder: " + ex.Message));
				}
			}
		}

		public string GetCustomSoundsFolderPath()
		{
			return Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)Instance).Info.Location), "CustomSounds");
		}

		public string GetCustomSoundsTempFolderPath()
		{
			return Path.Combine(GetCustomSoundsFolderPath(), "Temporary-Sync");
		}

		public static byte[] SerializeWavToBytes(string filePath)
		{
			try
			{
				return File.ReadAllBytes(filePath);
			}
			catch (Exception ex)
			{
				Console.WriteLine("An error occurred: " + ex.Message);
				return null;
			}
		}

		public static string SerializeWavToBase64(string filePath)
		{
			try
			{
				byte[] inArray = File.ReadAllBytes(filePath);
				return Convert.ToBase64String(inArray);
			}
			catch (Exception ex)
			{
				Console.WriteLine("An error occurred: " + ex.Message);
				return null;
			}
		}

		public static void DeserializeBytesToWav(byte[] byteArray, string audioFileName)
		{
			try
			{
				string customSoundsTempFolderPath = Instance.GetCustomSoundsTempFolderPath();
				if (!Directory.Exists(customSoundsTempFolderPath))
				{
					Instance.logger.LogInfo((object)"\"Temporary-Sync\" folder not found. Creating it now.");
					Directory.CreateDirectory(customSoundsTempFolderPath);
				}
				File.WriteAllBytes(Path.Combine(customSoundsTempFolderPath, audioFileName), byteArray);
				Console.WriteLine("WAV file \"" + audioFileName + "\" created!");
			}
			catch (Exception ex)
			{
				Console.WriteLine("An error occurred: " + ex.Message);
			}
		}

		public static List<byte[]> SplitAudioData(byte[] audioData, int maxSegmentSize = 62000)
		{
			List<byte[]> list = new List<byte[]>();
			for (int i = 0; i < audioData.Length; i += maxSegmentSize)
			{
				int num = Mathf.Min(maxSegmentSize, audioData.Length - i);
				byte[] array = new byte[num];
				Array.Copy(audioData, i, array, 0, num);
				list.Add(array);
			}
			return list;
		}

		public static byte[] CombineAudioSegments(List<byte[]> segments)
		{
			List<byte> list = new List<byte>();
			foreach (byte[] segment in segments)
			{
				list.AddRange(segment);
			}
			return list.ToArray();
		}

		public void ShowCustomTip(string header, string body, bool isWarning)
		{
			HUDManager.Instance.DisplayTip(header, body, isWarning, false, "LC_Tip1");
		}

		public void ForceUnsync()
		{
			DeleteTempFolder();
			ReloadSounds(serverSync: false, isTemporarySync: false);
		}

		public void RevertSounds()
		{
			HashSet<string> hashSet = new HashSet<string>();
			foreach (string currentSound in currentSounds)
			{
				string text = currentSound;
				if (currentSound.Contains("-"))
				{
					text = currentSound.Substring(0, currentSound.IndexOf("-"));
				}
				if (!hashSet.Contains(text))
				{
					logger.LogInfo((object)(text + " restored."));
					SoundTool.RestoreAudioClip(text);
					hashSet.Add(text);
				}
			}
			logger.LogInfo((object)"Original game sounds restored.");
		}

		public static string CalculateMD5(string filename)
		{
			using MD5 mD = MD5.Create();
			using FileStream inputStream = File.OpenRead(filename);
			byte[] array = mD.ComputeHash(inputStream);
			return BitConverter.ToString(array).Replace("-", "").ToLowerInvariant();
		}

		public void ReloadSounds(bool serverSync, bool isTemporarySync)
		{
			oldSounds = new HashSet<string>(currentSounds);
			modifiedSounds.Clear();
			string directoryName = Path.GetDirectoryName(Paths.PluginPath);
			currentSounds.Clear();
			customSoundNames.Clear();
			string customSoundsTempFolderPath = GetCustomSoundsTempFolderPath();
			if (isTemporarySync)
			{
				logger.LogInfo((object)("Temporary folder: " + customSoundsTempFolderPath));
				if (Directory.Exists(customSoundsTempFolderPath))
				{
					ProcessDirectory(customSoundsTempFolderPath, serverSync, isTemporarySync: true);
				}
			}
			ProcessDirectory(directoryName, serverSync, isTemporarySync: false);
		}

		private void ProcessDirectory(string directoryPath, bool serverSync, bool isTemporarySync)
		{
			string[] directories = Directory.GetDirectories(directoryPath, "CustomSounds", SearchOption.AllDirectories);
			foreach (string text in directories)
			{
				string fileName = Path.GetFileName(Path.GetDirectoryName(text));
				ProcessSoundFiles(text, fileName, serverSync, isTemporarySync);
				string[] directories2 = Directory.GetDirectories(text);
				foreach (string text2 in directories2)
				{
					string fileName2 = Path.GetFileName(text2);
					ProcessSoundFiles(text2, fileName2, serverSync, isTemporarySync);
				}
			}
		}

		private (string soundName, int? percentage, string customName) ParseSoundFileName(string fullSoundName)
		{
			string[] array = fullSoundName.Split(new char[1] { '-' });
			string s = array[^1].Replace(".wav", "");
			if (int.TryParse(s, out var result))
			{
				string item = array[0];
				string item2 = string.Join(" ", array.Skip(1).Take(array.Length - 2));
				return (item, result, item2);
			}
			return (array[0], null, string.Join(" ", array.Skip(1)).Replace(".wav", ""));
		}

		private void ProcessSoundFiles(string directoryPath, string packName, bool serverSync, bool isTemporarySync)
		{
			string[] files = Directory.GetFiles(directoryPath, "*.wav");
			foreach (string text in files)
			{
				string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(text);
				(string soundName, int? percentage, string customName) tuple = ParseSoundFileName(fileNameWithoutExtension);
				string item = tuple.soundName;
				int? item2 = tuple.percentage;
				string item3 = tuple.customName;
				string text2 = (item2.HasValue ? $"{item}-{item3}-{item2.Value}" : (item + "-" + item3));
				string text3 = CalculateMD5(text);
				if (isTemporarySync || !currentSounds.Contains(text2))
				{
					if (soundHashes.TryGetValue(text2, out var value) && value != text3)
					{
						modifiedSounds.Add(text2);
					}
					AudioClip audioClip = SoundTool.GetAudioClip(directoryPath, "", text);
					SoundTool.ReplaceAudioClip(item, audioClip);
					soundHashes[text2] = text3;
					currentSounds.Add(text2);
					soundPacks[item] = packName;
					string text4 = "[" + packName + "] " + item + " sound replaced!";
					if (item2 > 0)
					{
						text4 += $" (Random chance: {item2}%)";
					}
					logger.LogInfo((object)text4);
					string key = item + (item2.HasValue ? $"-{item2.Value}-{item3}" : ("-" + item3));
					if (!string.IsNullOrEmpty(item3))
					{
						customSoundNames[key] = item3;
					}
					if (serverSync)
					{
						string text5 = Path.Combine(directoryPath, fileNameWithoutExtension + ".wav");
						logger.LogInfo((object)("[" + text5 + "] " + fileNameWithoutExtension + ".wav!"));
						AudioNetworkHandler.Instance.QueueAudioData(SerializeWavToBytes(text5), fileNameWithoutExtension + ".wav");
					}
				}
			}
		}

		public string ListAllSounds(bool isListing)
		{
			StringBuilder stringBuilder = new StringBuilder(isListing ? "Listing all currently loaded custom sounds:\n\n" : "Customsounds reloaded.\n\n");
			Dictionary<string, List<string>> soundsByPack = new Dictionary<string, List<string>>();
			Action<HashSet<string>, string> action = delegate(HashSet<string> soundsSet, string status)
			{
				foreach (string item5 in soundsSet)
				{
					(string soundName, int? percentage, string customName) tuple = ParseSoundFileName(item5);
					string item = tuple.soundName;
					int? item2 = tuple.percentage;
					string item3 = tuple.customName;
					string text = (item2.HasValue ? $" (Random: {item2.Value}%)" : "");
					string text2 = "";
					string key = item + (item2.HasValue ? $"-{item2.Value}-{item3}" : ("-" + item3));
					if (customSoundNames.TryGetValue(key, out var value))
					{
						text2 = " [" + value + "]";
					}
					string key2 = (soundPacks.ContainsKey(item) ? soundPacks[item] : "Unknown");
					if (!soundsByPack.ContainsKey(key2))
					{
						soundsByPack[key2] = new List<string>();
					}
					string item4 = (isListing ? (item + text + text2) : (item + " (" + status + ")" + text + text2));
					soundsByPack[key2].Add(item4);
				}
			};
			if (!isListing)
			{
				action(new HashSet<string>(currentSounds.Except(oldSounds)), "N¹");
				action(new HashSet<string>(oldSounds.Except(currentSounds)), "D²");
				action(new HashSet<string>(oldSounds.Intersect(currentSounds).Except(modifiedSounds)), "A.E³");
				action(new HashSet<string>(modifiedSounds), "M⁴");
			}
			else
			{
				action(new HashSet<string>(currentSounds), "N¹");
			}
			foreach (string key3 in soundsByPack.Keys)
			{
				stringBuilder.AppendLine(key3 + " :");
				foreach (string item6 in soundsByPack[key3])
				{
					stringBuilder.AppendLine("- " + item6);
				}
				stringBuilder.AppendLine();
			}
			if (!isListing)
			{
				stringBuilder.AppendLine("Footnotes:");
				stringBuilder.AppendLine("¹ N = New");
				stringBuilder.AppendLine("² D = Deleted");
				stringBuilder.AppendLine("³ A.E = Already Existed");
				stringBuilder.AppendLine("⁴ M = Modified");
				stringBuilder.AppendLine();
			}
			return stringBuilder.ToString();
		}
	}
}
namespace CustomSounds.Patches
{
	[HarmonyPatch]
	public class NetworkObjectManager
	{
		private static GameObject networkPrefab;

		private static GameObject networkHandlerHost;

		[HarmonyPatch(typeof(GameNetworkManager), "Start")]
		[HarmonyPrefix]
		public static void Init()
		{
			if (!((Object)(object)networkPrefab != (Object)null))
			{
				networkPrefab = Plugin.Instance.LoadNetworkPrefabFromEmbeddedResource();
				networkPrefab.AddComponent<AudioNetworkHandler>();
				NetworkManager.Singleton.AddNetworkPrefab(networkPrefab);
				Plugin.Instance.logger.LogInfo((object)"Created AudioNetworkHandler prefab");
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(StartOfRound), "Awake")]
		private static void SpawnNetworkHandler()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (NetworkManager.Singleton.IsHost || NetworkManager.Singleton.IsServer)
				{
					Plugin.Instance.logger.LogInfo((object)"Spawning network handler");
					networkHandlerHost = Object.Instantiate<GameObject>(networkPrefab, Vector3.zero, Quaternion.identity);
					if (networkHandlerHost.GetComponent<NetworkObject>().IsSpawned)
					{
						Debug.Log((object)"NetworkObject is spawned and active.");
					}
					else
					{
						Debug.Log((object)"Failed to spawn NetworkObject.");
					}
					networkHandlerHost.GetComponent<NetworkObject>().Spawn(true);
					if ((Object)(object)AudioNetworkHandler.Instance != (Object)null)
					{
						Debug.Log((object)"Successfully accessed AudioNetworkHandler instance.");
					}
					else
					{
						Debug.Log((object)"AudioNetworkHandler instance is null.");
					}
				}
			}
			catch
			{
				Plugin.Instance.logger.LogError((object)"Failed to spawned network handler");
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(GameNetworkManager), "StartDisconnect")]
		private static void DestroyNetworkHandler()
		{
			try
			{
				if (NetworkManager.Singleton.IsHost || NetworkManager.Singleton.IsServer)
				{
					Plugin.Instance.logger.LogInfo((object)"Destroying network handler");
					Object.Destroy((Object)(object)networkHandlerHost);
					networkHandlerHost = null;
				}
			}
			catch
			{
				Plugin.Instance.logger.LogError((object)"Failed to destroy network handler");
			}
		}
	}
	[HarmonyPatch]
	public class RemapKeyPatch
	{
		public Harmony _harmony;

		public static InputActionAsset asset;

		private static string defaultKey;

		private static string path;

		public static string actionName;

		public static void UpdateInputActionAsset(string thing)
		{
			asset = InputActionAsset.FromJson("\r\n            {\r\n                \"maps\" : [\r\n                    {\r\n                        \"name\" : \"CustomSounds\",\r\n                        \"actions\": [\r\n                            {\"name\": \"" + actionName + "\", \"type\" : \"button\"}\r\n                        ],\r\n                        \"bindings\" : [\r\n                            {\"path\" : \"" + thing + "\", \"action\": \"" + actionName + "\"}\r\n                        ]\r\n                    }\r\n                ]\r\n            }");
		}

		[HarmonyPatch(typeof(KepRemapPanel), "LoadKeybindsUI")]
		[HarmonyPrefix]
		public static void AddRemappableKey(KepRemapPanel __instance)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			Debug.Log((object)("[CustomSounds] Default key for sync is " + defaultKey));
			for (int i = 0; i < __instance.remappableKeys.Count; i++)
			{
				if (__instance.remappableKeys[i].ControlName == "Accept Sync")
				{
					return;
				}
			}
			RemappableKey val = new RemappableKey();
			UpdateInputActionAsset(defaultKey);
			if ((Object)(object)asset == (Object)null)
			{
				Debug.LogError((object)"InputActionAsset is null.");
				return;
			}
			InputAction val2 = asset.FindAction("CustomSounds/" + actionName, false);
			if (val2 == null)
			{
				Debug.LogError((object)"Action 'CustomSounds/AcceptSyncAction' not found.");
				return;
			}
			InputActionReference currentInput = InputActionReference.Create(asset.FindAction("CustomSounds/" + actionName, false));
			val.ControlName = "Accept Sync";
			val.currentInput = currentInput;
			__instance.remappableKeys.Add(val);
		}

		[HarmonyPatch(typeof(PlayerControllerB), "Update")]
		[HarmonyPostfix]
		public static void ReadInput(PlayerControllerB __instance)
		{
			if (((((NetworkBehaviour)__instance).IsOwner && __instance.isPlayerControlled && (!((NetworkBehaviour)__instance).IsServer || __instance.isHostPlayerObject)) || __instance.isTestingPlayer) && Application.isFocused)
			{
				if (!Object.op_Implicit((Object)(object)asset) || !asset.enabled)
				{
					UpdateInputActionAsset(defaultKey);
					asset.Enable();
				}
				InputAction val = asset.FindAction("CustomSounds/" + actionName, false);
				if (val != null && val.WasPressedThisFrame() && AudioNetworkHandler.isRequestingSync)
				{
					Plugin.Instance.ShowCustomTip("CustomSounds Sync", "Sync request accepted successfully!", isWarning: false);
					AudioNetworkHandler.hasAcceptedSync = true;
					AudioNetworkHandler.isRequestingSync = false;
				}
			}
		}

		[HarmonyPatch(typeof(IngamePlayerSettings), "CompleteRebind")]
		[HarmonyPrefix]
		public static void SavingActionRebind(IngamePlayerSettings __instance)
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			if (!(__instance.rebindingOperation.action.name != actionName))
			{
				string text = ((object)__instance.rebindingOperation.action).ToString();
				string text2 = text.Split('[', ']')[1];
				string value = text2.Replace("/Keyboard/", "");
				defaultKey = text2;
				try
				{
					KeyCode val = (KeyCode)Enum.Parse(typeof(KeyCode), value, ignoreCase: true);
					Plugin.AcceptSyncKey.Value = new KeyboardShortcut(val, Array.Empty<KeyCode>());
				}
				catch (Exception ex)
				{
					Debug.LogError((object)("Erreur lors de la conversion de la chaîne en KeyCode: " + ex.Message));
				}
				UpdateInputActionAsset(defaultKey);
			}
		}

		[HarmonyPatch(typeof(KepRemapPanel), "ResetKeybindsUI")]
		[HarmonyPrefix]
		public static void ResetAcceptAction(KepRemapPanel __instance)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			Plugin.AcceptSyncKey.Value = new KeyboardShortcut((KeyCode)289, Array.Empty<KeyCode>());
			defaultKey = "<Keyboard>/f8";
			UpdateInputActionAsset(defaultKey);
			bool flag = UpdateAcceptSyncKeybind(__instance, "<Keyboard>/f8");
		}

		private static bool UpdateAcceptSyncKeybind(KepRemapPanel panel, string defaultBinding)
		{
			foreach (RemappableKey remappableKey in panel.remappableKeys)
			{
				if (remappableKey.ControlName == "Accept Sync")
				{
					remappableKey.currentInput = InputActionReference.Create(asset.FindAction("CustomSounds/AcceptSyncAction", false));
					Debug.Log((object)"[CustomSounds] Found and updated 'Accept Sync' keybinding");
					return true;
				}
			}
			Debug.Log((object)"[CustomSounds] 'Accept Sync' keybinding not found");
			return false;
		}

		static RemapKeyPatch()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			KeyboardShortcut value = Plugin.AcceptSyncKey.Value;
			defaultKey = "<Keyboard>/" + ((object)(KeyboardShortcut)(ref value)).ToString();
			path = Application.persistentDataPath + "/AcceptSyncButton.txt";
			actionName = "AcceptSyncAction";
		}
	}
	[HarmonyPatch(typeof(Terminal), "ParsePlayerSentence")]
	public static class TerminalParsePlayerSentencePatch
	{
		public static bool Prefix(Terminal __instance, ref TerminalNode __result)
		{
			string[] array = __instance.screenText.text.Split(new char[1] { '\n' });
			if (array.Length == 0)
			{
				return true;
			}
			string[] array2 = array.Last().Trim().ToLower()
				.Split(new char[1] { ' ' });
			if (array2.Length == 0 || (array2[0] != "customsounds" && array2[0] != "cs"))
			{
				return true;
			}
			Plugin.Instance.logger.LogInfo((object)("Received terminal command: " + string.Join(" ", array2)));
			if (array2.Length > 1 && (array2[0] == "customsounds" || array2[0] == "cs"))
			{
				switch (array2[1])
				{
				case "reload":
				case "rl":
					Plugin.Instance.RevertSounds();
					Plugin.Instance.ReloadSounds(serverSync: false, isTemporarySync: false);
					__result = CreateTerminalNode(Plugin.Instance.ListAllSounds(isListing: false));
					return false;
				case "revert":
				case "rv":
					Plugin.Instance.RevertSounds();
					__result = CreateTerminalNode("Game sounds reverted to original.\n\n");
					return false;
				case "list":
				case "l":
					__result = CreateTerminalNode(Plugin.Instance.ListAllSounds(isListing: true));
					return false;
				case "help":
				case "h":
					if (NetworkManager.Singleton.IsHost)
					{
						__result = CreateTerminalNode("CustomSounds commands \n(Can also be used with 'CS' as an alias).\n\n>CUSTOMSOUNDS LIST/L\nTo display all currently loaded sounds\n\n>CUSTOMSOUNDS RELOAD/RL\nTo reload and apply sounds from the 'CustomSounds' folder and its subfolders.\n\n>CUSTOMSOUNDS REVERT/RV\nTo unload all custom sounds and restore original game sounds\n\n>CUSTOMSOUNDS SYNC/S\nTo start the sync of custom sounds with clients\n\n>CUSTOMSOUNDS FORCE-UNSYNC/FU\nTo force the unsync process for all clients\n\n");
					}
					else
					{
						__result = CreateTerminalNode("CustomSounds commands \n(Can also be used with 'CS' as an alias).\n\n>CUSTOMSOUNDS LIST/L\nTo display all currently loaded sounds\n\n>CUSTOMSOUNDS RELOAD/RL\nTo reload and apply sounds from the 'CustomSounds' folder and its subfolders.\n\n>CUSTOMSOUNDS REVERT/RV\nTo unload all custom sounds and restore original game sounds\n\n>CUSTOMSOUNDS UNSYNC/U\nUnsyncs sounds sent by the host.\n\n");
					}
					return false;
				case "sync":
				case "s":
					if (NetworkManager.Singleton.IsHost)
					{
						if (Plugin.Instance.configUseNetworking.Value)
						{
							__result = CreateTerminalNode("Custom sound sync initiated. \nSyncing sounds with clients...\n\n");
							Plugin.Instance.ReloadSounds(serverSync: true, isTemporarySync: false);
						}
						else
						{
							__result = CreateTerminalNode("Custom sound sync is currently disabled. \nPlease enable network support in the plugin config to use this feature.\n\n");
						}
					}
					else
					{
						__result = CreateTerminalNode("/!\\ ERROR /!\\ \nThis command can only be used by the host!\n\n");
					}
					return false;
				case "unsync":
				case "u":
					if (!NetworkManager.Singleton.IsHost)
					{
						__result = CreateTerminalNode("Unsyncing custom sounds. \nTemporary files deleted and original sounds reloaded.\n\n");
						Plugin.Instance.DeleteTempFolder();
						Plugin.Instance.ReloadSounds(serverSync: false, isTemporarySync: false);
					}
					else
					{
						__result = CreateTerminalNode("/!\\ ERROR /!\\ \nThis command cannot be used by the host!\n\n");
					}
					return false;
				case "fu":
				case "force-unsync":
					if (NetworkManager.Singleton.IsHost)
					{
						__result = CreateTerminalNode("Forcing unsync for all clients. \nAll client-side temporary synced files have been deleted, and original sounds reloaded.\n\n");
						AudioNetworkHandler.Instance.ForceUnsync();
					}
					else
					{
						__result = CreateTerminalNode("/!\\ ERROR /!\\ \nThis command can only be used by the host!\n\n");
					}
					return false;
				default:
					__result = CreateTerminalNode("Unknown customsounds command.\n\n");
					return false;
				}
			}
			return true;
		}

		private static TerminalNode CreateTerminalNode(string message)
		{
			TerminalNode val = ScriptableObject.CreateInstance<TerminalNode>();
			val.displayText = message;
			val.clearPreviousText = true;
			return val;
		}
	}
}
namespace CustomSounds.Networking
{
	public class AudioNetworkHandler : NetworkBehaviour
	{
		private struct AudioData
		{
			public List<byte[]> Segments;

			public string FileName;

			public AudioData(List<byte[]> segments, string fileName)
			{
				Segments = segments;
				FileName = fileName;
			}
		}

		private List<byte[]> receivedAudioSegments = new List<byte[]>();

		private string audioFileName;

		private int totalAudioFiles;

		private int processedAudioFiles;

		private int totalSegments;

		private int processedSegments;

		public static bool isRequestingSync;

		private float[] progressThresholds = new float[4] { 0.25f, 0.5f, 0.75f, 1f };

		private int lastThresholdIndex = -1;

		public static bool hasAcceptedSync;

		private Queue<AudioData> audioQueue = new Queue<AudioData>();

		private bool isSendingAudio = false;

		public static AudioNetworkHandler Instance { get; private set; }

		private void Awake()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
				Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
				Debug.Log((object)"AudioNetworkHandler instance created.");
			}
			else
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
				Debug.Log((object)"Extra AudioNetworkHandler instance destroyed.");
			}
		}

		public void QueueAudioData(byte[] audioData, string audioName)
		{
			List<byte[]> list = Plugin.SplitAudioData(audioData);
			totalSegments += list.Count;
			audioQueue.Enqueue(new AudioData(list, audioName));
			if (!isSendingAudio)
			{
				totalAudioFiles = audioQueue.Count;
				processedAudioFiles = 0;
				((MonoBehaviour)this).StartCoroutine(SendAudioDataQueue());
			}
		}

		private IEnumerator SendAudioDataQueue()
		{
			isSendingAudio = true;
			totalSegments = 0;
			processedSegments = 0;
			lastThresholdIndex = -1;
			RequestSyncWithClients();
			yield return (object)new WaitForSeconds(6f);
			isRequestingSync = false;
			DisplayStartingSyncMessageClientRpc();
			yield return (object)new WaitForSeconds(2f);
			while (audioQueue.Count > 0)
			{
				AudioData audioData = audioQueue.Dequeue();
				yield return ((MonoBehaviour)this).StartCoroutine(SendAudioDataCoroutine(audioData.Segments, audioData.FileName));
				processedAudioFiles++;
				UpdateProgress();
			}
			NotifyClientsQueueCompletedServerRpc();
			isSendingAudio = false;
		}

		private void RequestSyncWithClients()
		{
			foreach (NetworkClient connectedClients in NetworkManager.Singleton.ConnectedClientsList)
			{
				RequestSyncClientRpc(connectedClients.ClientId);
			}
		}

		[ClientRpc]
		private void RequestSyncClientRpc(ulong clientId)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
				{
					ClientRpcParams val = default(ClientRpcParams);
					FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(3186703908u, val, (RpcDelivery)0);
					BytePacker.WriteValueBitPacked(val2, clientId);
					((NetworkBehaviour)this).__endSendClientRpc(ref val2, 3186703908u, val, (RpcDelivery)0);
				}
				if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost) && !((NetworkBehaviour)this).IsServer)
				{
					Plugin.Instance.ShowCustomTip("CustomSounds Sync", $"Press {Plugin.AcceptSyncKey.Value} to accept the audio sync request.", isWarning: false);
					isRequestingSync = true;
				}
			}
		}

		[ServerRpc(RequireOwnership = false)]
		private void NotifyClientsQueueCompletedServerRpc(ServerRpcParams rpcParams = default(ServerRpcParams))
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
				{
					FastBufferWriter val = ((NetworkBehaviour)this).__beginSendServerRpc(152710787u, rpcParams, (RpcDelivery)0);
					((NetworkBehaviour)this).__endSendServerRpc(ref val, 152710787u, rpcParams, (RpcDelivery)0);
				}
				if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost))
				{
					ProcessLastAudioFileClientRpc();
				}
			}
		}

		public void ForceUnsync()
		{
			ForceUnsyncClientsClientRpc();
		}

		[ClientRpc]
		private void ForceUnsyncClientsClientRpc()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
			{
				ClientRpcParams val = default(ClientRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(3960362720u, val, (RpcDelivery)0);
				((NetworkBehaviour)this).__endSendClientRpc(ref val2, 3960362720u, val, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost))
			{
				if (((NetworkBehaviour)this).IsServer)
				{
					Debug.Log((object)"Forcing all clients to delete Temporary-Sync folder.");
					return;
				}
				Plugin.Instance.ShowCustomTip("CustomSounds Sync", "The CustomSounds sync has been reset by the host.\nTemporary files deleted and original sounds reloaded", isWarning: false);
				Plugin.Instance.DeleteTempFolder();
				Plugin.Instance.RevertSounds();
				Plugin.Instance.ReloadSounds(serverSync: false, isTemporarySync: false);
			}
		}

		[ClientRpc]
		private void ProcessLastAudioFileClientRpc()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
				{
					ClientRpcParams val = default(ClientRpcParams);
					FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(234624598u, val, (RpcDelivery)0);
					((NetworkBehaviour)this).__endSendClientRpc(ref val2, 234624598u, val, (RpcDelivery)0);
				}
				if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost) && hasAcceptedSync)
				{
					hasAcceptedSync = false;
					ProcessLastAudioFile();
					Debug.Log((object)"Reverting all sounds.");
					Plugin.Instance.RevertSounds();
					Debug.Log((object)"All sounds reverted!");
					Debug.Log((object)"Reloading all sounds.");
					Plugin.Instance.ReloadSounds(serverSync: false, isTemporarySync: true);
					Debug.Log((object)"All sounds reloaded!");
				}
			}
		}

		private void ProcessLastAudioFile()
		{
			if (receivedAudioSegments.Count > 0 && !string.IsNullOrEmpty(audioFileName))
			{
				byte[] byteArray = Plugin.CombineAudioSegments(receivedAudioSegments);
				Plugin.DeserializeBytesToWav(byteArray, audioFileName);
				receivedAudioSegments.Clear();
				audioFileName = null;
			}
		}

		public void SendAudioData(byte[] audioData, string audioName)
		{
			List<byte[]> list = Plugin.SplitAudioData(audioData);
			audioFileName = audioName;
			SendAudioMetaDataToClientsServerRpc(list.Count, audioName);
			((MonoBehaviour)this).StartCoroutine(SendAudioDataCoroutine(list, audioName));
		}

		[ServerRpc]
		public void SendAudioMetaDataToClientsServerRpc(int totalSegments, string fileName)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Invalid comparison between Unknown and I4
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Invalid comparison between Unknown and I4
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
			{
				if (((NetworkBehaviour)this).OwnerClientId != networkManager.LocalClientId)
				{
					if ((int)networkManager.LogLevel <= 1)
					{
						Debug.LogError((object)"Only the owner can invoke a ServerRpc that requires ownership!");
					}
					return;
				}
				ServerRpcParams val = default(ServerRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(3991320206u, val, (RpcDelivery)0);
				BytePacker.WriteValueBitPacked(val2, totalSegments);
				bool flag = fileName != null;
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag, default(ForPrimitives));
				if (flag)
				{
					((FastBufferWriter)(ref val2)).WriteValueSafe(fileName, false);
				}
				((NetworkBehaviour)this).__endSendServerRpc(ref val2, 3991320206u, val, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost))
			{
				Debug.Log((object)$"Sending metadata to clients: {totalSegments} segments, file name: {fileName}");
				ReceiveAudioMetaDataClientRpc(totalSegments, fileName);
			}
		}

		private IEnumerator SendAudioDataCoroutine(List<byte[]> audioSegments, string audioName)
		{
			foreach (byte[] segment in audioSegments)
			{
				SendBytesToServerRpc(segment, audioName);
				processedSegments++;
				UpdateProgress();
				yield return (object)new WaitForSeconds(0.2f);
			}
		}

		[ServerRpc]
		public void SendBytesToServerRpc(byte[] audioSegment, string audioName)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Invalid comparison between Unknown and I4
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: 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_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Invalid comparison between Unknown and I4
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
			{
				if (((NetworkBehaviour)this).OwnerClientId != networkManager.LocalClientId)
				{
					if ((int)networkManager.LogLevel <= 1)
					{
						Debug.LogError((object)"Only the owner can invoke a ServerRpc that requires ownership!");
					}
					return;
				}
				ServerRpcParams val = default(ServerRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(3131260794u, val, (RpcDelivery)0);
				bool flag = audioSegment != null;
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag, default(ForPrimitives));
				if (flag)
				{
					((FastBufferWriter)(ref val2)).WriteValueSafe<byte>(audioSegment, default(ForPrimitives));
				}
				bool flag2 = audioName != null;
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag2, default(ForPrimitives));
				if (flag2)
				{
					((FastBufferWriter)(ref val2)).WriteValueSafe(audioName, false);
				}
				((NetworkBehaviour)this).__endSendServerRpc(ref val2, 3131260794u, val, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost))
			{
				Debug.Log((object)("Sending segment to server: " + audioName));
				ReceiveBytesClientRpc(audioSegment, audioName);
			}
		}

		[ClientRpc]
		public void ReceiveAudioMetaDataClientRpc(int totalSegments, string fileName)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
			{
				ClientRpcParams val = default(ClientRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(1027341762u, val, (RpcDelivery)0);
				BytePacker.WriteValueBitPacked(val2, totalSegments);
				bool flag = fileName != null;
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag, default(ForPrimitives));
				if (flag)
				{
					((FastBufferWriter)(ref val2)).WriteValueSafe(fileName, false);
				}
				((NetworkBehaviour)this).__endSendClientRpc(ref val2, 1027341762u, val, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost))
			{
				Debug.Log((object)$"Received metadata on client: {totalSegments} segments expected, file name: {fileName}");
				audioFileName = fileName;
				receivedAudioSegments.Clear();
			}
		}

		[ClientRpc]
		public void ReceiveBytesClientRpc(byte[] audioSegment, string audioName)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: 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_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
			{
				ClientRpcParams val = default(ClientRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(2945580654u, val, (RpcDelivery)0);
				bool flag = audioSegment != null;
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag, default(ForPrimitives));
				if (flag)
				{
					((FastBufferWriter)(ref val2)).WriteValueSafe<byte>(audioSegment, default(ForPrimitives));
				}
				bool flag2 = audioName != null;
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag2, default(ForPrimitives));
				if (flag2)
				{
					((FastBufferWriter)(ref val2)).WriteValueSafe(audioName, false);
				}
				((NetworkBehaviour)this).__endSendClientRpc(ref val2, 2945580654u, val, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost) && !((NetworkBehaviour)this).IsServer && hasAcceptedSync)
			{
				if (!string.IsNullOrEmpty(audioName) && audioFileName != audioName)
				{
					ProcessLastAudioFile();
					audioFileName = audioName;
				}
				receivedAudioSegments.Add(audioSegment);
			}
		}

		[ClientRpc]
		private void DisplayStartingSyncMessageClientRpc()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
			{
				ClientRpcParams val = default(ClientRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(3964799390u, val, (RpcDelivery)0);
				((NetworkBehaviour)this).__endSendClientRpc(ref val2, 3964799390u, val, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost))
			{
				if (hasAcceptedSync)
				{
					Plugin.Instance.ShowCustomTip("CustomSounds Sync", "Starting audio synchronization. Please wait...", isWarning: false);
					Plugin.Instance.DeleteTempFolder();
				}
				else if (((NetworkBehaviour)this).IsServer)
				{
					Plugin.Instance.ShowCustomTip("CustomSounds Sync", "Initiating audio synchronization. Sending files to clients...", isWarning: false);
				}
			}
		}

		private void UpdateProgress()
		{
			float progress = (float)processedSegments / (float)totalSegments;
			int currentThresholdIndex = GetCurrentThresholdIndex(progress);
			if (currentThresholdIndex > lastThresholdIndex)
			{
				lastThresholdIndex = currentThresholdIndex;
				UpdateProgressClientRpc(progress);
			}
		}

		private int GetCurrentThresholdIndex(float progress)
		{
			for (int num = progressThresholds.Length - 1; num >= 0; num--)
			{
				if (progress >= progressThresholds[num])
				{
					return num;
				}
			}
			return -1;
		}

		[ClientRpc]
		private void UpdateProgressClientRpc(float progress)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
			{
				ClientRpcParams val = default(ClientRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(3902617409u, val, (RpcDelivery)0);
				((FastBufferWriter)(ref val2)).WriteValueSafe<float>(ref progress, default(ForPrimitives));
				((NetworkBehaviour)this).__endSendClientRpc(ref val2, 3902617409u, val, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage != 2 || (!networkManager.IsClient && !networkManager.IsHost) || (!((NetworkBehaviour)this).IsServer && !hasAcceptedSync))
			{
				return;
			}
			string text = GenerateProgressBar(progress);
			if (progress < 1f)
			{
				if (!((NetworkBehaviour)this).IsServer)
				{
					Plugin.Instance.ShowCustomTip("CustomSounds Sync", "Sounds transfer progression:\n" + text, isWarning: false);
				}
			}
			else if (((NetworkBehaviour)this).IsServer)
			{
				Plugin.Instance.ShowCustomTip("CustomSounds Sync", "All sounds have been successfully sent!", isWarning: false);
			}
			else
			{
				Plugin.Instance.ShowCustomTip("CustomSounds Sync", "All sounds have been successfully received!", isWarning: false);
			}
		}

		private string GenerateProgressBar(float progress)
		{
			int num = 26;
			progress = Mathf.Clamp(progress, 0f, 1f);
			int num2 = (int)(progress * (float)num);
			return "[" + new string('#', num2) + new string('-', num - num2) + "] " + (int)(progress * 100f) + "%";
		}

		protected override void __initializeVariables()
		{
			((NetworkBehaviour)this).__initializeVariables();
		}

		[RuntimeInitializeOnLoadMethod]
		internal static void InitializeRPCS_AudioNetworkHandler()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Expected O, but got Unknown
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Expected O, but got Unknown
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Expected O, but got Unknown
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Expected O, but got Unknown
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Expected O, but got Unknown
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Expected O, but got Unknown
			NetworkManager.__rpc_func_table.Add(3186703908u, new RpcReceiveHandler(__rpc_handler_3186703908));
			NetworkManager.__rpc_func_table.Add(152710787u, new RpcReceiveHandler(__rpc_handler_152710787));
			NetworkManager.__rpc_func_table.Add(3960362720u, new RpcReceiveHandler(__rpc_handler_3960362720));
			NetworkManager.__rpc_func_table.Add(234624598u, new RpcReceiveHandler(__rpc_handler_234624598));
			NetworkManager.__rpc_func_table.Add(3991320206u, new RpcReceiveHandler(__rpc_handler_3991320206));
			NetworkManager.__rpc_func_table.Add(3131260794u, new RpcReceiveHandler(__rpc_handler_3131260794));
			NetworkManager.__rpc_func_table.Add(1027341762u, new RpcReceiveHandler(__rpc_handler_1027341762));
			NetworkManager.__rpc_func_table.Add(2945580654u, new RpcReceiveHandler(__rpc_handler_2945580654));
			NetworkManager.__rpc_func_table.Add(3964799390u, new RpcReceiveHandler(__rpc_handler_3964799390));
			NetworkManager.__rpc_func_table.Add(3902617409u, new RpcReceiveHandler(__rpc_handler_3902617409));
		}

		private static void __rpc_handler_3186703908(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				ulong clientId = default(ulong);
				ByteUnpacker.ReadValueBitPacked(reader, ref clientId);
				target.__rpc_exec_stage = (__RpcExecStage)2;
				((AudioNetworkHandler)(object)target).RequestSyncClientRpc(clientId);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_152710787(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: 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)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				ServerRpcParams server = rpcParams.Server;
				target.__rpc_exec_stage = (__RpcExecStage)1;
				((AudioNetworkHandler)(object)target).NotifyClientsQueueCompletedServerRpc(server);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_3960362720(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				target.__rpc_exec_stage = (__RpcExecStage)2;
				((AudioNetworkHandler)(object)target).ForceUnsyncClientsClientRpc();
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_234624598(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				target.__rpc_exec_stage = (__RpcExecStage)2;
				((AudioNetworkHandler)(object)target).ProcessLastAudioFileClientRpc();
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_3991320206(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Invalid comparison between Unknown and I4
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if (rpcParams.Server.Receive.SenderClientId != target.OwnerClientId)
			{
				if ((int)networkManager.LogLevel <= 1)
				{
					Debug.LogError((object)"Only the owner can invoke a ServerRpc that requires ownership!");
				}
				return;
			}
			int num = default(int);
			ByteUnpacker.ReadValueBitPacked(reader, ref num);
			bool flag = default(bool);
			((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag, default(ForPrimitives));
			string fileName = null;
			if (flag)
			{
				((FastBufferReader)(ref reader)).ReadValueSafe(ref fileName, false);
			}
			target.__rpc_exec_stage = (__RpcExecStage)1;
			((AudioNetworkHandler)(object)target).SendAudioMetaDataToClientsServerRpc(num, fileName);
			target.__rpc_exec_stage = (__RpcExecStage)0;
		}

		private static void __rpc_handler_3131260794(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Invalid comparison between Unknown and I4
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: 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)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if (rpcParams.Server.Receive.SenderClientId != target.OwnerClientId)
			{
				if ((int)networkManager.LogLevel <= 1)
				{
					Debug.LogError((object)"Only the owner can invoke a ServerRpc that requires ownership!");
				}
				return;
			}
			bool flag = default(bool);
			((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag, default(ForPrimitives));
			byte[] audioSegment = null;
			if (flag)
			{
				((FastBufferReader)(ref reader)).ReadValueSafe<byte>(ref audioSegment, default(ForPrimitives));
			}
			bool flag2 = default(bool);
			((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag2, default(ForPrimitives));
			string audioName = null;
			if (flag2)
			{
				((FastBufferReader)(ref reader)).ReadValueSafe(ref audioName, false);
			}
			target.__rpc_exec_stage = (__RpcExecStage)1;
			((AudioNetworkHandler)(object)target).SendBytesToServerRpc(audioSegment, audioName);
			target.__rpc_exec_stage = (__RpcExecStage)0;
		}

		private static void __rpc_handler_1027341762(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				int num = default(int);
				ByteUnpacker.ReadValueBitPacked(reader, ref num);
				bool flag = default(bool);
				((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag, default(ForPrimitives));
				string fileName = null;
				if (flag)
				{
					((FastBufferReader)(ref reader)).ReadValueSafe(ref fileName, false);
				}
				target.__rpc_exec_stage = (__RpcExecStage)2;
				((AudioNetworkHandler)(object)target).ReceiveAudioMetaDataClientRpc(num, fileName);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_2945580654(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_002f: 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_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				bool flag = default(bool);
				((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag, default(ForPrimitives));
				byte[] audioSegment = null;
				if (flag)
				{
					((FastBufferReader)(ref reader)).ReadValueSafe<byte>(ref audioSegment, default(ForPrimitives));
				}
				bool flag2 = default(bool);
				((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag2, default(ForPrimitives));
				string audioName = null;
				if (flag2)
				{
					((FastBufferReader)(ref reader)).ReadValueSafe(ref audioName, false);
				}
				target.__rpc_exec_stage = (__RpcExecStage)2;
				((AudioNetworkHandler)(object)target).ReceiveBytesClientRpc(audioSegment, audioName);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_3964799390(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				target.__rpc_exec_stage = (__RpcExecStage)2;
				((AudioNetworkHandler)(object)target).DisplayStartingSyncMessageClientRpc();
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_3902617409(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_002f: 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_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				float progress = default(float);
				((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref progress, default(ForPrimitives));
				target.__rpc_exec_stage = (__RpcExecStage)2;
				((AudioNetworkHandler)(object)target).UpdateProgressClientRpc(progress);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		protected internal override string __getTypeName()
		{
			return "AudioNetworkHandler";
		}
	}
}