Decompiled source of Crispberry PiPhone v0.17.69

tony4twentys-Crispberry PiPhone.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using BepInEx;
using BepInEx.Configuration;
using ExitGames.Client.Photon;
using HarmonyLib;
using Photon.Pun;
using Photon.Realtime;
using Photon.Voice;
using Photon.Voice.Unity;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.TextCore;
using UnityEngine.UI;
using Zorro.Core;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("PhotonVoice")]
[assembly: AssemblyTitle("Crispberry PiPhone")]
[assembly: AssemblyDescription("Android-style in-game phone for PEAK, with a public app API.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("tony4twentys")]
[assembly: AssemblyProduct("Crispberry PiPhone")]
[assembly: AssemblyCopyright("Copyright © 2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("b86841f9-1cd5-41de-ba99-f10d663d2700")]
[assembly: AssemblyFileVersion("0.17.69.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.17.69.0")]
[module: UnverifiableCode]
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}
namespace Crispberry_PiPhone
{
	[BepInPlugin("tony4twentys.Crispberry_PiPhone", "Crispberry PiPhone", "0.17.69")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInProcess("PEAK.exe")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "tony4twentys.Crispberry_PiPhone";

		public const string PluginName = "Crispberry PiPhone";

		public const string PluginVersion = "0.17.69";

		public const string OsName = "Crispberry OS";

		internal const byte PhotonEventCode = 185;

		internal const string EventMagic = "tony4twentys.Crispberry_PiPhone";

		public static Plugin Instance;

		public ConfigEntry<KeyCode> MenuKey;

		public ConfigEntry<KeyCode> MenuModifier;

		public ConfigEntry<bool> ShowPauseMenuButton;

		public ConfigEntry<KeyCode> CameraCursorKey;

		public ConfigEntry<KeyCode> CameraFlipKey;

		public ConfigEntry<KeyCode> CameraRotateKey;

		public ConfigEntry<KeyCode> CameraShutterKey;

		public ConfigEntry<KeyCode> AnswerKey;

		public ConfigEntry<KeyCode> DeclineKey;

		public ConfigEntry<KeyCode> LandscapeKey;

		public ConfigEntry<string> TenorApiKey;

		internal static bool CapturingHotkey;

		internal static int CaptureEndedFrame = -1;

		private Harmony _harmony;

		public static string OsVersionLabel => "Crispberry OS 0.17.69";

		private void Awake()
		{
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Expected O, but got Unknown
			Instance = this;
			MenuKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "MenuKey", (KeyCode)112, "Opens the phone. Used with MenuModifier.");
			MenuModifier = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "MenuModifier", (KeyCode)308, "Hold this with MenuKey. Set to None for the key alone.");
			ShowPauseMenuButton = ((BaseUnityPlugin)this).Config.Bind<bool>("Controls", "ShowPauseMenuButton", true, "Add a PiPhone button to the pause menu.");
			CameraCursorKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Camera", "CursorKey", (KeyCode)308, "While Camera is open: show or hide the cursor. Only this app uses it.");
			CameraFlipKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Camera", "FlipKey", (KeyCode)102, "While Camera is open: flip front/back. Does not stop a recording.");
			CameraRotateKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Camera", "RotateKey", (KeyCode)114, "While Camera is open: tall/wide. Does not stop a recording.");
			CameraShutterKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Camera", "ShutterKey", (KeyCode)118, "While Camera is open: photo snaps, video starts or stops.");
			AnswerKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Alerts", "AnswerKey", (KeyCode)282, "Answer an incoming call, or open the latest text in Messages.");
			DeclineKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Alerts", "DeclineKey", (KeyCode)283, "Decline an incoming call, or dismiss a text banner.");
			LandscapeKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "LandscapeKey", (KeyCode)284, "While the phone is open: switch portrait and landscape (same phone shape).");
			TenorApiKey = ((BaseUnityPlugin)this).Config.Bind<string>("Network", "TenorApiKey", "", "Optional Google Tenor API key for GIF search. Leave blank to use the built-in Tenor search page.");
			PhoneStore.Load();
			PhoneTheme.Load();
			PhoneLang.Ensure();
			PhoneTones.Load();
			PhoneContacts.Ensure();
			VoiceIo.Ensure();
			MusicPlayer.Ensure();
			PhoneNet.Ensure();
			CallService.Ensure();
			AlertHud.Ensure();
			PhoneMenu.EnsureCreated();
			BuiltinApps.Register();
			PhoneKeys.RegisterBuiltins();
			PhoneKeys.Load();
			_harmony = new Harmony("tony4twentys.Crispberry_PiPhone");
			try
			{
				_harmony.PatchAll(typeof(Plugin).Assembly);
			}
			catch (Exception ex)
			{
				LogError("Harmony PatchAll failed: " + ex.Message);
			}
			SceneManager.sceneLoaded += OnSceneLoaded;
			LogInfo("Crispberry PiPhone v0.17.69 loaded. Open with " + FormatHotkey() + ".");
		}

		private void Update()
		{
			PhoneMenu.TickUseLock();
			if (!PhoneKeys.TickCapture())
			{
				PhoneKeys.FirePressed();
				if (CameraApp.IsOpen)
				{
					CameraApp.TickHotkeys();
				}
			}
		}

		internal static string FormatCameraKeys()
		{
			return PhoneKeys.Format("pip.camera.cursor") + " cursor · " + PhoneKeys.Format("pip.camera.flip") + " flip · " + PhoneKeys.Format("pip.camera.rotate") + " rotate · " + PhoneKeys.Format("pip.camera.shutter") + " shutter · wheel zoom";
		}

		internal static string FormatLandscapeKey()
		{
			return PhoneKeys.Format("pip.landscape");
		}

		internal static string FormatAlertKeys(bool text = false)
		{
			string text2 = PhoneKeys.Format("pip.answer");
			string text3 = PhoneKeys.Format("pip.decline");
			return text ? (text2 + " open  ·  " + text3 + " dismiss") : (text2 + " answer  ·  " + text3 + " decline");
		}

		public static string FormatHotkey()
		{
			return PhoneKeys.Format("pip.open");
		}

		internal static string Pretty(KeyCode key)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return PhoneKeys.Pretty(key);
		}

		private void OnDestroy()
		{
			SceneManager.sceneLoaded -= OnSceneLoaded;
			try
			{
				Harmony harmony = _harmony;
				if (harmony != null)
				{
					harmony.UnpatchSelf();
				}
			}
			catch
			{
			}
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			PhoneUi.InvalidateFont();
			PhoneMenu.OnAfterSceneLoad();
		}

		public static bool GetShowPauseMenuButton()
		{
			return (Object)(object)Instance == (Object)null || Instance.ShowPauseMenuButton == null || Instance.ShowPauseMenuButton.Value;
		}

		public static void SetShowPauseMenuButton(bool show)
		{
			if ((Object)(object)Instance != (Object)null && Instance.ShowPauseMenuButton != null)
			{
				Instance.ShowPauseMenuButton.Value = show;
			}
		}

		public static void LogInfo(string message)
		{
			if (PhoneTheme.WriteLogs)
			{
				if ((Object)(object)Instance != (Object)null)
				{
					((BaseUnityPlugin)Instance).Logger.LogInfo((object)message);
				}
				else
				{
					Debug.Log((object)("[PiPhone] " + message));
				}
			}
		}

		public static void LogError(string message)
		{
			if ((Object)(object)Instance != (Object)null)
			{
				((BaseUnityPlugin)Instance).Logger.LogError((object)message);
			}
			else
			{
				Debug.LogError((object)("[PiPhone] " + message));
			}
		}
	}
	public static class PiPhoneApi
	{
		public const string PluginGuid = "tony4twentys.Crispberry_PiPhone";

		public const string OsName = "Crispberry OS";

		internal static readonly List<PiPhoneApp> Apps = new List<PiPhoneApp>(16);

		public static int BatteryPercent = 100;

		public static bool BatteryCharging;

		public static PiPhoneCarrier Carrier = PiPhoneCarrier.Lte;

		public static int SignalBars = 4;

		public const int MaxIconSize = 128;

		public const int MaxIconBytes = 2097152;

		private static readonly List<PiPhoneCategory> Categories = new List<PiPhoneCategory>();

		public static string OsVersion => Plugin.OsVersionLabel;

		public static bool IsReady => (Object)(object)Plugin.Instance != (Object)null;

		public static bool IsOpen => PhoneMenu.IsOpen;

		public static bool CanUsePhone => PhoneMenu.CanUsePhone();

		public static bool IsPlayThrough => PhoneMenu.IsPlayThrough;

		public static PiPhonePlayThrough PlayThroughMode => PhoneMenu.PlayThroughMode;

		public static bool PlayThroughAllowed => PhoneMenu.PlayThroughAllowed();

		public static string CurrentAppId => PhoneMenu.CurrentAppId;

		public static bool IsLandscape => PhoneMenu.IsLandscape;

		public static bool IsFullscreen => PhoneMenu.IsFullscreen;

		public static bool IsImmersive => PhoneMenu.IsImmersive;

		public static string AlertsFolder => PhoneStore.AlertsDir;

		public static bool IsLocalDead => ScoutQuery.LocalIsDead();

		public static bool IsLocalGhost => ScoutQuery.LocalIsGhost();

		public static event Action AppsChanged;

		public static event Action OrientationChanged;

		public static void SetPlayThrough(bool on)
		{
			PhoneMenu.SetPlayThrough(on);
		}

		public static void SetPlayThrough(PiPhonePlayThrough mode)
		{
			PhoneMenu.SetPlayThrough(mode);
		}

		public static void TogglePlayThrough()
		{
			PhoneMenu.TogglePlayThrough();
		}

		public static void Open()
		{
			PhoneMenu.Open();
		}

		public static void Close()
		{
			PhoneMenu.Close();
		}

		public static void Toggle()
		{
			PhoneMenu.Toggle();
		}

		public static void GoHome()
		{
			PhoneMenu.GoHome();
		}

		public static void GoBack()
		{
			PhoneMenu.GoBack();
		}

		public static bool OpenApp(string id)
		{
			return PhoneMenu.OpenApp(id);
		}

		public static void SetLandscape(bool landscape)
		{
			PhoneMenu.SetLandscape(landscape);
		}

		public static void SetFullscreen(bool fullscreen)
		{
			PhoneMenu.SetFullscreen(fullscreen);
		}

		public static void SetWallpaperPaused(bool paused)
		{
			PhoneMenu.SetWallpaperPaused(paused);
		}

		public static void RegisterKeybind(PiPhoneKeybind bind)
		{
			PhoneKeys.Add(bind);
		}

		public static void RegisterShadeButton(PiPhoneShadeButton button)
		{
			PhoneShade.Register(button);
			PhoneMenu.RefreshShade();
		}

		public static void RegisterNavButton(PiPhoneNavButton button)
		{
			PhoneMenu.RegisterNavButton(button);
		}

		public static void RegisterNumber(PiPhoneNumber number)
		{
			PhoneNumbers.Register(number);
		}

		public static bool UnregisterNumber(string number)
		{
			return PhoneNumbers.Unregister(number);
		}

		public static void SetBattery(int percent, bool charging)
		{
			if (percent < 0)
			{
				percent = 0;
			}
			if (percent > 100)
			{
				percent = 100;
			}
			BatteryPercent = percent;
			BatteryCharging = charging;
		}

		public static void SetCarrier(PiPhoneCarrier carrier, int bars)
		{
			Carrier = carrier;
			if (bars < 0)
			{
				bars = 0;
			}
			if (bars > 4)
			{
				bars = 4;
			}
			SignalBars = bars;
		}

		public static void SetContactName(string id, string customName)
		{
			PhoneContacts.SetCustomName(id, customName);
		}

		public static bool SetContactPhoto(string id, byte[] pngOrJpg)
		{
			return PhoneContacts.SetPhoto(id, pngOrJpg);
		}

		public static bool TryGetContact(string id, out PiPhoneContact contact)
		{
			contact = PhoneContacts.Get(id);
			return contact != null;
		}

		public static string ContactDisplayName(string id, string fallback)
		{
			return PhoneContacts.Display(id, fallback);
		}

		public static PiPhoneContact[] GetContacts()
		{
			return PhoneContacts.All();
		}

		public static PiPhoneLook GetLook()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: 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_0038: 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_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: 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_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			return new PiPhoneLook
			{
				Screen = PhoneTheme.ScreenColor,
				Surface = PhoneTheme.SurfaceColor,
				Nav = PhoneTheme.NavColor,
				NavButton = PhoneTheme.NavButtonColor,
				NavIcon = PhoneTheme.NavIconColor,
				Text = PhoneTheme.TextColor,
				Accent = PhoneTheme.AccentColor,
				Icon = PhoneTheme.IconColor,
				Case = PhoneTheme.CaseColor,
				Clock = PhoneTheme.ClockColor,
				ButtonFill = PhoneTheme.ButtonFillColor,
				ButtonText = PhoneTheme.ButtonFontColor,
				FontScale = PhoneTheme.FontScale,
				ButtonRadius = PhoneTheme.ButtonRadius,
				IconRadius = PhoneTheme.IconRadius
			};
		}

		public static void SetLook(PiPhoneLook look)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_002a: 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_0035: 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_0046: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: 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_0082: 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_008d: Unknown result type (might be due to invalid IL or missing references)
			if (look != null)
			{
				PhoneTheme.ScreenColor = look.Screen;
				PhoneTheme.SurfaceColor = look.Surface;
				PhoneTheme.NavColor = look.Nav;
				PhoneTheme.NavButtonColor = look.NavButton;
				PhoneTheme.NavIconColor = look.NavIcon;
				PhoneTheme.TextColor = look.Text;
				PhoneTheme.AccentColor = look.Accent;
				PhoneTheme.IconColor = look.Icon;
				PhoneTheme.CaseColor = look.Case;
				PhoneTheme.ClockColor = look.Clock;
				PhoneTheme.ButtonFillColor = look.ButtonFill;
				PhoneTheme.ButtonFontColor = look.ButtonText;
				PhoneTheme.FontScale = Mathf.Clamp(look.FontScale, 0.7f, 1.6f);
				PhoneTheme.ButtonRadius = ((look.ButtonRadius >= 0) ? ((look.ButtonRadius > 28) ? 28 : look.ButtonRadius) : 0);
				PhoneTheme.IconRadius = ((look.IconRadius >= 0) ? ((look.IconRadius > 28) ? 28 : look.IconRadius) : 0);
				PhoneTheme.Commit();
			}
		}

		public static void ResetLook()
		{
			PhoneTheme.ResetLook();
		}

		public static void ResetButtons()
		{
			PhoneTheme.ResetButtons();
		}

		public static void ResetCase()
		{
			PhoneTheme.ResetCase();
		}

		public static void ResetClockColor()
		{
			PhoneTheme.ResetClockColor();
		}

		public static void RegisterLanguage(PiPhoneLanguage pack)
		{
			PhoneLang.Register(pack);
		}

		public static bool SetLanguage(string code)
		{
			return PhoneLang.Set(code);
		}

		public static void UseSystemLanguage()
		{
			PhoneLang.UseSystem();
		}

		public static string GetLanguage()
		{
			return PhoneLang.Code;
		}

		public static string T(string key, string fallback)
		{
			return PhoneLang.T(key, fallback);
		}

		public static PiPhoneLanguage[] GetLanguages()
		{
			return PhoneLang.All();
		}

		public static void SetScreenColor(Color color)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			PhoneTheme.SetScreenColor(color);
		}

		public static void SetSurfaceColor(Color color)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			PhoneTheme.SetSurfaceColor(color);
		}

		public static void SetNavColor(Color color)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			PhoneTheme.SetNavColor(color);
		}

		public static void SetNavButtonColor(Color color)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			PhoneTheme.SetNavButtonColor(color);
		}

		public static void SetNavIconColor(Color color)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			PhoneTheme.SetNavIconColor(color);
		}

		public static void SetTextColor(Color color)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			PhoneTheme.SetTextColor(color);
		}

		public static void SetAccentColor(Color color)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			PhoneTheme.SetAccentColor(color);
		}

		public static void SetIconColor(Color color)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			PhoneTheme.SetIconColor(color);
		}

		public static void SetFontScale(float scale)
		{
			PhoneTheme.SetFontScale(scale);
		}

		public static void SetButtonRadius(int radius)
		{
			PhoneTheme.SetButtonRadius(radius);
		}

		public static void SetIconRadius(int radius)
		{
			PhoneTheme.SetIconRadius(radius);
		}

		public static bool UnregisterShadeButton(string id)
		{
			bool flag = PhoneShade.Unregister(id);
			if (flag)
			{
				PhoneMenu.RefreshShade();
			}
			return flag;
		}

		public static PiPhoneShadeButton[] GetShadeButtons()
		{
			return PhoneShade.All();
		}

		public static bool ShadeButtonVisible(string id)
		{
			PiPhoneShadeButton[] array = PhoneShade.All();
			for (int i = 0; i < array.Length; i++)
			{
				if (array[i] != null && string.Equals(array[i].Id, id, StringComparison.OrdinalIgnoreCase))
				{
					return PhoneShade.Visible(array[i]);
				}
			}
			return false;
		}

		public static void SetShadeButtonVisible(string id, bool visible)
		{
			PhoneTheme.SetShadeButtonOn(id, visible);
			PhoneMenu.RefreshShade();
		}

		public static bool UnregisterKeybind(string id)
		{
			return PhoneKeys.Remove(id);
		}

		public static bool KeyDown(string id)
		{
			return PhoneKeys.Down(id);
		}

		public static bool KeyHeld(string id)
		{
			return PhoneKeys.Held(id);
		}

		public static string FormatKey(string id)
		{
			return PhoneKeys.Format(id);
		}

		public static PiPhoneKeybind[] GetKeybinds()
		{
			return PhoneKeys.All();
		}

		public static void CaptureKeybind(string id, Action onDone)
		{
			PhoneKeys.BeginCapture(id, onDone);
		}

		public static void ClearKeybind(string id)
		{
			PhoneKeys.Clear(id);
		}

		public static void SetImmersive(bool immersive)
		{
			PhoneMenu.SetImmersive(immersive);
		}

		public static void SetUserLandscape(bool landscape)
		{
			PhoneMenu.SetUserLandscape(landscape);
		}

		public static void ToggleLandscape()
		{
			PhoneMenu.ToggleUserLandscape();
		}

		public static void Notify(string appId, string title, string body)
		{
			PhoneNotify.Post(appId, title, body, persist: true, sound: true);
		}

		public static string ImportAlert(string path)
		{
			return PhoneStore.AddSound(path, alert: true, 20f)?.Id;
		}

		public static void SetAppAlertSound(string appId, string soundId)
		{
			PhoneTones.SetAppTone(appId, soundId);
		}

		public static string GetAppAlertSound(string appId)
		{
			return PhoneTones.AppTone(appId);
		}

		public static void Toast(string message)
		{
			PhoneMenu.Toast(message);
		}

		public static PiPhoneScout LocalScout()
		{
			return ScoutQuery.Local();
		}

		public static PiPhoneScout[] GetScouts()
		{
			return ScoutQuery.All(othersOnly: false);
		}

		public static PiPhoneScout[] GetOtherScouts()
		{
			return ScoutQuery.All(othersOnly: true);
		}

		public static PiPhoneScout[] GetDeadScouts()
		{
			return ScoutQuery.Where((PiPhoneScout s) => s.IsDead);
		}

		public static PiPhoneScout[] GetGhostScouts()
		{
			return ScoutQuery.Where((PiPhoneScout s) => s.IsGhost);
		}

		public static PiPhoneScout[] GetPassedOutScouts()
		{
			return ScoutQuery.Where((PiPhoneScout s) => s.IsPassedOut && !s.IsDead && !s.IsGhost);
		}

		public static PiPhoneScout[] GetCarriedScouts()
		{
			return ScoutQuery.Where((PiPhoneScout s) => s.IsCarried);
		}

		public static bool TryGetScout(string id, out PiPhoneScout scout)
		{
			return ScoutQuery.TryById(id, out scout);
		}

		public static bool TryGetScout(int actorNumber, out PiPhoneScout scout)
		{
			return ScoutQuery.TryByActor(actorNumber, out scout);
		}

		public static bool IsScoutDead(string id)
		{
			PiPhoneScout scout;
			return TryGetScout(id, out scout) && scout.IsDead;
		}

		public static bool IsScoutGhost(string id)
		{
			PiPhoneScout scout;
			return TryGetScout(id, out scout) && scout.IsGhost;
		}

		public static bool IsScoutDead(int actorNumber)
		{
			PiPhoneScout scout;
			return TryGetScout(actorNumber, out scout) && scout.IsDead;
		}

		public static bool IsScoutGhost(int actorNumber)
		{
			PiPhoneScout scout;
			return TryGetScout(actorNumber, out scout) && scout.IsGhost;
		}

		public static bool TryGetVoiceFilter(string id, out PiPhoneVoiceFilter filter)
		{
			return VoiceFx.TryGet(id, out filter);
		}

		public static bool TryGetVoiceFilter(int actorNumber, out PiPhoneVoiceFilter filter)
		{
			return VoiceFx.TryGet(actorNumber, out filter);
		}

		public static bool SetVoiceFilter(string id, PiPhoneVoiceFilter filter)
		{
			return VoiceFx.SetHold(id, filter);
		}

		public static bool SetVoiceFilter(int actorNumber, PiPhoneVoiceFilter filter)
		{
			return VoiceFx.SetHold(actorNumber, filter);
		}

		public static bool ClearVoiceFilter(string id)
		{
			return VoiceFx.ClearHold(id);
		}

		public static bool ClearVoiceFilter(int actorNumber)
		{
			return VoiceFx.ClearHold(actorNumber);
		}

		public static void ClearAllVoiceFilters()
		{
			VoiceFx.ClearAllHolds();
		}

		public static bool VoiceFilterHeld(string id)
		{
			return VoiceFx.IsHeld(id);
		}

		public static void RegisterApp(PiPhoneApp app)
		{
			if (app == null || string.IsNullOrEmpty(app.Id))
			{
				throw new ArgumentException("PiPhone app needs a non-empty Id.", "app");
			}
			int num = IndexOf(app.Id);
			if (num >= 0)
			{
				Apps[num] = app;
			}
			else
			{
				Apps.Add(app);
			}
			if ((Object)(object)app.IconSprite != (Object)null)
			{
				app.IconSprite = PhoneIcons.ClampSprite(app.IconSprite);
			}
			if (!string.IsNullOrEmpty(app.BundledAlertPath) && File.Exists(app.BundledAlertPath))
			{
				SoundItem soundItem = PhoneStore.AddSound(app.BundledAlertPath, alert: true, 20f);
				if (soundItem != null && string.IsNullOrEmpty(PhoneTones.AppTone(app.Id)))
				{
					PhoneTones.SetAppTone(app.Id, soundItem.Id);
				}
			}
			if (PhoneStore.DefaultsReady && app.Preinstalled && !PhoneStore.IsInstalled(app.Id))
			{
				PhoneStore.Install(app.Id);
			}
			SortApps();
			RaiseAppsChanged();
			PhoneMenu.OnAppsChanged();
		}

		public static Sprite CreateIcon(Texture2D texture)
		{
			return PhoneIcons.FromTexture(texture, consumeSource: false);
		}

		public static Sprite CreateIcon(byte[] pngOrJpg)
		{
			return PhoneIcons.FromBytes(pngOrJpg);
		}

		public static Sprite CreateIconFromFile(string path)
		{
			return PhoneIcons.FromFile(path);
		}

		public static Button CreateIconButton(Transform parent, Sprite icon, UnityAction onClick, Vector2 size)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			return PhoneUi.CreateIconChip(parent, string.Empty, icon, onClick, lit: false, size, tintIcon: false);
		}

		public static Button CreateIconButton(Transform parent, byte[] pngOrJpg, UnityAction onClick, Vector2 size)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			return CreateIconButton(parent, CreateIcon(pngOrJpg), onClick, size);
		}

		public static bool UnregisterApp(string id)
		{
			int num = IndexOf(id);
			if (num < 0)
			{
				return false;
			}
			Apps.RemoveAt(num);
			RaiseAppsChanged();
			PhoneMenu.OnAppsChanged();
			return true;
		}

		public static bool TryGetApp(string id, out PiPhoneApp app)
		{
			int num = IndexOf(id);
			if (num < 0)
			{
				app = null;
				return false;
			}
			app = Apps[num];
			return true;
		}

		public static PiPhoneApp[] GetApps()
		{
			return Apps.ToArray();
		}

		public static PiPhoneApp[] GetInstalledApps()
		{
			List<PiPhoneApp> list = new List<PiPhoneApp>();
			for (int i = 0; i < Apps.Count; i++)
			{
				if (Apps[i] != null && PhoneStore.IsInstalled(Apps[i].Id))
				{
					list.Add(Apps[i]);
				}
			}
			return list.ToArray();
		}

		public static void RegisterCategory(string id, string displayName, int sortOrder)
		{
			if (string.IsNullOrEmpty(id))
			{
				return;
			}
			for (int i = 0; i < Categories.Count; i++)
			{
				if (Categories[i] != null && string.Equals(Categories[i].Id, id, StringComparison.OrdinalIgnoreCase))
				{
					Categories[i].DisplayName = (string.IsNullOrEmpty(displayName) ? id : displayName);
					Categories[i].SortOrder = sortOrder;
					return;
				}
			}
			Categories.Add(new PiPhoneCategory
			{
				Id = id,
				DisplayName = (string.IsNullOrEmpty(displayName) ? id : displayName),
				SortOrder = sortOrder
			});
		}

		public static PiPhoneCategory[] GetCategories()
		{
			List<PiPhoneCategory> list = new List<PiPhoneCategory>(Categories);
			list.Sort(delegate(PiPhoneCategory a, PiPhoneCategory b)
			{
				int num = a?.SortOrder ?? 0;
				int value = b?.SortOrder ?? 0;
				int num2 = num.CompareTo(value);
				return (num2 != 0) ? num2 : string.Compare((a != null) ? a.DisplayName : string.Empty, (b != null) ? b.DisplayName : string.Empty, StringComparison.OrdinalIgnoreCase);
			});
			return list.ToArray();
		}

		public static PiPhoneApp[] GetStoreApps()
		{
			List<PiPhoneApp> list = new List<PiPhoneApp>();
			for (int i = 0; i < Apps.Count; i++)
			{
				PiPhoneApp piPhoneApp = Apps[i];
				if (piPhoneApp != null && piPhoneApp.ListedInStore)
				{
					list.Add(piPhoneApp);
				}
			}
			return list.ToArray();
		}

		public static bool IsInstalled(string id)
		{
			return PhoneStore.IsInstalled(id);
		}

		public static bool CanUninstall(string id)
		{
			if (!TryGetApp(id, out var app) || app == null || app.Sticky)
			{
				return false;
			}
			return PhoneStore.IsInstalled(id);
		}

		public static bool Install(string id)
		{
			if (!TryGetApp(id, out var app) || app == null)
			{
				return false;
			}
			if (!PhoneStore.Install(id))
			{
				return false;
			}
			RaiseAppsChanged();
			PhoneMenu.OnAppsChanged();
			return true;
		}

		public static bool IsOnHome(string id)
		{
			return PhoneStore.IsOnHome(id);
		}

		public static bool AddToHome(string id)
		{
			if (!PhoneStore.AddToHome(id))
			{
				return false;
			}
			RaiseAppsChanged();
			PhoneMenu.OnAppsChanged();
			return true;
		}

		public static bool RemoveFromHome(string id)
		{
			if (!PhoneStore.RemoveFromHome(id))
			{
				return false;
			}
			RaiseAppsChanged();
			PhoneMenu.OnAppsChanged();
			return true;
		}

		public static bool Uninstall(string id)
		{
			if (!CanUninstall(id))
			{
				return false;
			}
			if (CurrentAppId == id)
			{
				PhoneMenu.GoHome();
			}
			if (!PhoneStore.Uninstall(id))
			{
				return false;
			}
			RaiseAppsChanged();
			PhoneMenu.OnAppsChanged();
			return true;
		}

		internal static int IndexOf(string id)
		{
			if (string.IsNullOrEmpty(id))
			{
				return -1;
			}
			for (int i = 0; i < Apps.Count; i++)
			{
				if (Apps[i] != null && string.Equals(Apps[i].Id, id, StringComparison.OrdinalIgnoreCase))
				{
					return i;
				}
			}
			return -1;
		}

		private static void SortApps()
		{
			Apps.Sort(CompareApps);
		}

		private static int CompareApps(PiPhoneApp a, PiPhoneApp b)
		{
			int num = ((b != null && b.ShowOnDock) ? 1 : 0) - ((a != null && a.ShowOnDock) ? 1 : 0);
			if (num != 0)
			{
				return num;
			}
			int num2 = (a?.SortOrder ?? 0).CompareTo(b?.SortOrder ?? 0);
			if (num2 != 0)
			{
				return num2;
			}
			string strA = ((a != null) ? a.DisplayName : string.Empty);
			string strB = ((b != null) ? b.DisplayName : string.Empty);
			return string.Compare(strA, strB, StringComparison.OrdinalIgnoreCase);
		}

		private static void RaiseAppsChanged()
		{
			PiPhoneApi.AppsChanged?.Invoke();
		}

		internal static void RaiseOrientation()
		{
			PiPhoneApi.OrientationChanged?.Invoke();
		}
	}
	public enum PiPhonePlayThrough
	{
		Off,
		Walk,
		WalkAndCursor
	}
	public enum PiPhoneCarrier
	{
		None,
		Edge,
		ThreeG,
		Lte,
		FiveG
	}
	public sealed class PiPhoneContact
	{
		public string Id;

		public string CustomName;

		public string RealName;

		public string PhotoFile;

		public bool BlockCalls;

		public bool BlockTexts;
	}
	public sealed class PiPhoneCategory
	{
		public string Id;

		public string DisplayName;

		public int SortOrder;
	}
	public sealed class PiPhoneLook
	{
		public Color Screen = new Color(0.08f, 0.1f, 0.13f, 1f);

		public Color Surface = new Color(0.16f, 0.18f, 0.21f, 0.96f);

		public Color Nav = new Color(0.1f, 0.11f, 0.13f, 1f);

		public Color NavButton = new Color(0.2f, 0.22f, 0.26f, 1f);

		public Color NavIcon = new Color(0.96f, 0.97f, 0.98f, 1f);

		public Color Text = new Color(0.96f, 0.97f, 0.98f, 1f);

		public Color Accent = new Color(0.24f, 0.86f, 0.52f, 1f);

		public Color Icon = Color.white;

		public Color Case = new Color(0.07f, 0.07f, 0.08f, 1f);

		public Color Clock = new Color(0.96f, 0.97f, 0.98f, 1f);

		public Color ButtonFill = new Color(0.2f, 0.22f, 0.26f, 1f);

		public Color ButtonText = new Color(0.96f, 0.97f, 0.98f, 1f);

		public float FontScale = 1f;

		public int ButtonRadius = 18;

		public int IconRadius = 20;
	}
	public sealed class PiPhoneApp
	{
		public string Id;

		public string DisplayName;

		public string IconGlyph;

		public Color IconBackground = new Color(0.22f, 0.45f, 0.72f, 1f);

		public Color IconForeground = Color.white;

		public Sprite IconSprite;

		public int SortOrder;

		public bool ShowOnDock;

		public bool ShowOnHome = true;

		public bool Preinstalled;

		public bool ListedInStore = true;

		public string Category;

		public string Description;

		private readonly List<Sprite> _screenshots = new List<Sprite>();

		public bool Sticky;

		public bool PostsNotices = true;

		public bool AllowPlayThrough = true;

		public string BundledAlertPath;

		public bool Landscape;

		public bool Fullscreen;

		public bool CoversWallpaper = true;

		public bool Immersive;

		public bool ApplyPhoneFonts = true;

		public Action<IPiPhoneHost> OnOpen;

		public Action OnClose;

		public Func<bool> OnBack;

		public Action OnOrientation;

		public Sprite[] Screenshots => _screenshots.ToArray();

		public bool SetIcon(byte[] pngOrJpg)
		{
			Sprite val = PhoneIcons.FromBytes(pngOrJpg);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			IconSprite = val;
			return true;
		}

		public void SetIcon(Texture2D texture)
		{
			IconSprite = PhoneIcons.FromTexture(texture, consumeSource: false);
		}

		public bool SetIconFile(string path)
		{
			Sprite val = PhoneIcons.FromFile(path);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			IconSprite = val;
			return true;
		}

		public bool AddScreenshot(byte[] pngOrJpg)
		{
			return AddScreenshot(PhoneIcons.FromBytes(pngOrJpg, allowOversizeFile: true, 480));
		}

		public bool AddScreenshot(Texture2D texture)
		{
			return AddScreenshot(PhoneIcons.Screenshot(texture));
		}

		public bool AddScreenshot(Sprite sprite)
		{
			if ((Object)(object)sprite == (Object)null || _screenshots.Count >= 8)
			{
				return false;
			}
			Sprite val = PhoneIcons.ClampSprite(sprite, 480);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			_screenshots.Add(val);
			return true;
		}
	}
	public sealed class PiPhoneKeybind
	{
		public string Id;

		public string Label;

		public string Group = "Apps";

		public string AppId;

		public string[] AlsoApps;

		public KeyCode DefaultKey;

		public KeyCode DefaultModifier;

		public KeyCode Key;

		public KeyCode Modifier;

		public bool WithModifier;

		public bool Global;

		public bool PhoneOpen;

		public bool Required;

		public int SortOrder;

		public Action OnPressed;
	}
	public sealed class PiPhoneNavButton
	{
		public string Id;

		public string Glyph;

		public Sprite Icon;

		public Func<Sprite> IconFn;

		public bool TintIcon = true;

		public int SortOrder = 100;

		public Action OnClick;

		public Func<bool> Available;
	}
	public sealed class PiPhoneShadeButton
	{
		public string Id;

		public string Label;

		public string Glyph;

		public Sprite Icon;

		public bool UseText;

		public int SortOrder = 100;

		public bool DefaultVisible = true;

		public Action OnClick;

		public Func<bool> IsActive;

		public Func<bool> Available;

		public bool CanHide = true;

		public Func<string> GlyphFn;

		public Func<Sprite> IconFn;
	}
	public interface IPiPhoneHost
	{
		RectTransform Content { get; }

		bool IsMasterClient { get; }

		bool IsLandscape { get; }

		bool IsFullscreen { get; }

		bool IsPlayThrough { get; }

		PiPhonePlayThrough PlayThroughMode { get; }

		void SetTitle(string title);

		void GoHome();

		void GoBack();

		void ClosePhone();

		void ShowToast(string message);

		Coroutine StartHostCoroutine(IEnumerator routine);

		Button CreateButton(Transform parent, string label, UnityAction onClick, Vector2 size);

		void SetLandscape(bool landscape);

		void SetFullscreen(bool fullscreen);

		void SetImmersive(bool immersive);

		void ToggleLandscape();

		void SetPlayThrough(bool on);

		void SetPlayThrough(PiPhonePlayThrough mode);

		void TogglePlayThrough();

		void SetWallpaperPaused(bool paused);
	}
	public sealed class PiPhoneScout
	{
		public string Id;

		public string Name;

		public int ActorNumber;

		public bool IsLocal;

		public bool IsDead;

		public bool IsGhost;

		public bool IsPassedOut;

		public bool IsFullyPassedOut;

		public bool IsFullyConscious;

		public float PassOutValue;

		public float DeathTimer;

		public float DeathLeft;

		public float DeathSecondsLeft;

		public float TimeSinceDied;

		public bool IsInFog;

		public bool IsInWater;

		public bool IsCarried;

		public string CarrierId;

		public string CarrierName;

		public int CarrierActor;

		public bool IsCarrying;

		public string CarriedId;

		public string CarriedName;

		public int CarriedActor;

		public Vector3 Position;

		public Vector3 VoicePosition;
	}
	internal static class ScoutQuery
	{
		internal static PiPhoneScout Local()
		{
			try
			{
				Character localCharacter = Character.localCharacter;
				if ((Object)(object)localCharacter != (Object)null)
				{
					return FromCharacter(localCharacter);
				}
			}
			catch
			{
			}
			return null;
		}

		internal static bool LocalIsDead()
		{
			return Local()?.IsDead ?? false;
		}

		internal static bool LocalIsGhost()
		{
			return Local()?.IsGhost ?? false;
		}

		internal static PiPhoneScout[] All(bool othersOnly)
		{
			List<PiPhoneScout> list = new List<PiPhoneScout>();
			try
			{
				List<Character> allCharacters = Character.AllCharacters;
				if (allCharacters == null)
				{
					return list.ToArray();
				}
				for (int i = 0; i < allCharacters.Count; i++)
				{
					Character val = allCharacters[i];
					if ((Object)(object)val == (Object)null)
					{
						continue;
					}
					try
					{
						if (val.isBot)
						{
							continue;
						}
					}
					catch
					{
					}
					PiPhoneScout piPhoneScout = FromCharacter(val);
					if (piPhoneScout != null && (!othersOnly || !piPhoneScout.IsLocal))
					{
						list.Add(piPhoneScout);
					}
				}
			}
			catch
			{
			}
			return list.ToArray();
		}

		internal static PiPhoneScout[] Where(Func<PiPhoneScout, bool> match)
		{
			PiPhoneScout[] array = All(othersOnly: false);
			if (match == null)
			{
				return array;
			}
			List<PiPhoneScout> list = new List<PiPhoneScout>();
			for (int i = 0; i < array.Length; i++)
			{
				if (array[i] != null && match(array[i]))
				{
					list.Add(array[i]);
				}
			}
			return list.ToArray();
		}

		internal static bool TryById(string id, out PiPhoneScout scout)
		{
			scout = null;
			if (string.IsNullOrEmpty(id))
			{
				return false;
			}
			PiPhoneScout[] array = All(othersOnly: false);
			for (int i = 0; i < array.Length; i++)
			{
				if (array[i] != null && string.Equals(array[i].Id, id, StringComparison.Ordinal))
				{
					scout = array[i];
					return true;
				}
			}
			return false;
		}

		internal static bool TryByActor(int actor, out PiPhoneScout scout)
		{
			scout = null;
			if (actor <= 0)
			{
				return false;
			}
			PiPhoneScout[] array = All(othersOnly: false);
			for (int i = 0; i < array.Length; i++)
			{
				if (array[i] != null && array[i].ActorNumber == actor)
				{
					scout = array[i];
					return true;
				}
			}
			return false;
		}

		private static PiPhoneScout FromCharacter(Character character)
		{
			//IL_0286: Unknown result type (might be due to invalid IL or missing references)
			//IL_028b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0292: Unknown result type (might be due to invalid IL or missing references)
			//IL_0297: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)character == (Object)null)
			{
				return null;
			}
			PiPhoneScout piPhoneScout = new PiPhoneScout();
			Player val = null;
			try
			{
				if ((Object)(object)((MonoBehaviourPun)character).photonView != (Object)null)
				{
					val = ((MonoBehaviourPun)character).photonView.Owner;
				}
			}
			catch
			{
			}
			if (val != null)
			{
				piPhoneScout.Id = BuiltinApps.PlayerId(val);
				piPhoneScout.Name = BuiltinApps.PlayerName(val);
				piPhoneScout.ActorNumber = val.ActorNumber;
				piPhoneScout.IsLocal = val.IsLocal;
			}
			else
			{
				piPhoneScout.Id = (character.IsLocal ? BuiltinApps.LocalId() : "unknown");
				piPhoneScout.Name = (character.IsLocal ? BuiltinApps.LocalName() : "Scout");
				piPhoneScout.IsLocal = character.IsLocal;
			}
			try
			{
				if (character.IsLocal)
				{
					piPhoneScout.IsLocal = true;
				}
			}
			catch
			{
			}
			try
			{
				CharacterData data = character.data;
				if ((Object)(object)data != (Object)null)
				{
					piPhoneScout.IsDead = data.dead;
					piPhoneScout.IsFullyPassedOut = data.fullyPassedOut;
					piPhoneScout.IsPassedOut = data.passedOut || data.fullyPassedOut;
					piPhoneScout.IsFullyConscious = data.fullyConscious;
					piPhoneScout.PassOutValue = data.passOutValue;
					piPhoneScout.DeathTimer = Mathf.Clamp01(data.deathTimer);
					piPhoneScout.DeathLeft = (piPhoneScout.IsDead ? 0f : Mathf.Clamp01(1f - piPhoneScout.DeathTimer));
					if (piPhoneScout.IsFullyPassedOut && !piPhoneScout.IsDead)
					{
						piPhoneScout.DeathSecondsLeft = piPhoneScout.DeathLeft * 60f;
					}
					if (data.dead)
					{
						piPhoneScout.TimeSinceDied = data.sinceDied;
					}
					piPhoneScout.IsInFog = data.isInFog;
					try
					{
						piPhoneScout.IsInWater = data.isInWater;
					}
					catch
					{
					}
					piPhoneScout.IsCarried = data.isCarried || (Object)(object)data.carrier != (Object)null;
					FillPeer(data.carrier, out piPhoneScout.CarrierId, out piPhoneScout.CarrierName, out piPhoneScout.CarrierActor);
					piPhoneScout.IsCarrying = data.IsCarryingCharacter || (Object)(object)data.carriedPlayer != (Object)null;
					FillPeer(data.carriedPlayer, out piPhoneScout.CarriedId, out piPhoneScout.CarriedName, out piPhoneScout.CarriedActor);
				}
			}
			catch
			{
			}
			try
			{
				piPhoneScout.IsGhost = character.IsGhost;
			}
			catch
			{
			}
			piPhoneScout.Position = WorldPos(character);
			piPhoneScout.VoicePosition = VoicePos(character);
			return piPhoneScout;
		}

		private static Vector3 WorldPos(Character character)
		{
			//IL_007f: 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)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)character.Ghost != (Object)null)
				{
					return ((Component)character.Ghost).transform.position;
				}
			}
			catch
			{
			}
			try
			{
				if (character.refs != null && (Object)(object)character.refs.head != (Object)null)
				{
					return character.refs.head.transform.position;
				}
			}
			catch
			{
			}
			try
			{
				return character.Center;
			}
			catch
			{
			}
			return Vector3.zero;
		}

		private static Vector3 VoicePos(Character character)
		{
			//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)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				CharacterVoiceHandler componentInChildren = ((Component)character).GetComponentInChildren<CharacterVoiceHandler>();
				if ((Object)(object)componentInChildren != (Object)null && (Object)(object)componentInChildren.m_transformProvider != (Object)null)
				{
					return componentInChildren.m_transformProvider.GetVoicePosition(false);
				}
			}
			catch
			{
			}
			return WorldPos(character);
		}

		private static void FillPeer(Character other, out string id, out string name, out int actor)
		{
			id = null;
			name = null;
			actor = 0;
			if ((Object)(object)other == (Object)null)
			{
				return;
			}
			actor = ActorOf(other);
			Player val = null;
			try
			{
				if ((Object)(object)((MonoBehaviourPun)other).photonView != (Object)null)
				{
					val = ((MonoBehaviourPun)other).photonView.Owner;
				}
			}
			catch
			{
			}
			if (val != null)
			{
				id = BuiltinApps.PlayerId(val);
				name = BuiltinApps.PlayerName(val);
				actor = val.ActorNumber;
			}
			else
			{
				id = (other.IsLocal ? BuiltinApps.LocalId() : "unknown");
				name = (other.IsLocal ? BuiltinApps.LocalName() : "Scout");
			}
		}

		internal static int ActorOf(Character character)
		{
			if ((Object)(object)character == (Object)null)
			{
				return 0;
			}
			try
			{
				if ((Object)(object)((MonoBehaviourPun)character).photonView != (Object)null && ((MonoBehaviourPun)character).photonView.Owner != null)
				{
					return ((MonoBehaviourPun)character).photonView.Owner.ActorNumber;
				}
			}
			catch
			{
			}
			return 0;
		}

		internal static CharacterVoiceHandler HandlerOf(Character character)
		{
			if ((Object)(object)character == (Object)null)
			{
				return null;
			}
			try
			{
				return ((Component)character).GetComponentInChildren<CharacterVoiceHandler>();
			}
			catch
			{
				return null;
			}
		}

		internal static CharacterVoiceHandler HandlerById(string id)
		{
			if (string.IsNullOrEmpty(id))
			{
				return null;
			}
			try
			{
				List<Character> allCharacters = Character.AllCharacters;
				if (allCharacters == null)
				{
					return null;
				}
				for (int i = 0; i < allCharacters.Count; i++)
				{
					Character val = allCharacters[i];
					if ((Object)(object)val == (Object)null)
					{
						continue;
					}
					Player val2 = null;
					try
					{
						if ((Object)(object)((MonoBehaviourPun)val).photonView != (Object)null)
						{
							val2 = ((MonoBehaviourPun)val).photonView.Owner;
						}
					}
					catch
					{
					}
					if (val2 != null && string.Equals(BuiltinApps.PlayerId(val2), id, StringComparison.Ordinal))
					{
						return HandlerOf(val);
					}
				}
			}
			catch
			{
			}
			return null;
		}

		internal static CharacterVoiceHandler HandlerByActor(int actor)
		{
			if (actor <= 0)
			{
				return null;
			}
			try
			{
				List<Character> allCharacters = Character.AllCharacters;
				if (allCharacters == null)
				{
					return null;
				}
				for (int i = 0; i < allCharacters.Count; i++)
				{
					Character character = allCharacters[i];
					if (ActorOf(character) == actor)
					{
						return HandlerOf(character);
					}
				}
			}
			catch
			{
			}
			return null;
		}
	}
	public sealed class PiPhoneVoiceFilter
	{
		public bool LowPass;

		public float LowPassCutoff = 7500f;

		public float LowPassResonance = 1f;

		public bool HighPass;

		public float HighPassCutoff = 10f;

		public float HighPassResonance = 1f;

		public bool Reverb;

		public AudioReverbPreset ReverbPreset = (AudioReverbPreset)0;

		public bool Echo;

		public float EchoWet;

		public float EchoDry = 1f;

		public float EchoDelay = 10f;

		public float EchoDecay;

		public static PiPhoneVoiceFilter Dry()
		{
			return new PiPhoneVoiceFilter();
		}

		public static PiPhoneVoiceFilter Realm()
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			return new PiPhoneVoiceFilter
			{
				LowPass = true,
				LowPassCutoff = 2800f,
				LowPassResonance = 1.05f,
				HighPass = true,
				HighPassCutoff = 900f,
				HighPassResonance = 1f,
				Reverb = true,
				ReverbPreset = (AudioReverbPreset)9,
				Echo = true,
				EchoWet = 0.22f,
				EchoDry = 0.7f,
				EchoDelay = 280f,
				EchoDecay = 0.25f
			};
		}

		internal PiPhoneVoiceFilter Clone()
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			return new PiPhoneVoiceFilter
			{
				LowPass = LowPass,
				LowPassCutoff = LowPassCutoff,
				LowPassResonance = LowPassResonance,
				HighPass = HighPass,
				HighPassCutoff = HighPassCutoff,
				HighPassResonance = HighPassResonance,
				Reverb = Reverb,
				ReverbPreset = ReverbPreset,
				Echo = Echo,
				EchoWet = EchoWet,
				EchoDry = EchoDry,
				EchoDelay = EchoDelay,
				EchoDecay = EchoDecay
			};
		}
	}
	internal static class VoiceFx
	{
		[HarmonyPatch(typeof(VoiceObscuranceFilter), "Update")]
		private static class Patch_VoiceFx
		{
			private static bool Prefix(VoiceObscuranceFilter __instance)
			{
				try
				{
					if (!TryOverride(__instance, out var spec))
					{
						return true;
					}
					Write(__instance, spec);
					return false;
				}
				catch (Exception ex)
				{
					LogOnce("Voice filter patch failed: " + ex.Message);
					return true;
				}
			}
		}

		private static readonly Dictionary<int, PiPhoneVoiceFilter> ApiHold = new Dictionary<int, PiPhoneVoiceFilter>();

		private static readonly Dictionary<int, PiPhoneVoiceFilter> CallLayer = new Dictionary<int, PiPhoneVoiceFilter>();

		private static readonly Dictionary<int, PiPhoneVoiceFilter> VanillaSnap = new Dictionary<int, PiPhoneVoiceFilter>();

		private static bool _logged;

		internal static bool TryGet(string id, out PiPhoneVoiceFilter filter)
		{
			filter = null;
			CharacterVoiceHandler handler = ScoutQuery.HandlerById(id);
			return TryRead(handler, out filter);
		}

		internal static bool TryGet(int actor, out PiPhoneVoiceFilter filter)
		{
			filter = null;
			CharacterVoiceHandler handler = ScoutQuery.HandlerByActor(actor);
			return TryRead(handler, out filter);
		}

		internal static bool SetHold(string id, PiPhoneVoiceFilter spec)
		{
			return SetHold(ScoutQuery.HandlerById(id), spec);
		}

		internal static bool SetHold(int actor, PiPhoneVoiceFilter spec)
		{
			return SetHold(ScoutQuery.HandlerByActor(actor), spec);
		}

		internal static bool ClearHold(string id)
		{
			return ClearHoldActor(ActorFromId(id));
		}

		internal static bool ClearHold(int actor)
		{
			return ClearHoldActor(actor);
		}

		internal static void ClearAllHolds()
		{
			List<int> list = new List<int>(ApiHold.Keys);
			ApiHold.Clear();
			for (int i = 0; i < list.Count; i++)
			{
				MaybeRestore(list[i]);
			}
		}

		internal static bool IsHeld(string id)
		{
			int num = ActorFromId(id);
			return num > 0 && ApiHold.ContainsKey(num);
		}

		internal static void SetCallLayer(CharacterVoiceHandler handler, PiPhoneVoiceFilter spec)
		{
			int num = ActorOf(handler);
			if (num > 0 && spec != null)
			{
				RememberVanilla(num, ((Object)(object)handler != (Object)null) ? handler.voiceObscuranceFilter : null);
				CallLayer[num] = spec.Clone();
				Write(((Object)(object)handler != (Object)null) ? handler.voiceObscuranceFilter : null, spec);
			}
		}

		internal static void ClearCallLayer(CharacterVoiceHandler handler)
		{
			int num = ActorOf(handler);
			if (num > 0)
			{
				CallLayer.Remove(num);
				MaybeRestore(num);
			}
		}

		internal static void ClearAllCallLayers()
		{
			List<int> list = new List<int>(CallLayer.Keys);
			CallLayer.Clear();
			for (int i = 0; i < list.Count; i++)
			{
				MaybeRestore(list[i]);
			}
		}

		internal static bool HasCallLayer(CharacterVoiceHandler handler)
		{
			int num = ActorOf(handler);
			return num > 0 && CallLayer.ContainsKey(num);
		}

		private static bool SetHold(CharacterVoiceHandler handler, PiPhoneVoiceFilter spec)
		{
			int num = ActorOf(handler);
			if (num <= 0 || spec == null)
			{
				return false;
			}
			RememberVanilla(num, handler.voiceObscuranceFilter);
			ApiHold[num] = spec.Clone();
			Write(handler.voiceObscuranceFilter, spec);
			return true;
		}

		private static bool ClearHoldActor(int actor)
		{
			if (actor <= 0 || !ApiHold.Remove(actor))
			{
				return false;
			}
			MaybeRestore(actor);
			return true;
		}

		private static void RememberVanilla(int actor, VoiceObscuranceFilter fx)
		{
			if (actor > 0 && !((Object)(object)fx == (Object)null) && !VanillaSnap.ContainsKey(actor))
			{
				VanillaSnap[actor] = Read(fx);
			}
		}

		private static void MaybeRestore(int actor)
		{
			if (actor > 0 && !CallLayer.ContainsKey(actor) && !ApiHold.ContainsKey(actor))
			{
				CharacterVoiceHandler val = ScoutQuery.HandlerByActor(actor);
				VoiceObscuranceFilter val2 = (((Object)(object)val != (Object)null) ? val.voiceObscuranceFilter : null);
				if (VanillaSnap.TryGetValue(actor, out var value))
				{
					Write(val2, value);
					VanillaSnap.Remove(actor);
				}
				if ((Object)(object)val2 != (Object)null)
				{
					((Behaviour)val2).enabled = true;
				}
			}
		}

		private static bool TryRead(CharacterVoiceHandler handler, out PiPhoneVoiceFilter filter)
		{
			filter = null;
			if ((Object)(object)handler == (Object)null || (Object)(object)handler.voiceObscuranceFilter == (Object)null)
			{
				return false;
			}
			filter = Read(handler.voiceObscuranceFilter);
			return true;
		}

		private static PiPhoneVoiceFilter Read(VoiceObscuranceFilter fx)
		{
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			PiPhoneVoiceFilter piPhoneVoiceFilter = new PiPhoneVoiceFilter();
			if ((Object)(object)fx == (Object)null)
			{
				return piPhoneVoiceFilter;
			}
			AudioLowPassFilter lowPass = fx.lowPass;
			if ((Object)(object)lowPass != (Object)null)
			{
				piPhoneVoiceFilter.LowPass = ((Behaviour)lowPass).enabled;
				piPhoneVoiceFilter.LowPassCutoff = lowPass.cutoffFrequency;
				piPhoneVoiceFilter.LowPassResonance = lowPass.lowpassResonanceQ;
			}
			AudioHighPassFilter highPass = fx.highPass;
			if ((Object)(object)highPass != (Object)null)
			{
				piPhoneVoiceFilter.HighPass = ((Behaviour)highPass).enabled;
				piPhoneVoiceFilter.HighPassCutoff = highPass.cutoffFrequency;
				piPhoneVoiceFilter.HighPassResonance = highPass.highpassResonanceQ;
			}
			AudioReverbFilter reverb = fx.reverb;
			if ((Object)(object)reverb != (Object)null)
			{
				piPhoneVoiceFilter.Reverb = ((Behaviour)reverb).enabled;
				piPhoneVoiceFilter.ReverbPreset = reverb.reverbPreset;
			}
			AudioEchoFilter echo = fx.echo;
			if ((Object)(object)echo != (Object)null)
			{
				piPhoneVoiceFilter.Echo = ((Behaviour)echo).enabled;
				piPhoneVoiceFilter.EchoWet = echo.wetMix;
				piPhoneVoiceFilter.EchoDry = echo.dryMix;
				piPhoneVoiceFilter.EchoDelay = echo.delay;
				piPhoneVoiceFilter.EchoDecay = echo.decayRatio;
			}
			return piPhoneVoiceFilter;
		}

		internal static void Write(VoiceObscuranceFilter fx, PiPhoneVoiceFilter spec)
		{
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)fx == (Object)null || spec == null)
			{
				return;
			}
			try
			{
				AudioLowPassFilter lowPass = fx.lowPass;
				if ((Object)(object)lowPass != (Object)null)
				{
					((Behaviour)lowPass).enabled = spec.LowPass;
					if (spec.LowPass)
					{
						lowPass.cutoffFrequency = spec.LowPassCutoff;
						lowPass.lowpassResonanceQ = spec.LowPassResonance;
					}
				}
				AudioHighPassFilter highPass = fx.highPass;
				if ((Object)(object)highPass != (Object)null)
				{
					((Behaviour)highPass).enabled = spec.HighPass;
					if (spec.HighPass)
					{
						highPass.cutoffFrequency = spec.HighPassCutoff;
						highPass.highpassResonanceQ = spec.HighPassResonance;
					}
				}
				AudioReverbFilter reverb = fx.reverb;
				if ((Object)(object)reverb != (Object)null)
				{
					((Behaviour)reverb).enabled = spec.Reverb;
					if (spec.Reverb)
					{
						reverb.reverbPreset = spec.ReverbPreset;
					}
				}
				AudioEchoFilter echo = fx.echo;
				if ((Object)(object)echo != (Object)null)
				{
					((Behaviour)echo).enabled = spec.Echo;
					echo.wetMix = (spec.Echo ? spec.EchoWet : 0f);
					echo.dryMix = (spec.Echo ? spec.EchoDry : 1f);
					echo.delay = (spec.Echo ? spec.EchoDelay : 10f);
					echo.decayRatio = (spec.Echo ? spec.EchoDecay : 0f);
				}
			}
			catch (Exception ex)
			{
				LogOnce("Voice filter write failed: " + ex.Message);
			}
		}

		private static bool TryOverride(VoiceObscuranceFilter fx, out PiPhoneVoiceFilter spec)
		{
			spec = null;
			if ((Object)(object)fx == (Object)null || (Object)(object)fx._voiceHandler == (Object)null)
			{
				return false;
			}
			int num = ActorOf(fx._voiceHandler);
			if (num <= 0)
			{
				return false;
			}
			if (CallLayer.TryGetValue(num, out spec))
			{
				return true;
			}
			return ApiHold.TryGetValue(num, out spec);
		}

		private static int ActorOf(CharacterVoiceHandler handler)
		{
			if ((Object)(object)handler == (Object)null)
			{
				return 0;
			}
			return ScoutQuery.ActorOf(handler.m_character);
		}

		private static int ActorFromId(string id)
		{
			CharacterVoiceHandler handler = ScoutQuery.HandlerById(id);
			return ActorOf(handler);
		}

		private static void LogOnce(string message)
		{
			if (!_logged)
			{
				_logged = true;
				Plugin.LogError(message);
			}
		}
	}
	internal static class PhoneKeys
	{
		private struct Saved
		{
			public KeyCode Key;

			public KeyCode Modifier;
		}

		public const string Open = "pip.open";

		public const string Landscape = "pip.landscape";

		public const string Answer = "pip.answer";

		public const string Decline = "pip.decline";

		public const string CamCursor = "pip.camera.cursor";

		public const string CamFlip = "pip.camera.flip";

		public const string CamRotate = "pip.camera.rotate";

		public const string CamShutter = "pip.camera.shutter";

		public const string CamZoomIn = "pip.camera.zoomin";

		public const string CamZoomOut = "pip.camera.zoomout";

		public const string MusicPlay = "pip.music.play";

		public const string MusicNext = "pip.music.next";

		public const string MusicPrev = "pip.music.prev";

		public const string GameUp = "pip.games.up";

		public const string GameDown = "pip.games.down";

		public const string GameLeft = "pip.games.left";

		public const string GameRight = "pip.games.right";

		public const string TetrisRotate = "pip.tetris.rotate";

		public const string TetrisDrop = "pip.tetris.drop";

		public const string BreakoutServe = "pip.breakout.serve";

		private static readonly List<PiPhoneKeybind> Binds = new List<PiPhoneKeybind>(24);

		private static readonly Dictionary<string, Saved> SavedKeys = new Dictionary<string, Saved>(StringComparer.OrdinalIgnoreCase);

		private static string _captureId;

		private static Action _captureDone;

		private static bool _fileLoaded;

		public static event Action Changed;

		public static void RegisterBuiltins()
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: 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_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0281: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_030e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0354: Unknown result type (might be due to invalid IL or missing references)
			//IL_0390: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_043c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0492: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0518: Unknown result type (might be due to invalid IL or missing references)
			//IL_055b: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0636: Unknown result type (might be due to invalid IL or missing references)
			string[] alsoApps = new string[5] { "pip.snake", "pip.2048", "pip.mines", "pip.tetris", "pip.breakout" };
			PiPhoneKeybind piPhoneKeybind = new PiPhoneKeybind();
			piPhoneKeybind.Id = "pip.open";
			piPhoneKeybind.Label = "Open phone";
			piPhoneKeybind.Group = "Phone";
			piPhoneKeybind.DefaultKey = (KeyCode)112;
			piPhoneKeybind.DefaultModifier = (KeyCode)308;
			piPhoneKeybind.WithModifier = true;
			piPhoneKeybind.Global = true;
			piPhoneKeybind.Required = true;
			piPhoneKeybind.SortOrder = 0;
			piPhoneKeybind.OnPressed = PhoneMenu.Toggle;
			Add(piPhoneKeybind);
			piPhoneKeybind = new PiPhoneKeybind();
			piPhoneKeybind.Id = "pip.landscape";
			piPhoneKeybind.Label = "Rotate phone";
			piPhoneKeybind.Group = "Phone";
			piPhoneKeybind.DefaultKey = (KeyCode)284;
			piPhoneKeybind.PhoneOpen = true;
			piPhoneKeybind.SortOrder = 1;
			piPhoneKeybind.OnPressed = PhoneMenu.ToggleUserLandscape;
			Add(piPhoneKeybind);
			piPhoneKeybind = new PiPhoneKeybind();
			piPhoneKeybind.Id = "pip.answer";
			piPhoneKeybind.Label = "Answer call / open text";
			piPhoneKeybind.Group = "Alerts";
			piPhoneKeybind.DefaultKey = (KeyCode)282;
			piPhoneKeybind.Global = true;
			piPhoneKeybind.SortOrder = 10;
			piPhoneKeybind.OnPressed = AlertHud.HotkeyAnswer;
			Add(piPhoneKeybind);
			piPhoneKeybind = new PiPhoneKeybind();
			piPhoneKeybind.Id = "pip.decline";
			piPhoneKeybind.Label = "Decline call / dismiss text";
			piPhoneKeybind.Group = "Alerts";
			piPhoneKeybind.DefaultKey = (KeyCode)283;
			piPhoneKeybind.Global = true;
			piPhoneKeybind.SortOrder = 11;
			piPhoneKeybind.OnPressed = AlertHud.HotkeyDecline;
			Add(piPhoneKeybind);
			piPhoneKeybind = new PiPhoneKeybind();
			piPhoneKeybind.Id = "pip.camera.cursor";
			piPhoneKeybind.Label = "Walk around";
			piPhoneKeybind.Group = "Phone";
			piPhoneKeybind.PhoneOpen = true;
			piPhoneKeybind.DefaultKey = (KeyCode)308;
			piPhoneKeybind.SortOrder = 20;
			piPhoneKeybind.OnPressed = PhoneMenu.TogglePlayThrough;
			Add(piPhoneKeybind);
			Add(new PiPhoneKeybind
			{
				Id = "pip.camera.flip",
				Label = "Flip camera",
				Group = "Camera",
				AppId = "pip.camera",
				DefaultKey = (KeyCode)102,
				SortOrder = 21
			});
			Add(new PiPhoneKeybind
			{
				Id = "pip.camera.rotate",
				Label = "Tall / wide",
				Group = "Camera",
				AppId = "pip.camera",
				DefaultKey = (KeyCode)114,
				SortOrder = 22
			});
			Add(new PiPhoneKeybind
			{
				Id = "pip.camera.shutter",
				Label = "Shutter",
				Group = "Camera",
				AppId = "pip.camera",
				DefaultKey = (KeyCode)118,
				SortOrder = 23
			});
			Add(new PiPhoneKeybind
			{
				Id = "pip.camera.zoomin",
				Label = "Zoom in",
				Group = "Camera",
				AppId = "pip.camera",
				DefaultKey = (KeyCode)0,
				SortOrder = 24
			});
			Add(new PiPhoneKeybind
			{
				Id = "pip.camera.zoomout",
				Label = "Zoom out",
				Group = "Camera",
				AppId = "pip.camera",
				DefaultKey = (KeyCode)0,
				SortOrder = 25
			});
			piPhoneKeybind = new PiPhoneKeybind();
			piPhoneKeybind.Id = "pip.music.play";
			piPhoneKeybind.Label = "Play / pause music";
			piPhoneKeybind.Group = "Music";
			piPhoneKeybind.DefaultKey = (KeyCode)0;
			piPhoneKeybind.Global = true;
			piPhoneKeybind.SortOrder = 30;
			piPhoneKeybind.OnPressed = MusicPlayer.Toggle;
			Add(piPhoneKeybind);
			piPhoneKeybind = new PiPhoneKeybind();
			piPhoneKeybind.Id = "pip.music.next";
			piPhoneKeybind.Label = "Next song";
			piPhoneKeybind.Group = "Music";
			piPhoneKeybind.DefaultKey = (KeyCode)0;
			piPhoneKeybind.Global = true;
			piPhoneKeybind.SortOrder = 31;
			piPhoneKeybind.OnPressed = MusicPlayer.Next;
			Add(piPhoneKeybind);
			piPhoneKeybind = new PiPhoneKeybind();
			piPhoneKeybind.Id = "pip.music.prev";
			piPhoneKeybind.Label = "Previous song";
			piPhoneKeybind.Group = "Music";
			piPhoneKeybind.DefaultKey = (KeyCode)0;
			piPhoneKeybind.Global = true;
			piPhoneKeybind.SortOrder = 32;
			piPhoneKeybind.OnPressed = MusicPlayer.Prev;
			Add(piPhoneKeybind);
			Add(new PiPhoneKeybind
			{
				Id = "pip.games.up",
				Label = "Up",
				Group = "Games",
				DefaultKey = (KeyCode)119,
				AlsoApps = alsoApps,
				SortOrder = 40
			});
			Add(new PiPhoneKeybind
			{
				Id = "pip.games.down",
				Label = "Down",
				Group = "Games",
				DefaultKey = (KeyCode)115,
				AlsoApps = alsoApps,
				SortOrder = 41
			});
			Add(new PiPhoneKeybind
			{
				Id = "pip.games.left",
				Label = "Left",
				Group = "Games",
				DefaultKey = (KeyCode)97,
				AlsoApps = alsoApps,
				SortOrder = 42
			});
			Add(new PiPhoneKeybind
			{
				Id = "pip.games.right",
				Label = "Right",
				Group = "Games",
				DefaultKey = (KeyCode)100,
				AlsoApps = alsoApps,
				SortOrder = 43
			});
			Add(new PiPhoneKeybind
			{
				Id = "pip.tetris.rotate",
				Label = "Rotate",
				Group = "Stacker",
				AppId = "pip.tetris",
				DefaultKey = (KeyCode)0,
				SortOrder = 50
			});
			Add(new PiPhoneKeybind
			{
				Id = "pip.tetris.drop",
				Label = "Hard drop",
				Group = "Stacker",
				AppId = "pip.tetris",
				DefaultKey = (KeyCode)32,
				SortOrder = 51
			});
			Add(new PiPhoneKeybind
			{
				Id = "pip.breakout.serve",
				Label = "Serve",
				Group = "Brick Break",
				AppId = "pip.breakout",
				DefaultKey = (KeyCode)32,
				SortOrder = 60
			});
		}

		public static void Add(PiPhoneKeybind bind)
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: 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_003f: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			if (bind != null && !string.IsNullOrEmpty(bind.Id))
			{
				int num = IndexOf(bind.Id);
				if (num >= 0)
				{
					bind.Key = Binds[num].Key;
					bind.Modifier = Binds[num].Modifier;
					Binds[num] = bind;
				}
				else
				{
					bind.Key = bind.DefaultKey;
					bind.Modifier = bind.DefaultModifier;
					Binds.Add(bind);
				}
				ApplySaved(bind);
				EnforceRequired(bind);
				Sort();
				RaiseChanged();
			}
		}

		public static bool Remove(string id)
		{
			int num = IndexOf(id);
			if (num < 0)
			{
				return false;
			}
			Binds.RemoveAt(num);
			RaiseChanged();
			return true;
		}

		public static PiPhoneKeybind Find(string id)
		{
			int num = IndexOf(id);
			return (num >= 0) ? Binds[num] : null;
		}

		public static PiPhoneKeybind[] All()
		{
			return Binds.ToArray();
		}

		public static bool Down(string id)
		{
			PiPhoneKeybind bind = Find(id);
			return Down(bind);
		}

		public static bool Held(string id)
		{
			//IL_0025: 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)
			PiPhoneKeybind piPhoneKeybind = Find(id);
			if (!Ready(piPhoneKeybind) || !ShouldFire(piPhoneKeybind))
			{
				return false;
			}
			if (!Input.GetKey(piPhoneKeybind.Key))
			{
				return false;
			}
			return ModifierOk(piPhoneKeybind.Modifier);
		}

		public static string Format(string id)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			PiPhoneKeybind piPhoneKeybind = Find(id);
			if (piPhoneKeybind == null)
			{
				return "None";
			}
			return Format(piPhoneKeybind.Key, piPhoneKeybind.Modifier);
		}

		public static string Format(KeyCode key, KeyCode modifier)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Invalid comparison between Unknown and I4
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			if ((int)key == 0)
			{
				return "None";
			}
			if ((int)modifier == 0)
			{
				return Pretty(key);
			}
			return Pretty(modifier) + "+" + Pretty(key);
		}

		public unsafe static string Pretty(KeyCode key)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Invalid comparison between Unknown and I4
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected I4, but got Unknown
			KeyCode val = key;
			KeyCode val2 = val;
			if ((int)val2 != 0)
			{
				if ((int)val2 != 32)
				{
					switch (val2 - 303)
					{
					case 2:
					case 3:
						return "Ctrl";
					case 4:
					case 5:
						return "Alt";
					case 0:
					case 1:
						return "Shift";
					default:
						return ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString();
					}
				}
				return "Space";
			}
			return "None";
		}

		public static void Set(string id, KeyCode key, KeyCode modifier)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Invalid comparison between Unknown and I4
			//IL_003e: 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)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: 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_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: 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)
			PiPhoneKeybind piPhoneKeybind = Find(id);
			if (piPhoneKeybind != null && (!piPhoneKeybind.Required || (int)key != 0))
			{
				if (!piPhoneKeybind.WithModifier)
				{
					modifier = (KeyCode)0;
				}
				piPhoneKeybind.Key = key;
				piPhoneKeybind.Modifier = modifier;
				SavedKeys[id] = new Saved
				{
					Key = key,
					Modifier = modifier
				};
				Save();
				SyncConfig(piPhoneKeybind);
				switch (id)
				{
				case "pip.games.up":
					PhoneTheme.SnakeUp = key;
					break;
				case "pip.games.down":
					PhoneTheme.SnakeDown = key;
					break;
				case "pip.games.left":
					PhoneTheme.SnakeLeft = key;
					break;
				case "pip.games.right":
					PhoneTheme.SnakeRight = key;
					break;
				}
				RaiseChanged();
			}
		}

		public static void Clear(string id)
		{
			PiPhoneKeybind piPhoneKeybind = Find(id);
			if (piPhoneKeybind != null && !piPhoneKeybind.Required)
			{
				Set(id, (KeyCode)0, (KeyCode)0);
			}
		}

		public static void BeginCapture(string id, Action onDone)
		{
			if (Find(id) != null)
			{
				_captureId = id;
				_captureDone = onDone;
				Plugin.CapturingHotkey = true;
			}
		}

		public static bool TickCapture()
		{
			//IL_006b: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: 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_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.CapturingHotkey || string.IsNullOrEmpty(_captureId))
			{
				return Plugin.CapturingHotkey;
			}
			if (Input.GetKeyDown((KeyCode)27))
			{
				EndCapture();
				return true;
			}
			PiPhoneKeybind piPhoneKeybind = Find(_captureId);
			foreach (KeyCode value in Enum.GetValues(typeof(KeyCode)))
			{
				if (IsIgnored(value, piPhoneKeybind?.WithModifier ?? false) || !Input.GetKeyDown(value))
				{
					continue;
				}
				KeyCode modifier = (KeyCode)0;
				if (piPhoneKeybind != null && piPhoneKeybind.WithModifier)
				{
					if (Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305))
					{
						modifier = (KeyCode)306;
					}
					else if (Input.GetKey((KeyCode)308) || Input.GetKey((KeyCode)307))
					{
						modifier = (KeyCode)308;
					}
					else if (Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303))
					{
						modifier = (KeyCode)304;
					}
				}
				Set(_captureId, value, modifier);
				EndCapture();
				return true;
			}
			return true;
		}

		public static void FirePressed()
		{
			if (Plugin.CapturingHotkey)
			{
				return;
			}
			for (int i = 0; i < Binds.Count; i++)
			{
				PiPhoneKeybind piPhoneKeybind = Binds[i];
				if (piPhoneKeybind != null && piPhoneKeybind.OnPressed != null && (!(piPhoneKeybind.Id == "pip.open") || !PhoneUi.IsTyping()) && Down(piPhoneKeybind))
				{
					try
					{
						piPhoneKeybind.OnPressed();
					}
					catch (Exception ex)
					{
						Plugin.LogError("Keybind '" + piPhoneKeybind.Id + "': " + ex.Message);
					}
				}
			}
		}

		public static void Load()
		{
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: 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_00db: Unknown result type (might be due to invalid IL or missing references)
			SavedKeys.Clear();
			string path = Path.Combine(PhoneStore.RootDir, "keys.txt");
			_fileLoaded = File.Exists(path);
			if (_fileLoaded)
			{
				try
				{
					string[] array = File.ReadAllLines(path);
					foreach (string text in array)
					{
						int num = text.IndexOf('=');
						if (num > 0)
						{
							string text2 = text.Substring(0, num).Trim();
							string val = text.Substring(num + 1).Trim();
							bool flag = text2.EndsWith(".mod", StringComparison.OrdinalIgnoreCase);
							string key = (flag ? text2.Substring(0, text2.Length - 4) : text2);
							KeyCode val2 = ParseKey(val, (KeyCode)0);
							SavedKeys.TryGetValue(key, out var value);
							if (flag)
							{
								value.Modifier = val2;
							}
							else
							{
								value.Key = val2;
							}
							SavedKeys[key] = value;
						}
					}
				}
				catch (Exception ex)
				{
					Plugin.LogError("Keybinds load failed: " + ex.Message);
				}
			}
			for (int j = 0; j < Binds.Count; j++)
			{
				ApplySaved(Binds[j]);
			}
			if (!_fileLoaded)
			{
				SeedFromLegacy();
			}
			bool flag2 = false;
			for (int k = 0; k < Binds.Count; k++)
			{
				if (EnforceRequired(Binds[k]))
				{
					flag2 = true;
				}
			}
			if (flag2)
			{
				Save();
			}
		}

		private static void SeedFromLegacy()
		{
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Invalid comparison between Unknown and I4
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Invalid comparison between Unknown and I4
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Invalid comparison between Unknown and I4
			//IL_0192: 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_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Invalid comparison between Unknown and I4
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: 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_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: 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)
			Plugin instance = Plugin.Instance;
			if ((Object)(object)instance != (Object)null)
			{
				if (instance.MenuKey != null)
				{
					Set("pip.open", instance.MenuKey.Value, (KeyCode)((instance.MenuModifier != null) ? ((int)instance.MenuModifier.Value) : 0));
				}
				if (instance.LandscapeKey != null)
				{
					Set("pip.landscape", instance.LandscapeKey.Value, (KeyCode)0);
				}
				if (instance.AnswerKey != null)
				{
					Set("pip.answer", instance.AnswerKey.Value, (KeyCode)0);
				}
				if (instance.DeclineKey != null)
				{
					Set("pip.decline", instance.DeclineKey.Value, (KeyCode)0);
				}
				if (instance.CameraCursorKey != null)
				{
					Set("pip.camera.cursor", instance.CameraCursorKey.Value, (KeyCode)0);
				}
				if (instance.CameraFlipKey != null)
				{
					Set("pip.camera.flip", instance.CameraFlipKey.Value, (KeyCode)0);
				}
				if (instance.CameraRotateKey != null)
				{
					Set("pip.camera.rotate", instance.CameraRotateKey.Value, (KeyCode)0);
				}
				if (instance.CameraShutterKey != null)
				{
					Set("pip.camera.shutter", instance.CameraShutterKey.Value, (KeyCode)0);
				}
			}
			if ((int)PhoneTheme.SnakeUp != 119)
			{
				Set("pip.games.up", PhoneTheme.SnakeUp, (KeyCode)0);
			}
			if ((int)PhoneTheme.SnakeDown != 115)
			{
				Set("pip.games.down", PhoneTheme.SnakeDown, (KeyCode)0);
			}
			if ((int)PhoneTheme.SnakeLeft != 97)
			{
				Set("pip.games.left", PhoneTheme.SnakeLeft, (KeyCode)0);
			}
			if ((int)PhoneTheme.SnakeRight != 100)
			{
				Set("pip.games.right", PhoneTheme.SnakeRight, (KeyCode)0);
			}
			Save();
		}

		private static void Save()
		{
			//IL_0040: 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)
			try
			{
				PhoneStore.EnsureDir();
				StringBuilder stringBuilder = new StringBuilder();
				for (int i = 0; i < Binds.Count; i++)
				{
					PiPhoneKeybind piPhoneKeybind = Binds[i];
					if (piPhoneKeybind != null)
					{
						stringBuilder.Append(piPhoneKeybind.Id).Append('=').Append(piPhoneKeybind.Key)
							.Append('\n');
						if (piPhoneKeybind.WithModifier)
						{
							stringBuilder.Append(piPhoneKeybind.Id).Append(".mod=").Append(piPhoneKeybind.Modifier)
								.Append('\n');
						}
					}
				}
				File.WriteAllText(Path.Combine(PhoneStore.RootDir, "keys.txt"), stringBuilder.ToString());
				_fileLoaded = true;
			}
			catch (Exception ex)
			{
				Plugin.LogError("Keybinds save failed: " + ex.Message);
			}
		}

		private static bool Down(PiPhoneKeybind bind)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			if (!Ready(bind) || !ShouldFire(bind))
			{
				return false;
			}
			if (!Input.GetKeyDown(bind.Key))
			{
				return false;
			}
			return ModifierOk(bind.Modifier);
		}

		private static bool Ready(PiPhoneKeybind bind)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Invalid comparison between Unknown and I4
			return bind != null && (int)bind.Key > 0;
		}

		internal static bool ShouldFire(PiPhoneKeybind bind)
		{
			if (bind == null)
			{
				return false;
			}
			if (bind.Global)
			{
				return true;
			}
			if (!PhoneMenu.IsOpen)
			{
				return false;
			}
			if (bind.PhoneOpen && string.IsNullOrEmpty(bind.AppId) && (bind.AlsoApps == null || bind.AlsoApps.Length == 0))
			{
				return true;
			}
			string currentAppId = PhoneMenu.CurrentAppId;
			if (string.IsNullOrEmpty(currentAppId))
			{
				return false;
			}
			if (!string.IsNullOrEmpty(bind.AppId) && string.Equals(bind.AppId, currentAppId, StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			if (bind.AlsoApps == null)
			{
				return false;
			}
			for (int i = 0; i < bind.AlsoApps.Length; i++)
			{
				if (string.Equals(bind.AlsoApps[i], currentAppId, StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
			}
			return false;
		}

		private static bool ModifierOk(KeyCode modifier)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Invalid comparison between Unknown and I4
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Invalid comparison between Unknown and I4
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Invalid comparison between Unknown and I4
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Invalid comparison between Unknown and I4
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Invalid comparison between Unknown and I4
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Invalid comparison between Unknown and I4
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			if ((int)modifier == 0)
			{
				return true;
			}
			if ((int)modifier == 306 || (int)modifier == 305)
			{
				return Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305);
			}
			if ((int)modifier == 308 || (int)modifier == 307)
			{
				return Input.GetKey((KeyCode)308) || Input.GetKey((KeyCode)307);
			}
			if ((int)modifier == 304 || (int)modifier == 303)
			{
				return Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303);
			}
			return Input.GetKey(modifier);
		}

		private static void ApplySaved(PiPhoneKeybind bind)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Invalid comparison between Unknown and I4
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			if (bind != null && SavedKeys.TryGetValue(bind.Id, out var value) && (!bind.Required || (int)value.Key != 0))
			{
				bind.Key = value.Key;
				if (bind.WithModifier)
				{
					bind.Modifier = value.Modifier;
				}
			}
		}

		private static bool EnforceRequired(PiPhoneKeybind bind)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Invalid comparison between Unknown and I4
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: 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_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: 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_0060: Unknown result type (might be due to invalid IL or missing references)
			if (bind == null || !bind.Required || (int)bind.Key > 0)
			{
				return false;
			}
			bind.Key = bind.DefaultKey;
			bind.Modifier = bind.DefaultModifier;
			SavedKeys[bind.Id] = new Saved
			{
				Key = bind.Key,
				Modifier = bind.Modifier
			};
			return true;
		}

		private static void SyncConfig(PiPhoneKeybind bind)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: 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_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			Plugin instance = Plugin.Instance;
			if ((Object)(object)instance == (Object)null || bind == null)
			{
				return;
			}
			if (bind.Id == "pip.open")
			{
				if (instance.MenuKey != null)
				{
					instance.MenuKey.Value = bind.Key;
				}
				if (instance.MenuModifier != null)
				{
					instance.MenuModifier.Value = bind.Modifier;
				}
			}
			else if (bind.Id == "pip.landscape" && instance.LandscapeKey != null)
			{
				instance.LandscapeKey.Value = bind.Key;
			}
			else if (bind.Id == "pip.answer" && instance.AnswerKey != null)
			{
				instance.AnswerKey.Value = bind.Key;
			}
			else if (bind.Id == "pip.decline" && instance.DeclineKey != null)
			{
				instance.DeclineKey.Value = bind.Key;
			}
			else if (bind.Id == "pip.camera.cursor" && instance.CameraCursorKey != null)
			{
				instance.CameraCursorKey.Value = bind.Key;
			}
			else if (bind.Id == "pip.camera.flip" && instance.CameraFlipKey != null)
			{
				instance.CameraFlipKey.Value = bind.Key;
			}
			else if (bind.Id == "pip.camera.rotate" && instance.CameraRotateKey != null)
			{
				instance.CameraRotateKey.Value = bind.Key;
			}
			else if (bind.Id == "pip.camera.shutter" && instance.CameraShutterKey != null)
			{
				instance.CameraShutterKey.Value = bind.Key;
			}
		}

		private static void EndCapture()
		{
			Plugin.CapturingHotkey = false;
			Plugin.CaptureEndedFrame = Time.frameCount;
			_captureId = null;
			Action captureDone = _captureDone;
			_captureDone = null;
			captureDone?.Invoke();
		}

		private static bool IsIgnored(KeyCode key, bool modifiersAreMods)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected I4, but got Unknown
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: 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_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: 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)
			//IL_0053: Invalid comparison between Unknown and I4
			if ((int)key == 0 || (int)key == 27)
			{
				return true;
			}
			int num = (int)key;
			if (num >= 323 && num <= 329)
			{
				return true;
			}
			if (!modifiersAreMods)
			{
				return false;
			}
			if (key - 303 <= 10)
			{
				return true;
			}
			return false;
		}

		private static KeyCode ParseKey(string val, KeyCode fallback)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: 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_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(val))
			{
				return fallback;
			}
			try
			{
				return (KeyCode)Enum.Parse(typeof(KeyCode), val, ignoreCase: true);
			}
			catch
			{
				return fallback;
			}
		}

		private static int IndexOf(string id)
		{
			if (string.IsNullOrEmpty(id))
			{
				return -1;
			}
			for (int i = 0; i < Binds.Count; i++)
			{
				if (Binds[i] != null && string.Equals(Binds[i].Id, id, StringComparison.OrdinalIgnoreCase))
				{
					return i;
				}
			}
			return -1;
		}

		private static void Sort()
		{
			Binds.Sort(Compare);
		}

		private static int Compare(PiPhoneKeybind a, PiPhoneKeybind b)
		{
			int num = string.Compare((a != null) ? a.Group : string.Empty, (b != null) ? b.Group : string.Empty, StringComparison.OrdinalIgnoreCase);
			if (num != 0)
			{
				return num;
			}
			int num2 = (a?.SortOrder ?? 0).CompareTo(b?.SortOrder ?? 0);
			if (num2 != 0)
			{
				return num2;
			}
			return string.Compare((a != null) ? a.Label : string.Empty, (b != null) ? b.Label : string.Empty, StringComparison.OrdinalIgnoreCase);
		}

		private static void RaiseChanged()
		{
			PhoneKeys.Changed?.Invoke();
		}
	}
	public static class PhoneUi
	{
		private sealed class ReadableLabel : MonoBehaviour
		{
		}

		public static Color Bezel = new Color(0.07f, 0.07f, 0.08f, 1f);

		public static Color Screen = new Color(0.08f, 0.1f, 0.13f, 1f);

		public static Color Surface = new Color(0.16f, 0.18f, 0.21f, 0.96f);

		public static Color SurfaceAlt = new Color(0.2f, 0.22f, 0.26f, 1f);

		public static Color Text = new Color(0.96f, 0.97f, 0.98f, 1f);

		public static Color ClockText = new Color(0.96f, 0.97f, 0.98f, 1f);

		public static Color ButtonText = new Color(0.96f, 0.97f, 0.98f, 1f);

		public static Color TextDim = new Color(0.7f, 0.74f, 0.78f, 1f);

		public static Color Accent = new Color(0.24f, 0.86f, 0.52f, 1f);

		public static Color CallGreen = new Color(0.18f, 0.72f, 0.38f, 1f);

		public static Color HangRed = new Color(0.86f, 0.24f, 0.24f, 1f);

		public static Color Nav = new Color(0.1f, 0.11f, 0.13f, 1f);

		public static Color PhoneIcon = new Color(0.18f, 0.72f, 0.38f, 1f);

		public static Color MessagesIcon = new Color(0.15f, 0.55f, 0.92f, 1f);

		public static Color VoicemailIcon = new Color(0.95f, 0.55f, 0.16f, 1f);

		public static Color SettingsIcon = new Color(0.45f, 0.48f, 0.52f, 1f);

		public static Color NotesIcon = new Color(0.96f, 0.78f, 0.2f, 1f);

		public static Color CameraIcon = new Color(0.35f, 0.72f, 0.82f, 1f);

		public static Color PhotosIcon = new Color(0.72f, 0.42f, 0.82f, 1f);

		public static Color MemosIcon = new Color(0.92f, 0.32f, 0.42f, 1f);

		private static Sprite _white;

		private static Sprite _circle;

		private static Sprite _wallpaper;

		private static readonly Dictionary<int, Sprite> RoundedCache = new Dictionary<int, Sprite>();

		private static TMP_FontAsset _cachedFont;

		private static int _cachedSceneHandle = -1;

		private static TMP_FontAsset _readableFont;

		public static bool Landscape => PiPhoneApi.IsLandscape;

		public static Canvas CreateOverlayCanvas(GameObject root, int sortingOrder)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			Canvas val = root.GetComponent<Canvas>() ?? root.AddComponent<Canvas>();
			val.renderMode = (RenderMode)0;
			val.sortingOrder = sortingOrder;
			val.additionalShaderChannels = (AdditionalCanvasShaderChannels)25;
			CanvasScaler val2 = root.GetComponent<CanvasScaler>() ?? root.AddComponent<CanvasScaler>();
			val2.uiScaleMode = (ScaleMode)1;
			val2.referenceResolution = new Vector2(1920f, 1080f);
			val2.matchWidthOrHeight = 1f;
			if ((Object)(object)root.GetComponent<GraphicRaycaster>() == (Object)null)
			{
				root.AddComponent<GraphicRaycaster>();
			}
			return val;
		}

		public static RectTransform CreateImage(Transform parent, string name, Sprite sprite, Color color)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			//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_007c: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(Image)
			});
			val.transform.SetParent(parent, false);
			Image component = val.GetComponent<Image>();
			component.sprite = sprite;
			int num;
			if ((Object)(object)sprite != (Object)null)
			{
				Vector4 border = sprite.border;
				if (((Vector4)(ref border)).sqrMagnitude > 0f)
				{
					num = 1;
					goto IL_0075;
				}
			}
			num = 0;
			goto IL_0075;
			IL_0075:
			component.type = (Type)num;
			((Graphic)component).color = color;
			((Graphic)component).raycastTarget = true;
			return val.GetComponent<RectTransform>();
		}

		public static TextMeshProUGUI CreateLabel(Transform parent, string name, string text, float fontSize, FontStyles style = (FontStyles)0, TextAlignmentOptions align = (TextAlignmentOptions)513)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[2]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer)
			});
			val.transform.SetParent(parent, false);
			TextMeshProUGUI val2 = val.AddComponent<TextMeshProUGUI>();
			((TMP_Text)val2).text = text ?? string.Empty;
			((TMP_Text)val2).fontSize = fontSize * PhoneTheme.FontScale;
			((TMP_Text)val2).fontStyle = style;
			((TMP_Text)val2).alignment = align;
			((Graphic)val2).color = Text;
			((Graphic)val2).raycastTarget = false;
			((TMP_Text)val2).enableWordWrapping = false;
			((TMP_Text)val2).overflowMode = (TextOverflowModes)0;
			((MaskableGraphic)val2).maskable = true;
			ApplyFont(val2);
			return val2;
		}

		public static Button CreateButton(Transform parent, string label, UnityAction onClick, Vector2 preferredSize)
		{
			//IL_0017: 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_0062: 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)
			RectTransform val = CreateImage(parent, "Btn_" + Sanitize(label), ButtonShape(), SurfaceAlt);
			Image component = ((Component)val).GetComponent<Image>();
			Button val2 = ((Component)val).gameObject.AddComponent<Button>();
			((Selectable)val2).targetGraphic = (Graphic)(object)component;
			((Selectable)val2).colors = TintColors();
			TextMeshProUGUI val3 = CreateLabel((Transform)(object)val, "Text", label, 18f, (FontStyles)0, (TextAlignmentOptions)514);
			((Graphic)val3).color = ButtonText;
			Stretch(((TMP_Text)val3).rectTransform, 8f, 4f);
			ApplySize(val, preferredSize);
			if (onClick != null)
			{
				((UnityEvent)val2.onClick).AddListener(onClick);
			}
			return val2;
		}

		public static Button CreateIconChip(Transform parent, string glyph, Sprite icon, UnityAction onClick, bool lit, Vector2 size, bool tintIcon = true)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: 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_0075: 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_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: 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_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			Color color = (lit ? Accent : SurfaceAlt);
			RectTransform val = CreateImage(parent, "Chip", ChipShape(), color);
			Image component = ((Component)val).GetComponent<Image>();
			Button val2 = ((Component)val).gameObject.AddComponent<Button>();
			((Selectable)val2).targetGraphic = (Graphic)(object)component;
			((Selectable)val2).colors = TintColors();
			Color color2 = (Color)((!tintIcon) ? Color.white : (lit ? new Color(0.1f, 0.11f, 0.12f, 1f) : ButtonText));
			if ((Object)(object)icon != (Object)null)
			{
				RectTransform val3 = CreateImage((Transform)(object)val, "I", icon, color2);
				Stretch(val3, 6f, 6f);
				Image component2 = ((Component)val3).GetCompone