Decompiled source of BigCamera v1.1.0

BigCamera.dll

Decompiled 17 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Unity.IL2CPP;
using BigMenu;
using Dissonance;
using Dissonance.Audio.Capture;
using Dissonance.Config;
using HarmonyLib;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using Mirror;
using TMPro;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("BigCamera")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("BigCamera")]
[assembly: AssemblyTitle("BigCamera")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace BigCamera
{
	internal static class BigMenuHook
	{
		private static readonly string[] NoiseLevels = new string[5] { "OFF", "LOW", "MODERATE", "HIGH", "VERY HIGH" };

		private static readonly string[] EchoLevels = new string[4] { "OFF", "LOW", "MODERATE", "HIGH" };

		private static string[] Mics()
		{
			return new string[1] { "Game's mic" }.Concat((IEnumerable<string>)Microphone.devices).ToArray();
		}

		public static void Register()
		{
			BigMenuApi.Register("Big Camera").AddToggle("VOICE LOOPBACK", (Func<bool>)(() => MicVoice.LoopbackOn), (Action<bool>)delegate(bool v)
			{
				MicVoice.LoopbackOn = v;
			}).AddChoice("LOOPBACK MIC", (Func<string[]>)Mics, (Func<int>)(() => Math.Max(0, Array.IndexOf(Mics(), Plugin.MicName.Value))), (Action<int>)delegate(int i)
			{
				Plugin.Set(Plugin.MicName, (i == 0) ? "" : Mics()[i]);
				MicVoice.RestartCapture();
			})
				.AddChoice("LOOPBACK OUTPUT", MicVoice.Routes, (Func<int>)(() => Math.Max(0, Array.IndexOf(MicVoice.Routes, Plugin.LoopbackRoute.Value))), (Action<int>)delegate(int i)
				{
					Plugin.Set(Plugin.LoopbackRoute, MicVoice.Routes[i]);
					MicVoice.RecreateSource();
				})
				.AddToggle("3D LOOPBACK", (Func<bool>)(() => Plugin.Loopback3D.Value), (Action<bool>)delegate(bool v)
				{
					Plugin.Set(Plugin.Loopback3D, v);
					MicVoice.RecreateSource();
				})
				.AddChoice("NOISE REDUCTION", NoiseLevels, (Func<int>)(() => VoiceSettings.Instance.DenoiseAmount + 1), (Action<int>)delegate(int i)
				{
					VoiceSettings.Instance.DenoiseAmount = (NoiseSuppressionLevels)(i - 1);
				})
				.AddChoice("ECHO REDUCTION", EchoLevels, (Func<int>)(() => VoiceSettings.Instance.AecSuppressionAmount + 1), (Action<int>)delegate(int i)
				{
					VoiceSettings.Instance.AecSuppressionAmount = (AecSuppressionLevels)(i - 1);
				})
				.AddToggle("BACKGROUND SOUND REMOVAL", (Func<bool>)(() => VoiceSettings.Instance.BackgroundSoundRemovalEnabled), (Action<bool>)delegate(bool v)
				{
					VoiceSettings.Instance.BackgroundSoundRemovalEnabled = v;
				})
				.AddSlider("MOUTH MULTIPLIER", 0f, 10f, 0.1f, (Func<float>)(() => Plugin.MouthGain.Value), (Action<float>)delegate(float v)
				{
					Plugin.Set(Plugin.MouthGain, v);
				}, "0.0", "x")
				.AddSlider("LOOPBACK VOLUME", 0f, 200f, 5f, (Func<float>)(() => Plugin.LoopbackVolume.Value * 100f), (Action<float>)delegate(float v)
				{
					Plugin.Set(Plugin.LoopbackVolume, v / 100f);
				}, "0", "%");
		}
	}
	public class CameraLocker : MonoBehaviour
	{
		private bool locked;

		private Vector3 pos;

		private Quaternion rot;

		private Vector3 savedLocalPos;

		private Quaternion savedLocalRot;

		public CameraLocker(IntPtr ptr)
			: base(ptr)
		{
		}

		private void Update()
		{
			//IL_0081: 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)
			//IL_003b: 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_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			if (!Input.GetKeyDown((KeyCode)288))
			{
				return;
			}
			Camera main = Camera.main;
			if (!((Object)(object)main == (Object)null))
			{
				locked = !locked;
				if (locked)
				{
					savedLocalPos = ((Component)main).transform.localPosition;
					savedLocalRot = ((Component)main).transform.localRotation;
					pos = ((Component)main).transform.position;
					rot = ((Component)main).transform.rotation;
				}
				else
				{
					((Component)main).transform.localPosition = savedLocalPos;
					((Component)main).transform.localRotation = savedLocalRot;
				}
				SetBodyMode(locked);
				MicVoice.CameraActive = locked;
			}
		}

		private void LateUpdate()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			if (locked)
			{
				Camera main = Camera.main;
				if ((Object)(object)main != (Object)null)
				{
					((Component)main).transform.SetPositionAndRotation(pos, rot);
				}
			}
		}

		private static void SetBodyMode(bool remote)
		{
			foreach (PlayerCharacter item in Object.FindObjectsOfType<PlayerCharacter>())
			{
				if (((NetworkBehaviour)item).isLocalPlayer && item.looks != null)
				{
					if (remote)
					{
						item.looks.SetBodyToRemoteMode();
					}
					else
					{
						item.looks.SetBodyToLocalMode();
					}
				}
			}
		}
	}
	internal static class MenuSettings
	{
		private sealed class Item
		{
			public string Title;

			public SettingsType Type;

			public Func<bool> GetOn;

			public Action<bool> SetOn;

			public Func<string[]> Options;

			public Func<int> GetIndex;

			public Action<int> SetIndex;

			public float Min;

			public float Max;

			public float Step;

			public Func<float> Get;

			public Action<float> Set;

			public string Format;

			public string Suffix;

			public int Steps => (int)Math.Round((Max - Min) / Step);

			public int ToStep(float v)
			{
				return Mathf.Clamp((int)Math.Round((v - Min) / Step), 0, Steps);
			}
		}

		private sealed class Pager
		{
			public SettingsCatagory Category;

			public SettingsRow PageRow;

			public SettingsRow[] Rows;

			public Vector3[] Positions;

			public int PerPage;

			public int Page;

			public int Pages => (Rows.Length + PerPage - 1) / PerPage;
		}

		private const SettingsType ToggleRow = (SettingsType)201;

		private const SettingsType ChoiceRow = (SettingsType)202;

		private const SettingsType SliderRow = (SettingsType)203;

		private const SettingsType PageType = (SettingsType)204;

		private static readonly MethodInfo SwapToCategoryMethod = AccessTools.Method(typeof(SettingsMenu), "SwapToCatagory", (Type[])null, (Type[])null);

		private static readonly Dictionary<int, Item> items = new Dictionary<int, Item>();

		private static bool configuringSlider;

		private static readonly string[] NoiseLevels = new string[5] { "OFF", "LOW", "MODERATE", "HIGH", "VERY HIGH" };

		private static readonly string[] EchoLevels = new string[4] { "OFF", "LOW", "MODERATE", "HIGH" };

		private static readonly Dictionary<int, Pager> pagers = new Dictionary<int, Pager>();

		private static string[] Mics()
		{
			return new string[1] { "Game's mic" }.Concat((IEnumerable<string>)Microphone.devices).ToArray();
		}

		private static Item Toggle(string title, Func<bool> get, Action<bool> set)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			return new Item
			{
				Title = title,
				Type = (SettingsType)201,
				GetOn = get,
				SetOn = set
			};
		}

		private static Item Choice(string title, Func<string[]> options, Func<int> get, Action<int> set)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			return new Item
			{
				Title = title,
				Type = (SettingsType)202,
				Options = options,
				GetIndex = get,
				SetIndex = set
			};
		}

		private static Item Slider(string title, float min, float max, float step, Func<float> get, Action<float> set, string format, string suffix)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			return new Item
			{
				Title = title,
				Type = (SettingsType)203,
				Min = min,
				Max = max,
				Step = step,
				Get = get,
				Set = set,
				Format = format,
				Suffix = suffix
			};
		}

		private static List<Item> Definitions()
		{
			return new List<Item>
			{
				Toggle("VOICE LOOPBACK", () => MicVoice.LoopbackOn, delegate(bool v)
				{
					MicVoice.LoopbackOn = v;
				}),
				Choice("LOOPBACK MIC", Mics, () => Math.Max(0, Array.IndexOf(Mics(), Plugin.MicName.Value)), delegate(int i)
				{
					Plugin.Set(Plugin.MicName, (i == 0) ? "" : Mics()[i]);
					MicVoice.RestartCapture();
				}),
				Choice("LOOPBACK OUTPUT", () => MicVoice.Routes, () => Math.Max(0, Array.IndexOf(MicVoice.Routes, Plugin.LoopbackRoute.Value)), delegate(int i)
				{
					Plugin.Set(Plugin.LoopbackRoute, MicVoice.Routes[i]);
					MicVoice.RecreateSource();
				}),
				Toggle("3D LOOPBACK", () => Plugin.Loopback3D.Value, delegate(bool v)
				{
					Plugin.Set(Plugin.Loopback3D, v);
					MicVoice.RecreateSource();
				}),
				Choice("NOISE REDUCTION", () => NoiseLevels, () => VoiceSettings.Instance.DenoiseAmount + 1, delegate(int i)
				{
					VoiceSettings.Instance.DenoiseAmount = (NoiseSuppressionLevels)(i - 1);
				}),
				Choice("ECHO REDUCTION", () => EchoLevels, () => VoiceSettings.Instance.AecSuppressionAmount + 1, delegate(int i)
				{
					VoiceSettings.Instance.AecSuppressionAmount = (AecSuppressionLevels)(i - 1);
				}),
				Toggle("BACKGROUND SOUND REMOVAL", () => VoiceSettings.Instance.BackgroundSoundRemovalEnabled, delegate(bool v)
				{
					VoiceSettings.Instance.BackgroundSoundRemovalEnabled = v;
				}),
				Slider("MOUTH MULTIPLIER", 0f, 10f, 0.1f, () => Plugin.MouthGain.Value, delegate(float v)
				{
					Plugin.Set(Plugin.MouthGain, v);
				}, "0.0", "x"),
				Slider("LOOPBACK VOLUME", 0f, 200f, 5f, () => Plugin.LoopbackVolume.Value * 100f, delegate(float v)
				{
					Plugin.Set(Plugin.LoopbackVolume, v / 100f);
				}, "0", "%")
			};
		}

		private static bool IsOurs(SettingsRow row)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Invalid comparison between Unknown and I4
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Invalid comparison between Unknown and I4
			if ((int)row.settingsType >= 201)
			{
				return (int)row.settingsType <= 204;
			}
			return false;
		}

		internal static void Install(Harmony harmony)
		{
			Patch(harmony, typeof(MainMenuManager), "Awake", "AddMainMenuCategory", postfix: true);
			Patch(harmony, typeof(WorldMenuManager), "Awake", "AddPauseMenuCategory", postfix: true);
			Patch(harmony, typeof(SettingsRow), "Start", "StartRow", postfix: false);
			Patch(harmony, typeof(SettingsRow), "OnEnable", "EnableRow", postfix: false);
			Patch(harmony, typeof(SettingsRow), "Refresh", "RefreshRow", postfix: false);
			Patch(harmony, typeof(SettingsRow), "ActionCycle", "CycleRow", postfix: false);
			Patch(harmony, typeof(SettingsRow), "ActionSelect", "SelectRow", postfix: false);
			Patch(harmony, typeof(SettingsRow), "ActionNavigate", "NavigateRow", postfix: false);
			Patch(harmony, typeof(SettingsRow), "ActionSetFromSlider", "SetSliderRow", postfix: false);
			Patch(harmony, typeof(SettingsRow), "ActionBack", "BackFromRow", postfix: false);
		}

		private static void Patch(Harmony harmony, Type type, string method, string handler, bool postfix)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			HarmonyMethod val = new HarmonyMethod(typeof(MenuSettings), handler, (Type[])null);
			MethodInfo methodInfo = AccessTools.Method(type, method, (Type[])null, (Type[])null);
			if (postfix)
			{
				harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			else
			{
				harmony.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
		}

		private static void AddMainMenuCategory(MainMenuManager __instance)
		{
			AddCategory(__instance.settingsMenu);
		}

		private static void AddPauseMenuCategory(WorldMenuManager __instance)
		{
			AddCategory(__instance.settingsMenu);
		}

		private static void ShowPage(Pager pager, int page)
		{
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			pager.Page = Mathf.Clamp(page, 0, pager.Pages - 1);
			List<SettingsRow> list = new List<SettingsRow>();
			if ((Object)(object)pager.PageRow != (Object)null)
			{
				list.Add(pager.PageRow);
			}
			int num = pager.Page * pager.PerPage;
			for (int i = 0; i < pager.Rows.Length; i++)
			{
				bool flag = i >= num && i < num + pager.PerPage;
				((Component)pager.Rows[i]).gameObject.SetActive(flag);
				if (flag)
				{
					list.Add(pager.Rows[i]);
				}
			}
			for (int j = 0; j < list.Count; j++)
			{
				((Component)list[j]).transform.localPosition = pager.Positions[j];
				list[j].SetNavigation((j == 0) ? null : list[j - 1], (j == list.Count - 1) ? null : list[j + 1]);
				Refresh(list[j]);
			}
			pager.Category.rows = new Il2CppReferenceArray<SettingsRow>(list.ToArray());
		}

		private static void AddCategory(SettingsMenu menu)
		{
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Invalid comparison between Unknown and I4
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Invalid comparison between Unknown and I4
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Invalid comparison between Unknown and I4
			//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c1: Invalid comparison between Unknown and I4
			//IL_03bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0405: Expected O, but got Unknown
			//IL_0442: Unknown result type (might be due to invalid IL or missing references)
			//IL_0449: Invalid comparison between Unknown and I4
			//IL_044d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0457: Expected O, but got Unknown
			List<Item> list = Definitions();
			SettingsCatagory category = Object.Instantiate<GameObject>(((Component)menu.catagoryGraphics).gameObject, ((Component)menu.catagoryGraphics).transform.parent, false).GetComponent<SettingsCatagory>();
			((Object)((Component)category).gameObject).name = "BigCamera Settings";
			((Component)category).gameObject.SetActive(false);
			Il2CppReferenceArray<SettingsRow> rows = category.rows;
			SettingsRow val = FindRow(menu.catagoryControls, (SettingsType)41);
			SettingsRow val2 = FindRow(menu.catagoryGraphics, (SettingsType)33);
			SettingsRow val3 = FindRow(menu.catagoryControls, (SettingsType)44);
			bool flag = list.Count > ((Il2CppArrayBase<SettingsRow>)(object)rows).Length;
			Pager pager = new Pager
			{
				Category = category,
				PerPage = (flag ? (((Il2CppArrayBase<SettingsRow>)(object)rows).Length - 1) : ((Il2CppArrayBase<SettingsRow>)(object)rows).Length),
				Positions = ((IEnumerable<SettingsRow>)rows).Select((SettingsRow s) => ((Component)s).transform.localPosition).ToArray()
			};
			if (flag)
			{
				pager.PageRow = CloneRow(val2, ((Il2CppArrayBase<SettingsRow>)(object)rows)[0], pager.Positions[0], new Item
				{
					Title = "PAGE",
					Type = (SettingsType)204
				});
				pager.PageRow.wrap = false;
				pagers[((Object)pager.PageRow).GetInstanceID()] = pager;
			}
			SettingsRow[] array = (SettingsRow[])(object)new SettingsRow[list.Count];
			for (int num = 0; num < list.Count; num++)
			{
				Item item = list[num];
				SettingsRow template = (((int)item.Type == 201) ? val : (((int)item.Type == 202) ? val2 : val3));
				array[num] = CloneRow(template, ((Il2CppArrayBase<SettingsRow>)(object)rows)[0], pager.Positions[0], item);
				items[((Object)array[num]).GetInstanceID()] = item;
			}
			pager.Rows = array;
			for (int num2 = 0; num2 < ((Il2CppArrayBase<SettingsRow>)(object)rows).Length; num2++)
			{
				Object.Destroy((Object)(object)((Component)((Il2CppArrayBase<SettingsRow>)(object)rows)[num2]).gameObject);
			}
			for (int num3 = 0; num3 < array.Length; num3++)
			{
				Item item2 = list[num3];
				if ((int)item2.Type == 201)
				{
					SetRawText(array[num3].label0, "ON");
					SetRawText(array[num3].label1, "OFF");
					if ((Object)(object)array[num3].label2 != (Object)null)
					{
						((Component)array[num3].label2).gameObject.SetActive(false);
					}
				}
				else if ((int)item2.Type == 202)
				{
					array[num3].wrap = false;
				}
				else
				{
					ConfigureSlider(array[num3], item2.Steps);
				}
			}
			ShowPage(pager, 0);
			DisableResetButton(category);
			Button component = ((Component)menu.catagoryControls.catagoryButton).GetComponent<Button>();
			Transform val4 = FindCommonParent(((Component)component).transform, ((Component)menu.catagoryAudio.catagoryButton).transform);
			Transform val5 = FindChildUnder(((Component)component).transform, val4);
			Transform val6 = FindChildUnder(((Component)menu.catagoryAudio.catagoryButton).transform, val4);
			Transform child = val4.GetChild(val4.childCount - 1);
			Button controlsButton = ((Component)child).GetComponentInChildren<Button>(true) ?? component;
			GameObject obj = Object.Instantiate<GameObject>(((Component)val5).gameObject, val4, false);
			((Object)obj).name = "BigCamera Category";
			obj.transform.SetAsLastSibling();
			obj.transform.localPosition = child.localPosition + val5.localPosition - val6.localPosition;
			Button componentInChildren = obj.GetComponentInChildren<Button>(true);
			((Component)componentInChildren).GetComponentInChildren<LocalizedText>(true).Change("Big Camera", (DisplayType)1);
			componentInChildren.onClick = new ButtonClickedEvent();
			((UnityEvent)componentInChildren.onClick).AddListener(UnityAction.op_Implicit((Action)delegate
			{
				SwapToCategoryMethod.Invoke(menu, new object[1] { category });
			}));
			Enumerator<Entry> enumerator = ((Component)componentInChildren).GetComponent<EventTrigger>().triggers.GetEnumerator();
			while (enumerator.MoveNext())
			{
				Entry current = enumerator.Current;
				if ((int)current.eventID == 9)
				{
					current.callback = new TriggerEvent();
					((UnityEvent<BaseEventData>)(object)current.callback).AddListener(UnityAction<BaseEventData>.op_Implicit((Action<BaseEventData>)delegate
					{
						menu.NavigateToCatagory(category);
					}));
				}
			}
			category.catagoryButton = (Selectable)(object)componentInChildren;
			menu.buttonList.Add(componentInChildren);
			LinkNavigation(menu, controlsButton, componentInChildren);
			LayoutRebuilder.ForceRebuildLayoutImmediate(((Component)val4).GetComponent<RectTransform>());
		}

		private unsafe static SettingsRow FindRow(SettingsCatagory category, SettingsType type)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			foreach (SettingsRow item in (Il2CppArrayBase<SettingsRow>)(object)category.rows)
			{
				if (item.settingsType == type)
				{
					return item;
				}
			}
			throw new InvalidOperationException("Settings row " + ((object)(*(SettingsType*)(&type))/*cast due to .constrained prefix*/).ToString() + " was not found.");
		}

		private static SettingsRow CloneRow(SettingsRow template, SettingsRow slot, Vector3 position, Item item)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = Object.Instantiate<GameObject>(((Component)template).gameObject, ((Component)slot).transform.parent, false);
			((Object)obj).name = "BigCamera " + item.Title;
			obj.transform.localPosition = position;
			obj.transform.localRotation = ((Component)slot).transform.localRotation;
			obj.transform.localScale = ((Component)slot).transform.localScale;
			obj.transform.SetSiblingIndex(((Component)slot).transform.GetSiblingIndex());
			SettingsRow component = obj.GetComponent<SettingsRow>();
			component.settingsType = item.Type;
			foreach (TMP_Text componentsInChild in obj.GetComponentsInChildren<TMP_Text>(true))
			{
				if (!(((Object)((Component)componentsInChild).gameObject).name != "Title"))
				{
					SetRawText(componentsInChild, item.Title);
					break;
				}
			}
			return component;
		}

		private static void SetRawText(TMP_Text text, string value)
		{
			LocalizedText component = ((Component)text).GetComponent<LocalizedText>();
			if ((Object)(object)component != (Object)null)
			{
				((Behaviour)component).enabled = false;
			}
			text.text = value;
		}

		private static void ConfigureSlider(SettingsRow row, int steps)
		{
			configuringSlider = true;
			row.slider.minValue = 0f;
			row.slider.maxValue = steps;
			row.slider.wholeNumbers = true;
			configuringSlider = false;
		}

		private static void DisableResetButton(SettingsCatagory category)
		{
			foreach (Button componentsInChild in ((Component)category).GetComponentsInChildren<Button>(true))
			{
				for (int i = 0; i < ((UnityEventBase)componentsInChild.onClick).GetPersistentEventCount(); i++)
				{
					if (((UnityEventBase)componentsInChild.onClick).GetPersistentMethodName(i) == "ActionResetControls")
					{
						((Component)componentsInChild).gameObject.SetActive(false);
					}
				}
			}
		}

		private static Transform FindCommonParent(Transform first, Transform second)
		{
			Transform parent = first.parent;
			while (!second.IsChildOf(parent))
			{
				parent = parent.parent;
			}
			return parent;
		}

		private static Transform FindChildUnder(Transform child, Transform parent)
		{
			while ((Object)(object)child.parent != (Object)(object)parent)
			{
				child = child.parent;
			}
			return child;
		}

		private static void LinkNavigation(SettingsMenu menu, Button controlsButton, Button ours)
		{
			Navigation navigation = ((Selectable)controlsButton).navigation;
			Navigation navigation2 = ((Selectable)ours).navigation;
			navigation.selectOnDown = (Selectable)(object)ours;
			navigation2.selectOnUp = (Selectable)(object)controlsButton;
			navigation2.selectOnDown = menu.catagoryGeneral.catagoryButton;
			((Selectable)controlsButton).navigation = navigation;
			((Selectable)ours).navigation = navigation2;
		}

		private static bool StartRow(SettingsRow __instance)
		{
			if (!IsOurs(__instance))
			{
				return true;
			}
			__instance.settingsMenu = ((Component)__instance).GetComponentInParent<SettingsMenu>(true);
			Refresh(__instance);
			return false;
		}

		private static bool EnableRow(SettingsRow __instance)
		{
			if (!IsOurs(__instance))
			{
				return true;
			}
			Refresh(__instance);
			return false;
		}

		private static bool RefreshRow(SettingsRow __instance)
		{
			if (!IsOurs(__instance))
			{
				return true;
			}
			Refresh(__instance);
			return false;
		}

		private static bool NavigateRow(SettingsRow __instance)
		{
			return !IsOurs(__instance);
		}

		private static bool BackFromRow(SettingsRow __instance)
		{
			if (!IsOurs(__instance))
			{
				return true;
			}
			__instance.settingsMenu.GoBackFromCatagory();
			return false;
		}

		private static bool CycleRow(SettingsRow __instance, int delta)
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Invalid comparison between Unknown and I4
			if (!IsOurs(__instance))
			{
				return true;
			}
			if (pagers.TryGetValue(((Object)__instance).GetInstanceID(), out var value))
			{
				ShowPage(value, value.Page + delta);
				return false;
			}
			if (items.TryGetValue(((Object)__instance).GetInstanceID(), out var item) && (int)item.Type == 202)
			{
				int index = Math.Clamp(item.GetIndex() + delta, 0, item.Options().Length - 1);
				Try(delegate
				{
					item.SetIndex(index);
				});
				Refresh(__instance);
			}
			return false;
		}

		private static bool SelectRow(SettingsRow __instance, int valueIndex)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Invalid comparison between Unknown and I4
			if (!IsOurs(__instance))
			{
				return true;
			}
			if (items.TryGetValue(((Object)__instance).GetInstanceID(), out var item) && (int)item.Type == 201)
			{
				Try(delegate
				{
					item.SetOn(valueIndex == 0);
				});
				Refresh(__instance);
			}
			return false;
		}

		private static bool SetSliderRow(SettingsRow __instance)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Invalid comparison between Unknown and I4
			if (!IsOurs(__instance))
			{
				return true;
			}
			if (configuringSlider)
			{
				return false;
			}
			if (items.TryGetValue(((Object)__instance).GetInstanceID(), out var item) && (int)item.Type == 203)
			{
				float value = item.Min + (float)Mathf.RoundToInt(__instance.slider.value) * item.Step;
				Try(delegate
				{
					item.Set(value);
				});
				Refresh(__instance);
			}
			return false;
		}

		private static void Try(Action action)
		{
			try
			{
				action();
			}
			catch (Exception ex)
			{
				((BasePlugin)Plugin.Instance).Log.LogWarning((object)ex.Message);
			}
		}

		private static T Read<T>(Func<T> get, T fallback)
		{
			try
			{
				return get();
			}
			catch
			{
				return fallback;
			}
		}

		private static void Refresh(SettingsRow row)
		{
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Invalid comparison between Unknown and I4
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Invalid comparison between Unknown and I4
			if (pagers.TryGetValue(((Object)row).GetInstanceID(), out var value))
			{
				row.arrayLabel.Change(value.Page + 1 + " / " + value.Pages, (DisplayType)1);
				((Selectable)row.leftButton).interactable = value.Page > 0;
				((Selectable)row.rightButton).interactable = value.Page < value.Pages - 1;
			}
			else
			{
				if (!items.TryGetValue(((Object)row).GetInstanceID(), out var value2))
				{
					return;
				}
				if ((int)value2.Type == 201)
				{
					bool flag = Read(value2.GetOn, fallback: false);
					row.SetUnderlineSingle(row.label0, flag);
					row.SetUnderlineSingle(row.label1, !flag);
				}
				else if ((int)value2.Type == 202)
				{
					string[] array = value2.Options();
					int num = Math.Clamp(Read(value2.GetIndex, 0), 0, array.Length - 1);
					string text = array[num];
					if (text.Length > 24)
					{
						text = text.Substring(0, 24);
					}
					row.arrayLabel.Change(text, (DisplayType)1);
					((Selectable)row.leftButton).interactable = num > 0;
					((Selectable)row.rightButton).interactable = num < array.Length - 1;
				}
				else
				{
					float v = Read(value2.Get, value2.Min);
					configuringSlider = true;
					row.slider.SetValueWithoutNotify((float)value2.ToStep(v));
					configuringSlider = false;
					row.sliderLabel.Change(v.ToString(value2.Format) + value2.Suffix, (DisplayType)1);
				}
			}
		}
	}
	public class MicVoice : MonoBehaviour
	{
		public const string RouteDirect = "Direct";

		public static readonly string[] Routes = new string[3] { "Self Voice", "Voice", "Direct" };

		public static float Level;

		public static bool LoopbackOn = true;

		public static bool CameraActive;

		private const int Window = 512;

		private const int CopyWindow = 4096;

		private static bool restart;

		private static bool recreate;

		private AudioClip clip;

		private AudioClip mirror;

		private AudioSource source;

		private PlayerCharacter local;

		private string device;

		private bool ownCapture;

		private float findTimer;

		private Il2CppStructArray<float> buffer;

		private Il2CppStructArray<float> copy;

		public MicVoice(IntPtr ptr)
			: base(ptr)
		{
		}

		public static void RestartCapture()
		{
			restart = true;
		}

		public static void RecreateSource()
		{
			recreate = true;
		}

		private void Awake()
		{
			buffer = new Il2CppStructArray<float>(512L);
			copy = new Il2CppStructArray<float>(4096L);
		}

		private void Update()
		{
			if (Input.GetKeyDown((KeyCode)289))
			{
				LoopbackOn = !LoopbackOn;
			}
			if (restart)
			{
				ResetCapture();
				findTimer = 0f;
			}
			findTimer -= Time.unscaledDeltaTime;
			if (findTimer <= 0f)
			{
				findTimer = 1f;
				if ((Object)(object)local == (Object)null)
				{
					local = FindLocal();
				}
				if ((Object)(object)clip == (Object)null)
				{
					FindClip();
				}
			}
			if ((Object)(object)clip == (Object)null)
			{
				Level = 0f;
				return;
			}
			int samples = clip.samples;
			int position = Microphone.GetPosition(device);
			if (position <= 0)
			{
				Level = 0f;
				return;
			}
			clip.GetData(buffer, Wrap(position - 512, samples));
			float num = 0f;
			for (int i = 0; i < 512; i++)
			{
				num += ((Il2CppArrayBase<float>)(object)buffer)[i] * ((Il2CppArrayBase<float>)(object)buffer)[i];
			}
			float num2 = Mathf.Sqrt(num / 512f);
			Level = Mathf.Lerp(Level, Mathf.Clamp01(num2 * Plugin.MouthGain.Value), 0.5f);
			UpdateLoopback(position, samples);
		}

		private static int Wrap(int i, int len)
		{
			return (i % len + len) % len;
		}

		private static PlayerCharacter FindLocal()
		{
			foreach (PlayerCharacter item in Object.FindObjectsOfType<PlayerCharacter>())
			{
				if (((NetworkBehaviour)item).isLocalPlayer)
				{
					return item;
				}
			}
			return null;
		}

		private void ResetCapture()
		{
			restart = false;
			if ((Object)(object)source != (Object)null)
			{
				source.Stop();
			}
			if (ownCapture && device != null)
			{
				Microphone.End(device);
			}
			if ((Object)(object)mirror != (Object)null)
			{
				Object.Destroy((Object)(object)mirror);
			}
			clip = null;
			mirror = null;
			device = null;
			ownCapture = false;
		}

		private void FindClip()
		{
			string value = Plugin.MicName.Value;
			if (string.IsNullOrEmpty(value))
			{
				DissonanceComms obj = Object.FindObjectOfType<DissonanceComms>();
				object obj2;
				if (obj == null)
				{
					obj2 = null;
				}
				else
				{
					IMicrophoneCapture microphoneCapture = obj.MicrophoneCapture;
					obj2 = ((microphoneCapture != null) ? ((Il2CppObjectBase)microphoneCapture).TryCast<BasicMicrophoneCapture>() : null);
				}
				BasicMicrophoneCapture val = (BasicMicrophoneCapture)obj2;
				if ((Object)(object)val != (Object)null && (Object)(object)val.Clip != (Object)null && !string.IsNullOrEmpty(val.Device))
				{
					clip = val.Clip;
					device = val.Device;
					return;
				}
			}
			Il2CppStringArray devices = Microphone.devices;
			if (((Il2CppArrayBase<string>)(object)devices).Length == 0)
			{
				return;
			}
			device = ((Il2CppArrayBase<string>)(object)devices)[0];
			foreach (string item in (Il2CppArrayBase<string>)(object)devices)
			{
				if (!string.IsNullOrEmpty(value) && item.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0)
				{
					device = item;
					break;
				}
			}
			clip = Microphone.Start(device, true, 1, 48000);
			ownCapture = true;
		}

		private void UpdateLoopback(int head, int len)
		{
			if (!LoopbackOn || !CameraActive || (Object)(object)local == (Object)null)
			{
				if ((Object)(object)source != (Object)null && source.isPlaying)
				{
					source.Stop();
				}
				return;
			}
			if ((Object)(object)mirror == (Object)null || mirror.samples != len || mirror.frequency != clip.frequency)
			{
				if ((Object)(object)mirror != (Object)null)
				{
					Object.Destroy((Object)(object)mirror);
				}
				mirror = AudioClip.Create("BigCamera_Mirror", len, clip.channels, clip.frequency, false);
				recreate = true;
			}
			int num = Wrap(head - 4096, len);
			clip.GetData(copy, num);
			mirror.SetData(copy, num);
			if (recreate)
			{
				recreate = false;
				if ((Object)(object)source != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)source).gameObject);
				}
				source = null;
			}
			if ((Object)(object)source == (Object)null)
			{
				CreateSource();
			}
			int num2 = Wrap(head - clip.frequency / 20, len);
			if (!source.isPlaying)
			{
				source.timeSamples = num2;
				source.Play();
			}
			source.volume = Plugin.LoopbackVolume.Value;
			int num3 = Math.Abs(source.timeSamples - num2);
			if (Math.Min(num3, len - num3) > clip.frequency / 7)
			{
				source.timeSamples = num2;
			}
		}

		private void CreateSource()
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			Transform val = ((local.looks != null && local.lips != null && (Object)(object)local.lips.lipTransform != (Object)null) ? local.lips.lipTransform : ((Component)local).transform);
			GameObject val2 = new GameObject("BigCamera_VoiceLoopback");
			val2.transform.SetParent(val, false);
			source = val2.AddComponent<AudioSource>();
			source.clip = mirror;
			source.loop = true;
			source.spatialBlend = (Plugin.Loopback3D.Value ? 1f : 0f);
			source.rolloffMode = (AudioRolloffMode)0;
			string value = Plugin.LoopbackRoute.Value;
			if (value == "Direct")
			{
				return;
			}
			foreach (AudioMixerGroup item in Resources.FindObjectsOfTypeAll<AudioMixerGroup>())
			{
				if (((Object)item).name == value)
				{
					source.outputAudioMixerGroup = item;
					break;
				}
			}
		}
	}
	[HarmonyPatch(typeof(PlayerLips), "Update")]
	internal static class LipsPatch
	{
		private static void Prefix(PlayerLips __instance)
		{
			PlayerCharacter playerCharacter = __instance.playerCharacter;
			if ((Object)(object)playerCharacter != (Object)null && ((NetworkBehaviour)playerCharacter).isLocalPlayer)
			{
				__instance.amplitude = MicVoice.Level;
			}
		}
	}
	[BepInPlugin("com.eggdog.bigwalk.bigcamera", "BigCamera", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BasePlugin
	{
		public static Plugin Instance;

		public static ConfigEntry<string> MicName;

		public static ConfigEntry<float> MouthGain;

		public static ConfigEntry<float> LoopbackVolume;

		public static ConfigEntry<string> LoopbackRoute;

		public static ConfigEntry<bool> Loopback3D;

		public override void Load()
		{
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Expected O, but got Unknown
			Instance = this;
			MicName = ((BasePlugin)this).Config.Bind<string>("Voice", "LoopbackMic", "", "Part of the mic device name to use. Empty uses the game's mic");
			MouthGain = ((BasePlugin)this).Config.Bind<float>("Voice", "MouthGain", 2.5f, "How strongly your mic level opens your mouth");
			LoopbackVolume = ((BasePlugin)this).Config.Bind<float>("Voice", "LoopbackVolume", 1f, "Volume of the voice loopback");
			LoopbackRoute = ((BasePlugin)this).Config.Bind<string>("Voice", "LoopbackRoute", "Self Voice", "Self Voice, Voice, or Direct (no mixer group)");
			Loopback3D = ((BasePlugin)this).Config.Bind<bool>("Voice", "Loopback3D", true, "Play the loopback from your mouth instead of flat in your ears");
			ClassInjector.RegisterTypeInIl2Cpp<CameraLocker>();
			ClassInjector.RegisterTypeInIl2Cpp<MicVoice>();
			((BasePlugin)this).AddComponent<CameraLocker>();
			((BasePlugin)this).AddComponent<MicVoice>();
			Harmony val = new Harmony("com.eggdog.bigwalk.bigcamera");
			val.PatchAll();
			if (((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins.ContainsKey("com.eggdog.bigmenu"))
			{
				BigMenuHook.Register();
			}
			else
			{
				MenuSettings.Install(val);
			}
		}

		public static void Set<T>(ConfigEntry<T> entry, T value)
		{
			entry.Value = value;
			((BasePlugin)Instance).Config.Save();
		}
	}
}