Decompiled source of MelaniesVoice v1.0.0

com.github.zehsteam.MelaniesVoice.dll

Decompiled 4 hours 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.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using LethalConfig;
using LethalConfig.ConfigItems;
using LethalConfig.ConfigItems.Options;
using Microsoft.CodeAnalysis;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.Networking;
using com.github.zehsteam.MelaniesVoice.Dependencies;
using com.github.zehsteam.MelaniesVoice.MonoBehaviours;
using com.github.zehsteam.MelaniesVoice.NetcodePatcher;
using com.github.zehsteam.MelaniesVoice.Patches;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("com.github.zehsteam.MelaniesVoice")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("MelaniesVoice")]
[assembly: AssemblyTitle("com.github.zehsteam.MelaniesVoice")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
[module: NetcodePatchedAssembly]
internal class <Module>
{
	static <Module>()
	{
	}
}
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 com.github.zehsteam.MelaniesVoice
{
	internal static class ConfigHelper
	{
		public static void SetModIcon(Sprite sprite)
		{
			if (LethalConfigProxy.Enabled)
			{
				LethalConfigProxy.SetModIcon(sprite);
			}
		}

		public static void SetModDescription(string description)
		{
			if (LethalConfigProxy.Enabled)
			{
				LethalConfigProxy.SetModDescription(description);
			}
		}

		public static void SkipAutoGen()
		{
			if (LethalConfigProxy.Enabled)
			{
				LethalConfigProxy.SkipAutoGen();
			}
		}

		public static ConfigEntry<T> Bind<T>(string section, string key, T defaultValue, bool requiresRestart, string description, AcceptableValueBase acceptableValues = null, Action<T> settingChanged = null, ConfigFile configFile = null)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			if (configFile == null)
			{
				configFile = ((BaseUnityPlugin)Plugin.Instance).Config;
			}
			ConfigEntry<T> configEntry = ((acceptableValues == null) ? configFile.Bind<T>(section, key, defaultValue, description) : configFile.Bind<T>(section, key, defaultValue, new ConfigDescription(description, acceptableValues, Array.Empty<object>())));
			if (settingChanged != null)
			{
				configEntry.SettingChanged += delegate
				{
					settingChanged?.Invoke(configEntry.Value);
				};
			}
			if (LethalConfigProxy.Enabled)
			{
				LethalConfigProxy.AddConfig<T>(configEntry, requiresRestart);
			}
			return configEntry;
		}

		public static void AddButton(string section, string name, string description, string buttonText, Action callback)
		{
			if (LethalConfigProxy.Enabled)
			{
				LethalConfigProxy.AddButton(section, name, description, buttonText, callback);
			}
		}
	}
	internal class ConfigManager
	{
		public ConfigEntry<bool> ExtendedLogging { get; private set; }

		public ConfigEntry<bool> TTS_Enabled { get; private set; }

		public ConfigEntry<string> TTS_Voice { get; private set; }

		public ConfigEntry<bool> TTS_HearMyself { get; private set; }

		public ConfigEntry<float> TTS_MaxDistance { get; private set; }

		public ConfigManager()
		{
			BindConfigs();
			SetupChangedEvents();
			ClearUnusedEntries();
		}

		private void BindConfigs()
		{
			ConfigHelper.SkipAutoGen();
			ExtendedLogging = ConfigHelper.Bind("General", "ExtendedLogging", defaultValue: false, requiresRestart: false, "Enable extended logging.");
			TTS_Enabled = ConfigHelper.Bind("Text-To-Speech", "Enabled", defaultValue: true, requiresRestart: false, "If enabled, messages sent by players will be spoken by text-to-speech.");
			TTS_Voice = ConfigHelper.Bind("Text-To-Speech", "Voice", TextToSpeech.Voices[0], requiresRestart: false, "Your text-to-speech voice.", (AcceptableValueBase)(object)new AcceptableValueList<string>(TextToSpeech.Voices));
			TTS_HearMyself = ConfigHelper.Bind("Text-To-Speech", "HearMyself", defaultValue: true, requiresRestart: false, "If enabled, you will hear your own messages.");
			TTS_MaxDistance = ConfigHelper.Bind("Text-To-Speech", "MaxDistance", 40f, requiresRestart: false, "The max distance you will hear other players messages.");
		}

		private void SetupChangedEvents()
		{
			TTS_Enabled.SettingChanged += VoiceController.OnSettingsChanged;
			TTS_HearMyself.SettingChanged += VoiceController.OnSettingsChanged;
			TTS_MaxDistance.SettingChanged += VoiceController.OnSettingsChanged;
		}

		private void ClearUnusedEntries()
		{
			ConfigFile config = ((BaseUnityPlugin)Plugin.Instance).Config;
			PropertyInfo property = ((object)config).GetType().GetProperty("OrphanedEntries", BindingFlags.Instance | BindingFlags.NonPublic);
			Dictionary<ConfigDefinition, string> dictionary = (Dictionary<ConfigDefinition, string>)property.GetValue(config, null);
			dictionary.Clear();
			config.Save();
		}
	}
	internal static class Content
	{
		public static GameObject VoiceControllerPrefab;

		public static void Load()
		{
			LoadAssetsFromAssetBundle();
		}

		private static void LoadAssetsFromAssetBundle()
		{
			try
			{
				AssetBundle val = LoadAssetBundle("melaniesvoice_assets");
				VoiceControllerPrefab = val.LoadAsset<GameObject>("VoiceController");
				Plugin.logger.LogInfo((object)"Successfully loaded assets from AssetBundle!");
			}
			catch (Exception arg)
			{
				Plugin.logger.LogError((object)$"Failed to load assets from AssetBundle.\n\n{arg}");
			}
		}

		private static AssetBundle LoadAssetBundle(string fileName)
		{
			string directoryName = Path.GetDirectoryName(((BaseUnityPlugin)Plugin.Instance).Info.Location);
			string text = Path.Combine(directoryName, fileName);
			return AssetBundle.LoadFromFile(text);
		}
	}
	internal static class NetworkUtils
	{
		public static bool IsServer
		{
			get
			{
				if ((Object)(object)NetworkManager.Singleton == (Object)null)
				{
					return false;
				}
				return NetworkManager.Singleton.IsServer;
			}
		}

		public static bool IsHost
		{
			get
			{
				if ((Object)(object)NetworkManager.Singleton == (Object)null)
				{
					return false;
				}
				return NetworkManager.Singleton.IsHost;
			}
		}

		public static ulong GetLocalClientId()
		{
			return NetworkManager.Singleton.LocalClientId;
		}

		public static bool IsLocalClientId(ulong clientId)
		{
			return clientId == GetLocalClientId();
		}
	}
	internal static class PlayerUtils
	{
		public static PlayerControllerB GetLocalPlayerScript()
		{
			if ((Object)(object)GameNetworkManager.Instance == (Object)null)
			{
				return null;
			}
			return GameNetworkManager.Instance.localPlayerController;
		}

		public static bool IsLocalPlayer(PlayerControllerB playerScript)
		{
			return (Object)(object)playerScript == (Object)(object)GetLocalPlayerScript();
		}

		public static PlayerControllerB GetPlayerScriptByClientId(ulong clientId)
		{
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			foreach (PlayerControllerB val in allPlayerScripts)
			{
				if (val.actualClientId == clientId)
				{
					return val;
				}
			}
			return null;
		}

		public static PlayerControllerB GetPlayerScriptByPlayerId(int playerId)
		{
			if (playerId < 0 || playerId > StartOfRound.Instance.allPlayerScripts.Length - 1)
			{
				return null;
			}
			return StartOfRound.Instance.allPlayerScripts[playerId];
		}
	}
	[BepInPlugin("com.github.zehsteam.MelaniesVoice", "MelaniesVoice", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	internal class Plugin : BaseUnityPlugin
	{
		private readonly Harmony harmony = new Harmony("com.github.zehsteam.MelaniesVoice");

		internal static Plugin Instance;

		internal static ManualLogSource logger;

		internal static ConfigManager ConfigManager;

		private void Awake()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
			logger = Logger.CreateLogSource("com.github.zehsteam.MelaniesVoice");
			logger.LogInfo((object)"MelaniesVoice has awoken!");
			harmony.PatchAll(typeof(GameNetworkManagerPatch));
			harmony.PatchAll(typeof(HUDManagerPatch));
			harmony.PatchAll(typeof(PlayerControllerBPatch));
			ConfigManager = new ConfigManager();
			Content.Load();
			NetcodePatcherAwake();
		}

		private void NetcodePatcherAwake()
		{
			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);
					}
				}
			}
		}

		public void LogInfoExtended(object data)
		{
			if (ConfigManager.ExtendedLogging.Value)
			{
				logger.LogInfo(data);
			}
		}

		public void LogWarningExtended(object data)
		{
			if (ConfigManager.ExtendedLogging.Value)
			{
				logger.LogWarning(data);
			}
		}
	}
	internal static class TextToSpeech
	{
		private const string _apiUrl = "https://api.streamelements.com/kappa/v2/speech";

		public static readonly string[] Voices = new string[3] { "Brian", "Salli", "Justin" };

		public static void GetAudioClip(int id, string text, string voice, Action<int, AudioClip> onClipReady)
		{
			Utils.StartCoroutine(GetAudioClipFromAPI(id, text, voice, onClipReady));
		}

		private static IEnumerator GetAudioClipFromAPI(int id, string text, string voice, Action<int, AudioClip> onClipReady)
		{
			if (!Voices.Contains(voice))
			{
				voice = GetRandomVoice();
			}
			string url = "https://api.streamelements.com/kappa/v2/speech?voice=" + voice + "&text=" + UnityWebRequest.EscapeURL(text);
			Plugin.Instance.LogInfoExtended("[TextToSpeech] Sending GET request to " + url);
			UnityWebRequest www = UnityWebRequestMultimedia.GetAudioClip(url, (AudioType)13);
			try
			{
				yield return www.SendWebRequest();
				if ((int)www.result == 2 || (int)www.result == 3)
				{
					Plugin.logger.LogError((object)("[TextToSpeech] Error fetching TTS audio: " + www.error));
					onClipReady(id, null);
				}
				else
				{
					AudioClip audioClip = DownloadHandlerAudioClip.GetContent(www);
					onClipReady(id, audioClip);
				}
			}
			finally
			{
				((IDisposable)www)?.Dispose();
			}
		}

		public static string GetRandomVoice()
		{
			return Voices[Random.Range(0, Voices.Length)];
		}
	}
	internal static class Utils
	{
		public static bool RemoveByValue<TKey, TValue>(Dictionary<TKey, TValue> dictionary, TValue value)
		{
			foreach (KeyValuePair<TKey, TValue> item in dictionary)
			{
				if (EqualityComparer<TValue>.Default.Equals(item.Value, value))
				{
					dictionary.Remove(item.Key);
					return true;
				}
			}
			return false;
		}

		public static Coroutine StartCoroutine(IEnumerator routine)
		{
			if ((Object)(object)Plugin.Instance != (Object)null)
			{
				return ((MonoBehaviour)Plugin.Instance).StartCoroutine(routine);
			}
			if ((Object)(object)GameNetworkManager.Instance != (Object)null)
			{
				return ((MonoBehaviour)GameNetworkManager.Instance).StartCoroutine(routine);
			}
			Plugin.logger.LogError((object)("Failed to start coroutine. " + routine));
			return null;
		}

		public static AudioClip AmplifyClipByDecibels(AudioClip originalClip, float decibelChange)
		{
			if ((Object)(object)originalClip == (Object)null)
			{
				return null;
			}
			float num = Mathf.Pow(10f, decibelChange / 20f);
			float[] array = new float[originalClip.samples * originalClip.channels];
			originalClip.GetData(array, 0);
			for (int i = 0; i < array.Length; i++)
			{
				array[i] *= num;
				array[i] = Mathf.Clamp(array[i], -1f, 1f);
			}
			AudioClip val = AudioClip.Create("AmplifiedClip", originalClip.samples, originalClip.channels, originalClip.frequency, false);
			val.SetData(array, 0);
			return val;
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "com.github.zehsteam.MelaniesVoice";

		public const string PLUGIN_NAME = "MelaniesVoice";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace com.github.zehsteam.MelaniesVoice.Patches
{
	[HarmonyPatch(typeof(GameNetworkManager))]
	internal static class GameNetworkManagerPatch
	{
		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		private static void StartPatch()
		{
			AddNetworkPrefabs();
		}

		private static void AddNetworkPrefabs()
		{
			AddNetworkPrefab(Content.VoiceControllerPrefab);
		}

		private static void AddNetworkPrefab(GameObject prefab)
		{
			if (!((Object)(object)prefab == (Object)null))
			{
				NetworkManager.Singleton.AddNetworkPrefab(prefab);
				Plugin.logger.LogInfo((object)("Registered \"" + ((Object)prefab).name + "\" network prefab."));
			}
		}
	}
	[HarmonyPatch(typeof(HUDManager))]
	internal static class HUDManagerPatch
	{
		[HarmonyPatch("AddTextToChatOnServer")]
		[HarmonyPostfix]
		private static void AddTextToChatOnServerPatch(string chatMessage, int playerId)
		{
			//IL_0047: 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)
			if (playerId == -1)
			{
				return;
			}
			PlayerControllerB localPlayerScript = PlayerUtils.GetLocalPlayerScript();
			if (!((Object)(object)localPlayerScript == (Object)null))
			{
				VoiceController componentInChildren = ((Component)localPlayerScript).GetComponentInChildren<VoiceController>();
				if (!((Object)(object)componentInChildren == (Object)null))
				{
					componentInChildren.CreateVoiceMessageServerRpc(chatMessage, Plugin.ConfigManager.TTS_Voice.Value);
				}
			}
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB))]
	internal static class PlayerControllerBPatch
	{
		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		private static void StartPatch(ref PlayerControllerB __instance)
		{
			if (NetworkUtils.IsServer)
			{
				GameObject val = Object.Instantiate<GameObject>(Content.VoiceControllerPrefab, ((Component)__instance).transform);
				val.GetComponent<NetworkObject>().Spawn(false);
				val.transform.SetParent(((Component)__instance).transform);
			}
		}

		[HarmonyPatch("OnDestroy")]
		[HarmonyPrefix]
		private static void OnDestroyPatch(ref PlayerControllerB __instance)
		{
			if (NetworkUtils.IsServer)
			{
				VoiceController componentInChildren = ((Component)__instance).GetComponentInChildren<VoiceController>();
				if (!((Object)(object)componentInChildren == (Object)null))
				{
					((Component)componentInChildren).GetComponent<NetworkObject>().Despawn(true);
				}
			}
		}
	}
}
namespace com.github.zehsteam.MelaniesVoice.MonoBehaviours
{
	public class VoiceController : NetworkBehaviour
	{
		public AudioSource VoiceAudio;

		public float NoiseRange = 30f;

		public float NoiseLoudness = 0.7f;

		private List<VoiceMessage> _voiceMessageQueue = new List<VoiceMessage>();

		private float _noiseTimer;

		private float _noiseCooldown = 0.2f;

		public PlayerControllerB PlayerScript { get; private set; }

		public bool IsLocal => PlayerUtils.IsLocalPlayer(PlayerScript);

		private void Start()
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			PlayerControllerB playerScript = default(PlayerControllerB);
			if ((Object)(object)((Component)this).transform.parent == (Object)null)
			{
				LogError("Failed to initialize. Transform parent is null.");
				if (NetworkUtils.IsServer)
				{
					((Component)this).GetComponent<NetworkObject>().Despawn(true);
				}
			}
			else if (!((Component)((Component)this).transform.parent).TryGetComponent<PlayerControllerB>(ref playerScript))
			{
				LogError("Failed to initialize. PlayerControllerB is null.");
				if (NetworkUtils.IsServer)
				{
					((Component)this).GetComponent<NetworkObject>().Despawn(true);
				}
			}
			else
			{
				PlayerScript = playerScript;
				((Component)this).transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity);
				UpdateSettings();
				SetAudioMixerGroup();
				LogInfoExtended("Initialized.");
			}
		}

		private void Update()
		{
			if (!NetworkUtils.IsServer || (Object)(object)VoiceAudio == (Object)null)
			{
				return;
			}
			if (VoiceAudio.isPlaying)
			{
				NoiseTick();
			}
			else
			{
				if (_voiceMessageQueue.Count == 0)
				{
					return;
				}
				VoiceMessage voiceMessage = _voiceMessageQueue[0];
				if (voiceMessage == null)
				{
					_voiceMessageQueue.RemoveAt(0);
					return;
				}
				if (voiceMessage.IsReady)
				{
					PlayVoiceMessageClientRpc(voiceMessage.Id);
					return;
				}
				voiceMessage.Tick();
				if (voiceMessage.IsTimedout)
				{
					_voiceMessageQueue.RemoveAt(0);
				}
			}
		}

		private void NoiseTick()
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)VoiceAudio == (Object)null) && VoiceAudio.isPlaying && !((Object)(object)PlayerScript == (Object)null))
			{
				if (_noiseTimer >= _noiseCooldown)
				{
					_noiseTimer = 0f;
					RoundManager.Instance.PlayAudibleNoise(((Component)PlayerScript).transform.position, NoiseRange, NoiseLoudness, 0, PlayerScript.isInHangarShipRoom && StartOfRound.Instance.hangarDoorsClosed, 75);
				}
				else
				{
					_noiseTimer += Time.deltaTime;
				}
			}
		}

		private void UpdateSettings()
		{
			if (!((Object)(object)VoiceAudio == (Object)null))
			{
				bool mute = false;
				if (!Plugin.ConfigManager.TTS_Enabled.Value)
				{
					mute = true;
				}
				if (IsLocal && !Plugin.ConfigManager.TTS_HearMyself.Value)
				{
					mute = true;
				}
				VoiceAudio.mute = mute;
				VoiceAudio.maxDistance = Plugin.ConfigManager.TTS_MaxDistance.Value;
			}
		}

		public static void OnSettingsChanged(object sender, EventArgs e)
		{
			VoiceController[] array = Object.FindObjectsByType<VoiceController>((FindObjectsSortMode)0);
			foreach (VoiceController voiceController in array)
			{
				voiceController.UpdateSettings();
			}
		}

		private void SetAudioMixerGroup()
		{
			if ((Object)(object)VoiceAudio == (Object)null || (Object)(object)PlayerScript == (Object)null)
			{
				LogError("Failed to set audio mixer group.");
				return;
			}
			if ((Object)(object)StartOfRound.Instance.playersVoiceMixerGroup == (Object)null)
			{
				LogError("Failed to set audio mixer group.");
				return;
			}
			string text = $"VoicePlayer{PlayerScript.playerClientId}";
			AudioMixerGroup[] array = StartOfRound.Instance.playersVoiceMixerGroup.audioMixer.FindMatchingGroups(text);
			if (array.Length == 0)
			{
				LogError("Failed to set audio mixer group.");
			}
			else
			{
				VoiceAudio.outputAudioMixerGroup = array[0];
			}
		}

		private VoiceMessage GetVoiceMessage(int id)
		{
			foreach (VoiceMessage item in _voiceMessageQueue)
			{
				if (item.Id == id)
				{
					return item;
				}
			}
			return null;
		}

		[ServerRpc(RequireOwnership = false)]
		public void CreateVoiceMessageServerRpc(string message, string voice, ServerRpcParams serverRpcParams = 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_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: 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_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: 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)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
			{
				FastBufferWriter val = ((NetworkBehaviour)this).__beginSendServerRpc(2570117490u, serverRpcParams, (RpcDelivery)0);
				bool flag = message != null;
				((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref flag, default(ForPrimitives));
				if (flag)
				{
					((FastBufferWriter)(ref val)).WriteValueSafe(message, false);
				}
				bool flag2 = voice != null;
				((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref flag2, default(ForPrimitives));
				if (flag2)
				{
					((FastBufferWriter)(ref val)).WriteValueSafe(voice, false);
				}
				((NetworkBehaviour)this).__endSendServerRpc(ref val, 2570117490u, serverRpcParams, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost))
			{
				ulong senderClientId = serverRpcParams.Receive.SenderClientId;
				if (((NetworkBehaviour)this).NetworkManager.ConnectedClients.ContainsKey(senderClientId) && !((Object)(object)PlayerScript == (Object)null) && PlayerScript.actualClientId == senderClientId)
				{
					int id = Random.Range(0, 1000000);
					CreateVoiceMessageClientRpc(id, message, voice);
				}
			}
		}

		[ClientRpc]
		private void CreateVoiceMessageClientRpc(int id, string message, string voice)
		{
			//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_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_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_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(2612776477u, val, (RpcDelivery)0);
				BytePacker.WriteValueBitPacked(val2, id);
				bool flag = message != null;
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag, default(ForPrimitives));
				if (flag)
				{
					((FastBufferWriter)(ref val2)).WriteValueSafe(message, false);
				}
				bool flag2 = voice != null;
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag2, default(ForPrimitives));
				if (flag2)
				{
					((FastBufferWriter)(ref val2)).WriteValueSafe(voice, false);
				}
				((NetworkBehaviour)this).__endSendClientRpc(ref val2, 2612776477u, val, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage != 2 || (!networkManager.IsClient && !networkManager.IsHost))
			{
				return;
			}
			VoiceMessage voiceMessage = new VoiceMessage(id, message, voice);
			_voiceMessageQueue.Add(voiceMessage);
			LogInfoExtended($"Created VoiceMessage. (Id: {voiceMessage.Id}, Message: \"{voiceMessage.Message}\", Voice: {voiceMessage.Voice})");
			if (NetworkUtils.IsServer)
			{
				if (!Plugin.ConfigManager.TTS_Enabled.Value && GameNetworkManager.Instance.connectedPlayers == 1)
				{
					OnReceivedVoiceMessageAudioClip(voiceMessage.Id, null);
					return;
				}
			}
			else
			{
				if (!Plugin.ConfigManager.TTS_Enabled.Value)
				{
					OnReceivedVoiceMessageAudioClip(voiceMessage.Id, null);
					return;
				}
				if (IsLocal && !Plugin.ConfigManager.TTS_HearMyself.Value)
				{
					OnReceivedVoiceMessageAudioClip(voiceMessage.Id, null);
					return;
				}
			}
			TextToSpeech.GetAudioClip(voiceMessage.Id, voiceMessage.Message, voiceMessage.Voice, OnReceivedVoiceMessageAudioClip);
		}

		private void OnReceivedVoiceMessageAudioClip(int id, AudioClip audioClip)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			VoiceMessage voiceMessage = GetVoiceMessage(id);
			if (voiceMessage != null)
			{
				voiceMessage.AudioClip = audioClip;
				ReceivedVoiceMessageAudioClipServerRpc(voiceMessage.Id);
			}
		}

		[ServerRpc(RequireOwnership = false)]
		private void ReceivedVoiceMessageAudioClipServerRpc(int id, ServerRpcParams serverRpcParams = 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_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_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: 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))
			{
				FastBufferWriter val = ((NetworkBehaviour)this).__beginSendServerRpc(1527114313u, serverRpcParams, (RpcDelivery)0);
				BytePacker.WriteValueBitPacked(val, id);
				((NetworkBehaviour)this).__endSendServerRpc(ref val, 1527114313u, serverRpcParams, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage != 1 || (!networkManager.IsServer && !networkManager.IsHost))
			{
				return;
			}
			ulong senderClientId = serverRpcParams.Receive.SenderClientId;
			if (((NetworkBehaviour)this).NetworkManager.ConnectedClients.ContainsKey(senderClientId))
			{
				VoiceMessage voiceMessage = GetVoiceMessage(id);
				if (voiceMessage != null && !voiceMessage.ClientsReceivedAudioClip.Contains(senderClientId))
				{
					voiceMessage.ClientsReceivedAudioClip.Add(senderClientId);
				}
			}
		}

		[ClientRpc]
		private void PlayVoiceMessageClientRpc(int id)
		{
			//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)
			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(3972401569u, val, (RpcDelivery)0);
				BytePacker.WriteValueBitPacked(val2, id);
				((NetworkBehaviour)this).__endSendClientRpc(ref val2, 3972401569u, val, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost))
			{
				VoiceMessage voiceMessage = GetVoiceMessage(id);
				if (voiceMessage == null)
				{
					LogWarningExtended($"Failed to play VoiceMessage. Could not find VoiceMessage. (Id: {id})");
					return;
				}
				if ((Object)(object)voiceMessage.AudioClip == (Object)null)
				{
					LogWarningExtended($"Failed to play VoiceMessage. AudioClip is null. (Id: {voiceMessage.Id}, Message: \"{voiceMessage.Message}\", Voice: {voiceMessage.Voice})");
					_voiceMessageQueue.Remove(voiceMessage);
					return;
				}
				LogInfoExtended($"Playing VoiceMessage. (Id: {voiceMessage.Id}, Message: \"{voiceMessage.Message}\", Voice: {voiceMessage.Voice})");
				VoiceAudio.clip = voiceMessage.AudioClip;
				VoiceAudio.Play();
				_voiceMessageQueue.Remove(voiceMessage);
			}
		}

		private void LogInfoExtended(object data)
		{
			Plugin.Instance.LogInfoExtended(GetLogHeader() + " " + data);
		}

		private void LogWarningExtended(object data)
		{
			Plugin.Instance.LogWarningExtended(GetLogHeader() + " " + data);
		}

		private void LogWarning(object data)
		{
			Plugin.logger.LogWarning((object)(GetLogHeader() + " " + data));
		}

		private void LogError(object data)
		{
			Plugin.logger.LogError((object)(GetLogHeader() + " " + data));
		}

		private string GetLogHeader()
		{
			if ((Object)(object)PlayerScript == (Object)null)
			{
				return "[VoiceController]";
			}
			return "[VoiceController : " + PlayerScript.playerUsername + "]";
		}

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

		[RuntimeInitializeOnLoadMethod]
		internal static void InitializeRPCS_VoiceController()
		{
			//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
			NetworkManager.__rpc_func_table.Add(2570117490u, new RpcReceiveHandler(__rpc_handler_2570117490));
			NetworkManager.__rpc_func_table.Add(2612776477u, new RpcReceiveHandler(__rpc_handler_2612776477));
			NetworkManager.__rpc_func_table.Add(1527114313u, new RpcReceiveHandler(__rpc_handler_1527114313));
			NetworkManager.__rpc_func_table.Add(3972401569u, new RpcReceiveHandler(__rpc_handler_3972401569));
		}

		private static void __rpc_handler_2570117490(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_0067: 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_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: 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));
				string message = null;
				if (flag)
				{
					((FastBufferReader)(ref reader)).ReadValueSafe(ref message, false);
				}
				bool flag2 = default(bool);
				((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag2, default(ForPrimitives));
				string voice = null;
				if (flag2)
				{
					((FastBufferReader)(ref reader)).ReadValueSafe(ref voice, false);
				}
				ServerRpcParams server = rpcParams.Server;
				target.__rpc_exec_stage = (__RpcExecStage)1;
				((VoiceController)(object)target).CreateVoiceMessageServerRpc(message, voice, server);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_2612776477(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_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_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				int id = default(int);
				ByteUnpacker.ReadValueBitPacked(reader, ref id);
				bool flag = default(bool);
				((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag, default(ForPrimitives));
				string message = null;
				if (flag)
				{
					((FastBufferReader)(ref reader)).ReadValueSafe(ref message, false);
				}
				bool flag2 = default(bool);
				((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag2, default(ForPrimitives));
				string voice = null;
				if (flag2)
				{
					((FastBufferReader)(ref reader)).ReadValueSafe(ref voice, false);
				}
				target.__rpc_exec_stage = (__RpcExecStage)2;
				((VoiceController)(object)target).CreateVoiceMessageClientRpc(id, message, voice);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_1527114313(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: 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)
			{
				int id = default(int);
				ByteUnpacker.ReadValueBitPacked(reader, ref id);
				ServerRpcParams server = rpcParams.Server;
				target.__rpc_exec_stage = (__RpcExecStage)1;
				((VoiceController)(object)target).ReceivedVoiceMessageAudioClipServerRpc(id, server);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_3972401569(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)
			{
				int id = default(int);
				ByteUnpacker.ReadValueBitPacked(reader, ref id);
				target.__rpc_exec_stage = (__RpcExecStage)2;
				((VoiceController)(object)target).PlayVoiceMessageClientRpc(id);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		protected internal override string __getTypeName()
		{
			return "VoiceController";
		}
	}
	public class VoiceMessage
	{
		private float _timer;

		public int Id { get; private set; }

		public string Message { get; private set; }

		public string Voice { get; private set; }

		public AudioClip AudioClip { get; set; }

		public List<ulong> ClientsReceivedAudioClip { get; private set; } = new List<ulong>();


		public bool IsReady
		{
			get
			{
				if (!ClientsReceivedAudioClip.Contains(NetworkUtils.GetLocalClientId()))
				{
					return false;
				}
				return ClientsReceivedAudioClip.Count >= GameNetworkManager.Instance.connectedPlayers;
			}
		}

		public bool IsTimedout => _timer >= 15f;

		public VoiceMessage(int id, string message, string voice)
		{
			Id = id;
			Message = message;
			Voice = voice;
		}

		public void Tick()
		{
			_timer += Time.deltaTime;
		}
	}
}
namespace com.github.zehsteam.MelaniesVoice.Dependencies
{
	internal static class LethalConfigProxy
	{
		public const string PLUGIN_GUID = "ainavt.lc.lethalconfig";

		public static bool Enabled => Chainloader.PluginInfos.ContainsKey("ainavt.lc.lethalconfig");

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static void SetModIcon(Sprite sprite)
		{
			LethalConfigManager.SetModIcon(sprite);
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static void SetModDescription(string description)
		{
			LethalConfigManager.SetModDescription(description);
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static void SkipAutoGen()
		{
			LethalConfigManager.SkipAutoGen();
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static void AddConfig<T>(ConfigEntry<T> configEntry, bool requiresRestart = false)
		{
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Expected O, but got Unknown
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Expected O, but got Unknown
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Expected O, but got Unknown
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Expected O, but got Unknown
			AcceptableValueBase acceptableValues = ((ConfigEntryBase)configEntry).Description.AcceptableValues;
			if (acceptableValues != null)
			{
				if (acceptableValues is AcceptableValueRange<float> || acceptableValues is AcceptableValueRange<int>)
				{
					AddConfigSlider<T>(configEntry, requiresRestart);
					return;
				}
				if (acceptableValues is AcceptableValueList<string>)
				{
					AddConfigDropdown<T>(configEntry, requiresRestart);
					return;
				}
			}
			if (!(configEntry is ConfigEntry<string> val))
			{
				if (!(configEntry is ConfigEntry<bool> val2))
				{
					if (!(configEntry is ConfigEntry<float> val3))
					{
						if (!(configEntry is ConfigEntry<int> val4))
						{
							throw new NotSupportedException($"Unsupported type: {typeof(T)}");
						}
						LethalConfigManager.AddConfigItem((BaseConfigItem)new IntInputFieldConfigItem(val4, requiresRestart));
					}
					else
					{
						LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatInputFieldConfigItem(val3, requiresRestart));
					}
				}
				else
				{
					LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(val2, requiresRestart));
				}
			}
			else
			{
				LethalConfigManager.AddConfigItem((BaseConfigItem)new TextInputFieldConfigItem(val, requiresRestart));
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static void AddConfigSlider<T>(ConfigEntry<T> configEntry, bool requiresRestart = false)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			if (!(configEntry is ConfigEntry<float> val))
			{
				if (!(configEntry is ConfigEntry<int> val2))
				{
					throw new NotSupportedException($"Slider not supported for type: {typeof(T)}");
				}
				LethalConfigManager.AddConfigItem((BaseConfigItem)new IntSliderConfigItem(val2, requiresRestart));
			}
			else
			{
				LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatSliderConfigItem(val, requiresRestart));
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static void AddConfigDropdown<T>(ConfigEntry<T> configEntry, bool requiresRestart = false)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			if (configEntry is ConfigEntry<string> val)
			{
				LethalConfigManager.AddConfigItem((BaseConfigItem)new TextDropDownConfigItem(val, requiresRestart));
				return;
			}
			throw new NotSupportedException($"Dropdown not supported for type: {typeof(T)}");
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static void AddButton(string section, string name, string description, string buttonText, Action callback)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			LethalConfigManager.AddConfigItem((BaseConfigItem)new GenericButtonConfigItem(section, name, description, buttonText, (GenericButtonHandler)delegate
			{
				callback?.Invoke();
			}));
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}
namespace com.github.zehsteam.MelaniesVoice.NetcodePatcher
{
	[AttributeUsage(AttributeTargets.Module)]
	internal class NetcodePatchedAssemblyAttribute : Attribute
	{
	}
}