Decompiled source of DesktopBuddy v1.1.0

Renderer/BepInEx/plugins/DesktopBuddySharedTextureBridge/DesktopBuddySharedTextureBridge.dll

Decompiled a month ago
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
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.RegularExpressions;
using BepInEx;
using BepInEx.Logging;
using DesktopBuddy.Shared;
using HarmonyLib;
using InterprocessLib;
using Microsoft.CodeAnalysis;
using Renderite.Shared;
using Renderite.Unity;
using UMP;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("DesktopBuddySharedTextureBridge")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+e5251e37dd743ac1b5ffad5e3f95aa6063a3aabc")]
[assembly: AssemblyProduct("DesktopBuddySharedTextureBridge")]
[assembly: AssemblyTitle("DesktopBuddySharedTextureBridge")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace DesktopBuddy.Shared
{
	internal static class SharedTextureBridgeProtocol
	{
		private const string BaseOwnerId = "DesktopBuddy.SharedTexture.v2";

		private const string BaseQueueName = "DesktopBuddy.SharedTexture.v2";

		private static readonly string QueueScope = GetQueueScope();

		public static readonly string OwnerId = GetScopedName("DesktopBuddy.SharedTexture.v2");

		public static readonly string QueueName = GetScopedName("DesktopBuddy.SharedTexture.v2");

		public const string StartMessageId = "Start";

		public const string StopMessageId = "Stop";

		public const string RunningMessageId = "Running";

		public const string StoppedMessageId = "Stopped";

		public const string RendererDeviceMessageId = "RendererDevice";

		public const int MaxTextureSlots = 4096;

		public const int MagicIndexBase = 10000;

		private static string GetScopedName(string baseName)
		{
			if (!string.IsNullOrEmpty(QueueScope))
			{
				return baseName + "." + QueueScope;
			}
			return baseName;
		}

		private static string GetQueueScope()
		{
			string value = GetArgumentValue("-shmprefix") ?? GetArgumentValue("--shmprefix");
			if (string.IsNullOrWhiteSpace(value))
			{
				return string.Empty;
			}
			return "shm" + ComputeStableHash(value).ToString("X16");
		}

		private static string GetArgumentValue(string name)
		{
			string[] commandLineArgs;
			try
			{
				commandLineArgs = Environment.GetCommandLineArgs();
			}
			catch
			{
				return null;
			}
			for (int i = 0; i < commandLineArgs.Length; i++)
			{
				string text = commandLineArgs[i];
				if (text == null)
				{
					continue;
				}
				if (string.Equals(text, name, StringComparison.OrdinalIgnoreCase))
				{
					if (i + 1 < commandLineArgs.Length)
					{
						return commandLineArgs[i + 1];
					}
					return null;
				}
				string text2 = name + "=";
				if (text.StartsWith(text2, StringComparison.OrdinalIgnoreCase))
				{
					return text.Substring(text2.Length);
				}
			}
			return null;
		}

		private static ulong ComputeStableHash(string value)
		{
			ulong num = 14695981039346656037uL;
			for (int i = 0; i < value.Length; i++)
			{
				num ^= value[i];
				num *= 1099511628211L;
			}
			return num;
		}
	}
	internal sealed class SimpleMemoryPackerPool : IMemoryPackerEntityPool
	{
		public static readonly SimpleMemoryPackerPool Instance = new SimpleMemoryPackerPool();

		private SimpleMemoryPackerPool()
		{
		}

		T IMemoryPackerEntityPool.Borrow<T>()
		{
			return new T();
		}

		void IMemoryPackerEntityPool.Return<T>(T value)
		{
		}
	}
	internal sealed class SharedTextureStartMessage : IMemoryPackable
	{
		public int SlotId;

		public int Generation;

		public long SharedTextureHandle;

		public string SharedTextureName;

		public int SharedTextureWidth;

		public int SharedTextureHeight;

		public void Pack(ref MemoryPacker packer)
		{
			((MemoryPacker)(ref packer)).Write<int>(SlotId);
			((MemoryPacker)(ref packer)).Write<int>(Generation);
			((MemoryPacker)(ref packer)).Write<long>(SharedTextureHandle);
			((MemoryPacker)(ref packer)).Write(SharedTextureName);
			((MemoryPacker)(ref packer)).Write<int>(SharedTextureWidth);
			((MemoryPacker)(ref packer)).Write<int>(SharedTextureHeight);
		}

		public void Unpack(ref MemoryUnpacker unpacker)
		{
			((MemoryUnpacker)(ref unpacker)).Read<int>(ref SlotId);
			((MemoryUnpacker)(ref unpacker)).Read<int>(ref Generation);
			((MemoryUnpacker)(ref unpacker)).Read<long>(ref SharedTextureHandle);
			((MemoryUnpacker)(ref unpacker)).Read(ref SharedTextureName);
			((MemoryUnpacker)(ref unpacker)).Read<int>(ref SharedTextureWidth);
			((MemoryUnpacker)(ref unpacker)).Read<int>(ref SharedTextureHeight);
		}
	}
	internal sealed class SharedTextureStopMessage : IMemoryPackable
	{
		public int SlotId;

		public int Generation;

		public void Pack(ref MemoryPacker packer)
		{
			((MemoryPacker)(ref packer)).Write<int>(SlotId);
			((MemoryPacker)(ref packer)).Write<int>(Generation);
		}

		public void Unpack(ref MemoryUnpacker unpacker)
		{
			((MemoryUnpacker)(ref unpacker)).Read<int>(ref SlotId);
			((MemoryUnpacker)(ref unpacker)).Read<int>(ref Generation);
		}
	}
	internal sealed class SharedTextureRunningMessage : IMemoryPackable
	{
		public int SlotId;

		public int Generation;

		public int Width;

		public int Height;

		public void Pack(ref MemoryPacker packer)
		{
			((MemoryPacker)(ref packer)).Write<int>(SlotId);
			((MemoryPacker)(ref packer)).Write<int>(Generation);
			((MemoryPacker)(ref packer)).Write<int>(Width);
			((MemoryPacker)(ref packer)).Write<int>(Height);
		}

		public void Unpack(ref MemoryUnpacker unpacker)
		{
			((MemoryUnpacker)(ref unpacker)).Read<int>(ref SlotId);
			((MemoryUnpacker)(ref unpacker)).Read<int>(ref Generation);
			((MemoryUnpacker)(ref unpacker)).Read<int>(ref Width);
			((MemoryUnpacker)(ref unpacker)).Read<int>(ref Height);
		}
	}
	internal sealed class SharedTextureStoppedMessage : IMemoryPackable
	{
		public int SlotId;

		public int Generation;

		public void Pack(ref MemoryPacker packer)
		{
			((MemoryPacker)(ref packer)).Write<int>(SlotId);
			((MemoryPacker)(ref packer)).Write<int>(Generation);
		}

		public void Unpack(ref MemoryUnpacker unpacker)
		{
			((MemoryUnpacker)(ref unpacker)).Read<int>(ref SlotId);
			((MemoryUnpacker)(ref unpacker)).Read<int>(ref Generation);
		}
	}
	internal sealed class SharedTextureRendererDeviceMessage : IMemoryPackable
	{
		public long AdapterLuid;

		public int VendorId;

		public string Description;

		public void Pack(ref MemoryPacker packer)
		{
			((MemoryPacker)(ref packer)).Write<long>(AdapterLuid);
			((MemoryPacker)(ref packer)).Write<int>(VendorId);
			((MemoryPacker)(ref packer)).Write(Description);
		}

		public void Unpack(ref MemoryUnpacker unpacker)
		{
			((MemoryUnpacker)(ref unpacker)).Read<long>(ref AdapterLuid);
			((MemoryUnpacker)(ref unpacker)).Read<int>(ref VendorId);
			((MemoryUnpacker)(ref unpacker)).Read(ref Description);
		}
	}
}
namespace DesktopBuddySharedTextureBridge
{
	internal interface IBridgeTextureSlot : IDisplayTextureSource, IDisposable
	{
		int Width { get; }

		int Height { get; }

		int RequestCount { get; }

		bool TryBind();

		void Tick();
	}
	[HarmonyPatch(/*Could not decode attribute arguments.*/)]
	internal static class LibVlcCachePatch
	{
		private struct CacheSettings
		{
			public int NetworkCachingMs;

			public int LiveCachingMs;

			public int FileCachingMs;

			public static CacheSettings Default => new CacheSettings
			{
				NetworkCachingMs = 300,
				LiveCachingMs = 300,
				FileCachingMs = 300
			};
		}

		private static DateTime _lastLoadUtc;

		private static CacheSettings _settings = CacheSettings.Default;

		private static bool _loggedConfigPath;

		private static void Prefix(PlayerOptionsStandalone options)
		{
			try
			{
				if (options != null)
				{
					CacheSettings cacheSettings = LoadSettings();
					options.NetworkCaching = cacheSettings.NetworkCachingMs;
					options.LiveCaching = cacheSettings.LiveCachingMs;
					options.FileCaching = cacheSettings.FileCachingMs;
					SharedTextureBridgePlugin.LogInfo($"[LibVLC] Cache options: network={options.NetworkCaching}ms live={options.LiveCaching}ms file={options.FileCaching}ms");
				}
			}
			catch (Exception ex)
			{
				SharedTextureBridgePlugin.LogError("[LibVLC] Prefix failed", ex);
			}
		}

		private static CacheSettings LoadSettings()
		{
			if ((DateTime.UtcNow - _lastLoadUtc).TotalSeconds < 2.0)
			{
				return _settings;
			}
			_lastLoadUtc = DateTime.UtcNow;
			string text = FindConfigPath();
			if (text == null || !File.Exists(text))
			{
				if (!_loggedConfigPath)
				{
					_loggedConfigPath = true;
					SharedTextureBridgePlugin.LogWarning("[LibVLC] DesktopBuddy BepInEx config not found; using low-latency cache defaults");
				}
				_settings = CacheSettings.Default;
				return _settings;
			}
			if (!_loggedConfigPath)
			{
				_loggedConfigPath = true;
				SharedTextureBridgePlugin.LogInfo("[LibVLC] Reading DesktopBuddy cache config from " + text);
			}
			try
			{
				string json = File.ReadAllText(text);
				_settings = new CacheSettings
				{
					NetworkCachingMs = ReadCacheMs(json, "libVlcNetworkCachingMs", CacheSettings.Default.NetworkCachingMs),
					LiveCachingMs = ReadCacheMs(json, "libVlcLiveCachingMs", CacheSettings.Default.LiveCachingMs),
					FileCachingMs = ReadCacheMs(json, "libVlcFileCachingMs", CacheSettings.Default.FileCachingMs)
				};
			}
			catch (Exception ex)
			{
				SharedTextureBridgePlugin.LogError("[LibVLC] Failed to read DesktopBuddy cache config", ex);
				_settings = CacheSettings.Default;
			}
			return _settings;
		}

		private static string FindConfigPath()
		{
			string gameRootPath = Paths.GameRootPath;
			string text = Directory.GetParent(gameRootPath)?.FullName;
			string currentDirectory = Directory.GetCurrentDirectory();
			string baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
			string directoryName = Path.GetDirectoryName(typeof(SharedTextureBridgePlugin).Assembly.Location);
			string[] array = new string[6]
			{
				Path.Combine(directoryName ?? "", "..", "..", "..", "..", "BepInEx", "config", "com.devl0rd.DesktopBuddy.cfg"),
				Path.Combine(gameRootPath ?? "", "BepInEx", "config", "com.devl0rd.DesktopBuddy.cfg"),
				Path.Combine(text ?? "", "BepInEx", "config", "com.devl0rd.DesktopBuddy.cfg"),
				Path.Combine(currentDirectory ?? "", "BepInEx", "config", "com.devl0rd.DesktopBuddy.cfg"),
				Path.Combine(baseDirectory ?? "", "..", "..", "..", "BepInEx", "config", "com.devl0rd.DesktopBuddy.cfg"),
				Path.Combine(baseDirectory ?? "", "..", "..", "..", "..", "BepInEx", "config", "com.devl0rd.DesktopBuddy.cfg")
			};
			foreach (string path in array)
			{
				try
				{
					string fullPath = Path.GetFullPath(path);
					if (File.Exists(fullPath))
					{
						return fullPath;
					}
				}
				catch
				{
				}
			}
			return null;
		}

		private static int ReadInt(string configText, string key, int fallback)
		{
			string text = Regex.Escape(key);
			Match match = Regex.Match(configText, "\"" + text + "\"\\s*:\\s*(-?\\d+)");
			if (!match.Success)
			{
				match = Regex.Match(configText, "(?m)^\\s*" + text + "\\s*=\\s*(-?\\d+)\\s*$");
			}
			if (!match.Success || !int.TryParse(match.Groups[1].Value, out var result))
			{
				return fallback;
			}
			if (result < 0)
			{
				return 0;
			}
			if (result > 5000)
			{
				return 5000;
			}
			return result;
		}

		private static int ReadCacheMs(string json, string key, int fallback)
		{
			return ReadInt(json, key, fallback);
		}
	}
	internal sealed class LinuxCaptureTextureSlot : IBridgeTextureSlot, IDisplayTextureSource, IDisposable
	{
		private const uint DrmFormatArgb8888 = 875713089u;

		private const uint DrmFormatXrgb8888 = 875713112u;

		private const uint DrmFormatAbgr8888 = 875708993u;

		private const uint DrmFormatXbgr8888 = 875709016u;

		private readonly ManualLogSource _log;

		private readonly HashSet<Action> _requests = new HashSet<Action>();

		private readonly LinuxNativeBridgeRenderer _bridge = new LinuxNativeBridgeRenderer();

		private readonly uint _pipeWireNodeId;

		private Texture2D _texture;

		private byte[] _pixels;

		private bool _disposed;

		private bool _captureStarted;

		private bool _started;

		private int _width;

		private int _height;

		private int _pollsWithoutFrame;

		private int _copyFailures;

		private int _unsupportedFrames;

		private int _uploadedFrames;

		private bool _loggedFirstFrame;

		public Texture UnityTexture => (Texture)(object)_texture;

		public int Width => Math.Max(1, _width);

		public int Height => Math.Max(1, _height);

		public int RequestCount => _requests.Count;

		public bool IsValid
		{
			get
			{
				if (!_disposed && _started)
				{
					return (Object)(object)_texture != (Object)null;
				}
				return false;
			}
		}

		public string SourceName => "LinuxShmCapture";

		internal LinuxCaptureTextureSlot(uint pipeWireNodeId, int widthHint, int heightHint, ManualLogSource log)
		{
			_pipeWireNodeId = pipeWireNodeId;
			_width = Math.Max(1, widthHint);
			_height = Math.Max(1, heightHint);
			_log = log;
		}

		public bool TryBind()
		{
			if (_started)
			{
				return true;
			}
			if (_disposed)
			{
				return false;
			}
			EnsureCaptureStarted();
			PollAndUploadFrame();
			return _started;
		}

		public void Tick()
		{
			if (_captureStarted && !_disposed)
			{
				PollAndUploadFrame();
			}
		}

		private void EnsureCaptureStarted()
		{
			if (!_captureStarted && !_disposed)
			{
				SharedTextureBridgePlugin.LogInfo($"[LinuxCapture] SHM capture start calling native bridge node={_pipeWireNodeId}");
				int num = _bridge.StartCapture(_pipeWireNodeId);
				SharedTextureBridgePlugin.LogInfo($"[LinuxCapture] SHM capture start returned {num} node={_pipeWireNodeId}");
				if (num != 0)
				{
					SharedTextureBridgePlugin.LogWarning($"[LinuxCapture] SHM capture did not start cleanly: {num}");
				}
				_captureStarted = num == 0;
			}
		}

		private bool PollAndUploadFrame()
		{
			//IL_02c3: 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_02cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02db: Expected O, but got Unknown
			DbLinuxFrame frame;
			int num = _bridge.PollFrame(out frame);
			switch (num)
			{
			case 1:
				_pollsWithoutFrame++;
				if (_pollsWithoutFrame == 120 || _pollsWithoutFrame % 600 == 0)
				{
					SharedTextureBridgePlugin.LogInfo($"[LinuxCapture] Waiting for SHM frame ({_pollsWithoutFrame} polls)");
				}
				return false;
			case 0:
				if (frame.Status == 0)
				{
					_pollsWithoutFrame = 0;
					if (!IsSupportedFourcc(frame.Fourcc) || frame.Width == 0 || frame.Height == 0)
					{
						_unsupportedFrames++;
						if (_unsupportedFrames <= 8 || _unsupportedFrames % 120 == 0)
						{
							SharedTextureBridgePlugin.LogWarning($"[LinuxCapture] Unsupported SHM frame count={_unsupportedFrames} fd={frame.Fd} {frame.Width}x{frame.Height} fourcc=0x{frame.Fourcc:X8} stride={frame.Stride}");
						}
						_bridge.DiscardFrame(frame);
						return false;
					}
					int num2;
					int num3;
					int num5;
					checked
					{
						num2 = (int)frame.Width;
						num3 = (int)frame.Height;
						int num4 = num2 * 4 * num3;
						if (_pixels == null || _pixels.Length != num4)
						{
							_pixels = new byte[num4];
						}
						num5 = _bridge.CopyFrameBytes(frame, _pixels);
					}
					if (num5 != 0)
					{
						_copyFailures++;
						if (_copyFailures <= 8 || _copyFailures % 120 == 0)
						{
							SharedTextureBridgePlugin.LogWarning($"[LinuxCapture] SHM copy failed count={_copyFailures} status={num5} fd={frame.Fd} {frame.Width}x{frame.Height} fourcc=0x{frame.Fourcc:X8} stride={frame.Stride}");
						}
						return false;
					}
					if (frame.Fourcc == 875708993 || frame.Fourcc == 875709016)
					{
						SwapRedBlue(_pixels);
					}
					if (frame.Fourcc == 875713112 || frame.Fourcc == 875709016)
					{
						ForceOpaqueAlpha(_pixels);
					}
					bool flag = (Object)(object)_texture == (Object)null || ((Texture)_texture).width != num2 || ((Texture)_texture).height != num3;
					if (flag)
					{
						DestroyTexture();
						_texture = new Texture2D(num2, num3, (TextureFormat)14, false, false)
						{
							wrapMode = (TextureWrapMode)1,
							filterMode = (FilterMode)1
						};
						_width = num2;
						_height = num3;
					}
					_texture.LoadRawTextureData(_pixels);
					_texture.Apply(false, false);
					_uploadedFrames++;
					if (!_started)
					{
						_started = true;
					}
					if (!_loggedFirstFrame || flag)
					{
						NotifyCallbacks();
					}
					if (!_loggedFirstFrame)
					{
						_loggedFirstFrame = true;
						SharedTextureBridgePlugin.LogInfo($"[LinuxCapture] First SHM frame uploaded {_width}x{_height} fourcc=0x{frame.Fourcc:X8} stride={frame.Stride}");
					}
					else if (_uploadedFrames % 120 == 0)
					{
						SharedTextureBridgePlugin.LogInfo($"[LinuxCapture] Uploaded SHM frames={_uploadedFrames} {_width}x{_height}");
					}
					return true;
				}
				goto default;
			default:
				SharedTextureBridgePlugin.LogWarning($"[LinuxCapture] PollFrame status={num} frameStatus={frame.Status} fd={frame.Fd}");
				return false;
			}
		}

		private static bool IsSupportedFourcc(uint fourcc)
		{
			if (fourcc != 875713089 && fourcc != 875713112 && fourcc != 875708993)
			{
				return fourcc == 875709016;
			}
			return true;
		}

		private static void SwapRedBlue(byte[] pixels)
		{
			for (int i = 0; i < pixels.Length; i += 4)
			{
				byte b = pixels[i];
				pixels[i] = pixels[i + 2];
				pixels[i + 2] = b;
			}
		}

		private static void ForceOpaqueAlpha(byte[] pixels)
		{
			for (int i = 3; i < pixels.Length; i += 4)
			{
				pixels[i] = byte.MaxValue;
			}
		}

		public void RegisterRequest(Action onTextureChanged)
		{
			try
			{
				if (onTextureChanged != null)
				{
					_requests.Add(onTextureChanged);
				}
				if ((Object)(object)_texture != (Object)null)
				{
					onTextureChanged?.Invoke();
				}
			}
			catch (Exception ex)
			{
				SharedTextureBridgePlugin.LogError("[LinuxCapture] RegisterRequest failed", ex);
			}
		}

		public void UnregisterRequest(Action onTextureChanged)
		{
			try
			{
				if (onTextureChanged != null)
				{
					_requests.Remove(onTextureChanged);
				}
			}
			catch (Exception ex)
			{
				SharedTextureBridgePlugin.LogError("[LinuxCapture] UnregisterRequest failed", ex);
			}
		}

		public void Dispose()
		{
			if (!_disposed)
			{
				_disposed = true;
				DestroyTexture();
				_bridge.Dispose();
				_requests.Clear();
			}
		}

		private void DestroyTexture()
		{
			if (!((Object)(object)_texture == (Object)null))
			{
				try
				{
					Object.Destroy((Object)(object)_texture);
				}
				catch (Exception ex)
				{
					SharedTextureBridgePlugin.LogWarning("[LinuxCapture] Texture destroy failed: " + ex.Message);
				}
				_texture = null;
			}
		}

		private void NotifyCallbacks()
		{
			foreach (Action request in _requests)
			{
				try
				{
					request?.Invoke();
				}
				catch (Exception ex)
				{
					ManualLogSource log = _log;
					if (log != null)
					{
						log.LogWarning((object)("[LinuxCapture] Callback error: " + ex.Message));
					}
				}
			}
		}
	}
	internal sealed class LinuxNativeBridgeRenderer : IDisposable
	{
		[UnmanagedFunctionPointer(CallingConvention.StdCall)]
		private delegate int DesktopBuddyLinuxBridgeCallDelegate(ref DbLinuxBridgeCall call);

		private const uint OpPoll = 2u;

		private const uint OpStop = 3u;

		private const uint OpStartNode = 6u;

		private const uint OpCopyFrame = 7u;

		private const uint OpCloseFrame = 8u;

		private static readonly object LoadLock = new object();

		private static IntPtr SharedModule;

		private static DesktopBuddyLinuxBridgeCallDelegate SharedCall;

		private DesktopBuddyLinuxBridgeCallDelegate _call;

		private ulong _captureId;

		internal bool TryLoad()
		{
			if (_call != null)
			{
				return true;
			}
			lock (LoadLock)
			{
				if (SharedCall == null)
				{
					string text = ResolveBridgePath();
					SharedModule = LoadLibraryA(text);
					if (SharedModule == IntPtr.Zero)
					{
						SharedTextureBridgePlugin.LogWarning($"[LinuxBridge] LoadLibrary failed path={text} err=0x{Marshal.GetLastWin32Error():X8}");
						return false;
					}
					IntPtr procAddress = GetProcAddress(SharedModule, "DesktopBuddyLinuxBridgeCall");
					if (procAddress == IntPtr.Zero)
					{
						SharedTextureBridgePlugin.LogWarning($"[LinuxBridge] GetProcAddress failed err=0x{Marshal.GetLastWin32Error():X8}");
						FreeSharedModule();
						return false;
					}
					SharedCall = (DesktopBuddyLinuxBridgeCallDelegate)Marshal.GetDelegateForFunctionPointer(procAddress, typeof(DesktopBuddyLinuxBridgeCallDelegate));
					SharedTextureBridgePlugin.LogInfo("[LinuxBridge] Loaded " + text);
				}
				_call = SharedCall;
			}
			return true;
		}

		internal int StartCapture(uint nodeId)
		{
			if (!TryLoad())
			{
				return -1;
			}
			DbLinuxBridgeCall call = new DbLinuxBridgeCall
			{
				Op = 6u,
				Arg0 = nodeId
			};
			int num = _call(ref call);
			if (num == 0)
			{
				_captureId = call.Arg0;
			}
			return num;
		}

		internal int PollFrame(out DbLinuxFrame frame)
		{
			frame = default(DbLinuxFrame);
			if (_call == null || _captureId == 0L)
			{
				return -1;
			}
			DbLinuxBridgeCall call = new DbLinuxBridgeCall
			{
				Op = 2u,
				Arg0 = _captureId
			};
			int result = _call(ref call);
			frame = call.Frame;
			return result;
		}

		internal int CopyFrameBytes(DbLinuxFrame frame, byte[] destination)
		{
			if (_call == null || destination == null || destination.Length == 0)
			{
				return -1;
			}
			GCHandle gCHandle = GCHandle.Alloc(destination, GCHandleType.Pinned);
			try
			{
				DbLinuxBridgeCall call = new DbLinuxBridgeCall
				{
					Op = 7u,
					Arg0 = checked((ulong)destination.LongLength),
					Frame = frame,
					Buffer = (ulong)gCHandle.AddrOfPinnedObject().ToInt64()
				};
				return _call(ref call);
			}
			finally
			{
				gCHandle.Free();
			}
		}

		internal void DiscardFrame(DbLinuxFrame frame)
		{
			if (_call != null && frame.Fd >= 0)
			{
				DbLinuxBridgeCall call = new DbLinuxBridgeCall
				{
					Op = 8u,
					Frame = frame
				};
				_call(ref call);
			}
		}

		internal void Stop()
		{
			if (_call != null && _captureId != 0L)
			{
				DbLinuxBridgeCall call = new DbLinuxBridgeCall
				{
					Op = 3u,
					Arg0 = _captureId
				};
				_call(ref call);
				_captureId = 0uL;
			}
		}

		private static string ResolveBridgePath()
		{
			return Path.Combine(Path.GetDirectoryName(typeof(SharedTextureBridgePlugin).Assembly.Location) ?? string.Empty, "DesktopBuddyLinuxBridge.so");
		}

		public void Dispose()
		{
			Stop();
			_call = null;
		}

		private static void FreeSharedModule()
		{
			if (!(SharedModule == IntPtr.Zero))
			{
				FreeLibrary(SharedModule);
				SharedModule = IntPtr.Zero;
				SharedCall = null;
			}
		}

		[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
		private static extern IntPtr LoadLibraryA(string fileName);

		[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
		private static extern IntPtr GetProcAddress(IntPtr module, string procName);

		[DllImport("kernel32.dll", SetLastError = true)]
		private static extern bool FreeLibrary(IntPtr module);
	}
	internal struct DbLinuxFrame
	{
		public int Status;

		public int Fd;

		public uint Width;

		public uint Height;

		public uint Fourcc;

		public uint Offset;

		public int Stride;
	}
	internal struct DbLinuxBridgeCall
	{
		public uint Op;

		public int Status;

		public ulong Arg0;

		public DbLinuxFrame Frame;

		public ulong Buffer;
	}
	internal sealed class SharedTextureBridge : IDisposable
	{
		private readonly ManualLogSource _log;

		private readonly ConcurrentQueue<Action> _mainThreadActions = new ConcurrentQueue<Action>();

		private Messenger _messenger;

		private float _connectRetryTimer;

		private float _connectLogTimer;

		private const float ConnectRetryInterval = 1f;

		private const float ConnectLogInterval = 5f;

		private readonly Dictionary<int, IBridgeTextureSlot> _activeSlots = new Dictionary<int, IBridgeTextureSlot>();

		private readonly Dictionary<int, int> _activeGenerations = new Dictionary<int, int>();

		private static readonly ConcurrentDictionary<int, IDisplayTextureSource> _bridgeIndexToSlot = new ConcurrentDictionary<int, IDisplayTextureSource>();

		private readonly List<(int slot, int generation, IBridgeTextureSlot textureSlot)> _pendingBinds = new List<(int, int, IBridgeTextureSlot)>();

		private bool _rendererDevicePublished;

		internal int ActiveSlotCount => _activeSlots.Count;

		internal int PendingBindCount => _pendingBinds.Count;

		internal int TotalTextureRequestCount
		{
			get
			{
				int num = 0;
				foreach (IBridgeTextureSlot value in _activeSlots.Values)
				{
					num += value.RequestCount;
				}
				return num;
			}
		}

		internal SharedTextureBridge(ManualLogSource log)
		{
			_log = log;
			SharedTextureBridgePlugin.LogInfo("[SharedTextureBridge] Constructed");
		}

		internal static IDisplayTextureSource GetSlotForBridgeIndex(int bridgeIndex)
		{
			_bridgeIndexToSlot.TryGetValue(bridgeIndex, out var value);
			return value;
		}

		internal void Update()
		{
			SharedTextureSlot.ProcessDeferredNativeReleases();
			TryEnsureMessenger();
			TryPublishRendererDevice();
			Action result;
			while (_mainThreadActions.TryDequeue(out result))
			{
				try
				{
					result();
				}
				catch (Exception ex)
				{
					SharedTextureBridgePlugin.LogError("IPC action failed", ex);
				}
			}
			foreach (IBridgeTextureSlot value2 in _activeSlots.Values)
			{
				try
				{
					value2.Tick();
				}
				catch (Exception ex2)
				{
					SharedTextureBridgePlugin.LogError("Texture slot tick failed", ex2);
				}
			}
			for (int num = _pendingBinds.Count - 1; num >= 0; num--)
			{
				var (num2, num3, bridgeTextureSlot) = _pendingBinds[num];
				if (!_activeGenerations.TryGetValue(num2, out var value) || value != num3)
				{
					_pendingBinds.RemoveAt(num);
					continue;
				}
				bool flag;
				try
				{
					flag = bridgeTextureSlot.TryBind();
				}
				catch (Exception ex3)
				{
					SharedTextureBridgePlugin.LogError($"Pending TryBind threw slot={num2}", ex3);
					continue;
				}
				if (flag)
				{
					_pendingBinds.RemoveAt(num);
					WriteRunning(num2, num3, bridgeTextureSlot);
					SharedTextureBridgePlugin.LogInfo($"[SharedTextureBridge] Slot {num2} gen={num3} bound: {bridgeTextureSlot.Width}x{bridgeTextureSlot.Height}");
				}
			}
		}

		private void TryPublishRendererDevice()
		{
			if (_rendererDevicePublished || _messenger == null)
			{
				return;
			}
			try
			{
				if (UnityD3D11Device.Initialize(_log) && UnityD3D11Device.HasAdapterInfo)
				{
					_messenger.SendObject<SharedTextureRendererDeviceMessage>("RendererDevice", new SharedTextureRendererDeviceMessage
					{
						AdapterLuid = UnityD3D11Device.AdapterLuid,
						VendorId = UnityD3D11Device.AdapterVendorId,
						Description = UnityD3D11Device.AdapterDescription
					});
					_rendererDevicePublished = true;
					SharedTextureBridgePlugin.LogInfo($"[SharedTextureBridge] Published renderer adapter '{UnityD3D11Device.AdapterDescription}' VendorId=0x{UnityD3D11Device.AdapterVendorId:X4} LUID=0x{UnityD3D11Device.AdapterLuid:X16}");
				}
			}
			catch (Exception ex)
			{
				SharedTextureBridgePlugin.LogWarning("[SharedTextureBridge] Failed to publish renderer adapter: " + ex.Message);
			}
		}

		private void TryEnsureMessenger()
		{
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Expected O, but got Unknown
			if (_messenger != null)
			{
				return;
			}
			_connectRetryTimer += Time.unscaledDeltaTime;
			_connectLogTimer += Time.unscaledDeltaTime;
			if (_connectLogTimer >= 5f)
			{
				_connectLogTimer = 0f;
				SharedTextureBridgePlugin.LogInfo("[SharedTextureBridge] Waiting for InterprocessLib queue " + SharedTextureBridgeProtocol.QueueName);
			}
			if (_connectRetryTimer < 1f)
			{
				return;
			}
			_connectRetryTimer = 0f;
			try
			{
				SharedTextureBridgePlugin.LogInfo("[SharedTextureBridge] Creating Messenger");
				Messenger.OnWarning += OnWarning;
				Messenger.OnFailure += OnFailure;
				_messenger = new Messenger(SharedTextureBridgeProtocol.OwnerId, false, SharedTextureBridgeProtocol.QueueName, (IMemoryPackerEntityPool)(object)SimpleMemoryPackerPool.Instance, 1048576L);
				RegisterMessages();
				SharedTextureBridgePlugin.LogInfo("Opened InterprocessLib queue: " + SharedTextureBridgeProtocol.QueueName);
			}
			catch (Exception ex)
			{
				Messenger.OnWarning -= OnWarning;
				Messenger.OnFailure -= OnFailure;
				Messenger messenger = _messenger;
				if (messenger != null)
				{
					messenger.Dispose();
				}
				_messenger = null;
				SharedTextureBridgePlugin.LogWarning("InterprocessLib queue not ready: " + ex.GetType().Name + ": " + ex.Message);
			}
		}

		private void RegisterMessages()
		{
			_messenger.ReceiveObject<SharedTextureStartMessage>("Start", (Action<SharedTextureStartMessage>)delegate(SharedTextureStartMessage msg)
			{
				try
				{
					if (msg != null)
					{
						SharedTextureBridgePlugin.LogInfo($"[SharedTextureBridge] Received Start slot={msg.SlotId} gen={msg.Generation} name={msg.SharedTextureName} shared=0x{msg.SharedTextureHandle:X} {msg.SharedTextureWidth}x{msg.SharedTextureHeight}");
						_mainThreadActions.Enqueue(delegate
						{
							StartSharedTexture(msg.SlotId, msg.Generation, msg.SharedTextureHandle, msg.SharedTextureName, msg.SharedTextureWidth, msg.SharedTextureHeight);
						});
					}
				}
				catch (Exception ex)
				{
					SharedTextureBridgePlugin.LogError("[SharedTextureBridge] Start callback failed", ex);
				}
			});
			_messenger.ReceiveObject<SharedTextureStopMessage>("Stop", (Action<SharedTextureStopMessage>)delegate(SharedTextureStopMessage msg)
			{
				try
				{
					if (msg != null)
					{
						SharedTextureBridgePlugin.LogInfo($"[SharedTextureBridge] Received Stop slot={msg.SlotId} gen={msg.Generation}");
						_mainThreadActions.Enqueue(delegate
						{
							StopSharedTexture(msg.SlotId, msg.Generation, sendStopped: true);
						});
					}
				}
				catch (Exception ex)
				{
					SharedTextureBridgePlugin.LogError("[SharedTextureBridge] Stop callback failed", ex);
				}
			});
			_messenger.ReceiveObject<SharedTextureRunningMessage>("Running", (Action<SharedTextureRunningMessage>)delegate
			{
			});
			_messenger.ReceiveObject<SharedTextureStoppedMessage>("Stopped", (Action<SharedTextureStoppedMessage>)delegate
			{
			});
			_messenger.ReceiveObject<SharedTextureRendererDeviceMessage>("RendererDevice", (Action<SharedTextureRendererDeviceMessage>)delegate
			{
			});
		}

		private void StartSharedTexture(int slot, int generation, long sharedTextureHandleRaw, string sharedTextureName, int sharedTextureWidth, int sharedTextureHeight)
		{
			if (sharedTextureHandleRaw == -1 && TryParseLinuxCaptureName(sharedTextureName, out var pipeWireNodeId))
			{
				StartLinuxCapture(slot, generation, pipeWireNodeId, sharedTextureWidth, sharedTextureHeight);
				return;
			}
			if (_activeSlots.ContainsKey(slot))
			{
				StopSharedTexture(slot, _activeGenerations.TryGetValue(slot, out var value) ? value : 0, sendStopped: false);
			}
			IntPtr intPtr = new IntPtr(sharedTextureHandleRaw);
			SharedTextureBridgePlugin.LogInfo($"Starting shared texture slot={slot} gen={generation} name={sharedTextureName} shared=0x{sharedTextureHandleRaw:X} {sharedTextureWidth}x{sharedTextureHeight}");
			if (intPtr == IntPtr.Zero || sharedTextureWidth <= 0 || sharedTextureHeight <= 0)
			{
				SharedTextureBridgePlugin.LogWarning($"Shared texture start ignored slot={slot} gen={generation}: missing handle or size");
				return;
			}
			SharedTextureSlot sharedTextureSlot;
			try
			{
				sharedTextureSlot = new SharedTextureSlot(intPtr, sharedTextureWidth, sharedTextureHeight, _log);
				_activeSlots[slot] = sharedTextureSlot;
				_activeGenerations[slot] = generation;
				_bridgeIndexToSlot[10000 + slot] = (IDisplayTextureSource)(object)sharedTextureSlot;
				SharedTextureBridgePlugin.LogInfo($"Registered bridge index={10000 + slot} slot={slot} gen={generation}");
			}
			catch (Exception ex)
			{
				SharedTextureBridgePlugin.LogError($"Shared texture slot construction failed slot={slot} gen={generation}", ex);
				return;
			}
			bool flag;
			try
			{
				flag = sharedTextureSlot.TryBind();
			}
			catch (Exception ex2)
			{
				SharedTextureBridgePlugin.LogError($"Initial TryBind threw slot={slot} gen={generation}", ex2);
				return;
			}
			if (flag)
			{
				WriteRunning(slot, generation, sharedTextureSlot);
				return;
			}
			SharedTextureBridgePlugin.LogWarning($"Initial TryBind failed slot={slot} gen={generation}; adding pending bind");
			_pendingBinds.Add((slot, generation, sharedTextureSlot));
		}

		private void StopSharedTexture(int slot, int generation, bool sendStopped)
		{
			if (!_activeSlots.ContainsKey(slot))
			{
				if (sendStopped)
				{
					WriteStopped(slot, generation);
				}
				return;
			}
			if (_activeGenerations.TryGetValue(slot, out var value) && value != generation)
			{
				SharedTextureBridgePlugin.LogWarning($"Ignoring stale shared texture stop slot={slot} gen={generation} active={value}");
				return;
			}
			SharedTextureBridgePlugin.LogInfo($"Stopping shared texture slot={slot} gen={generation}");
			_bridgeIndexToSlot.TryRemove(10000 + slot, out var _);
			SharedTextureBridgePlugin.LogInfo($"[SharedTextureBridge] Removed bridge index for slot={slot}");
			try
			{
				_activeSlots[slot].Dispose();
				SharedTextureBridgePlugin.LogInfo($"[SharedTextureBridge] Slot dispose completed slot={slot}");
			}
			catch (Exception ex)
			{
				SharedTextureBridgePlugin.LogError($"[SharedTextureBridge] Slot dispose failed slot={slot}", ex);
			}
			_activeSlots.Remove(slot);
			_activeGenerations.Remove(slot);
			_pendingBinds.RemoveAll(((int slot, int generation, IBridgeTextureSlot textureSlot) p) => p.slot == slot);
			if (sendStopped)
			{
				WriteStopped(slot, generation);
			}
			SharedTextureBridgePlugin.LogInfo($"[SharedTextureBridge] Stop complete slot={slot}");
		}

		private static bool TryParseLinuxCaptureName(string name, out uint pipeWireNodeId)
		{
			pipeWireNodeId = 0u;
			if (string.IsNullOrEmpty(name) || !name.StartsWith("DesktopBuddyLinuxCapture:", StringComparison.Ordinal))
			{
				return false;
			}
			if (uint.TryParse(name.Substring("DesktopBuddyLinuxCapture:".Length), out pipeWireNodeId))
			{
				return pipeWireNodeId != 0;
			}
			return false;
		}

		private void StartLinuxCapture(int slot, int generation, uint pipeWireNodeId, int widthHint, int heightHint)
		{
			StopSharedTexture(slot, _activeGenerations.TryGetValue(slot, out var value) ? value : 0, sendStopped: false);
			try
			{
				LinuxCaptureTextureSlot linuxCaptureTextureSlot = new LinuxCaptureTextureSlot(pipeWireNodeId, widthHint, heightHint, _log);
				_activeSlots[slot] = linuxCaptureTextureSlot;
				_activeGenerations[slot] = generation;
				_bridgeIndexToSlot[10000 + slot] = (IDisplayTextureSource)(object)linuxCaptureTextureSlot;
				if (linuxCaptureTextureSlot.TryBind())
				{
					WriteRunning(slot, generation, linuxCaptureTextureSlot);
					SharedTextureBridgePlugin.LogInfo($"[SharedTextureBridge] Linux capture slot={slot} gen={generation} node={pipeWireNodeId} running {linuxCaptureTextureSlot.Width}x{linuxCaptureTextureSlot.Height}");
				}
				else
				{
					_pendingBinds.Add((slot, generation, linuxCaptureTextureSlot));
					SharedTextureBridgePlugin.LogWarning($"[SharedTextureBridge] Linux capture slot={slot} node={pipeWireNodeId} pending bind");
				}
			}
			catch (Exception ex)
			{
				SharedTextureBridgePlugin.LogError($"[SharedTextureBridge] Linux capture start failed slot={slot} gen={generation}", ex);
			}
		}

		private void WriteRunning(int slot, int generation, IBridgeTextureSlot textureSlot)
		{
			try
			{
				Messenger messenger = _messenger;
				if (messenger != null)
				{
					messenger.SendObject<SharedTextureRunningMessage>("Running", new SharedTextureRunningMessage
					{
						SlotId = slot,
						Generation = generation,
						Width = textureSlot.Width,
						Height = textureSlot.Height
					});
				}
			}
			catch (Exception ex)
			{
				SharedTextureBridgePlugin.LogWarning($"Failed to send running ack for slot {slot}: {ex.Message}");
			}
			SharedTextureBridgePlugin.LogInfo($"Shared texture slot={slot} gen={generation} running: {textureSlot.Width}x{textureSlot.Height}");
		}

		private void WriteStopped(int slot, int generation)
		{
			try
			{
				Messenger messenger = _messenger;
				if (messenger != null)
				{
					messenger.SendObject<SharedTextureStoppedMessage>("Stopped", new SharedTextureStoppedMessage
					{
						SlotId = slot,
						Generation = generation
					});
				}
			}
			catch (Exception ex)
			{
				SharedTextureBridgePlugin.LogWarning($"Failed to send stopped ack for slot {slot} gen={generation}: {ex.Message}");
			}
			SharedTextureBridgePlugin.LogInfo($"Shared texture slot={slot} gen={generation} stopped");
		}

		private void OnWarning(string message)
		{
			SharedTextureBridgePlugin.LogWarning("[InterprocessLib] " + message);
		}

		private void OnFailure(Exception ex)
		{
			SharedTextureBridgePlugin.LogError("[InterprocessLib]", ex);
		}

		public void Dispose()
		{
			SharedTextureBridgePlugin.LogInfo("[SharedTextureBridge] Disposing");
			foreach (KeyValuePair<int, IBridgeTextureSlot> activeSlot in _activeSlots)
			{
				try
				{
					SharedTextureBridgePlugin.LogInfo($"[SharedTextureBridge] Disposing slot={activeSlot.Key}");
					activeSlot.Value.Dispose();
				}
				catch (Exception ex)
				{
					SharedTextureBridgePlugin.LogError($"[SharedTextureBridge] Slot dispose failed during bridge dispose slot={activeSlot.Key}", ex);
				}
			}
			_activeSlots.Clear();
			_activeGenerations.Clear();
			_bridgeIndexToSlot.Clear();
			_pendingBinds.Clear();
			try
			{
				SharedTextureBridgePlugin.LogInfo("[SharedTextureBridge] Messenger.Dispose START");
				Messenger messenger = _messenger;
				if (messenger != null)
				{
					messenger.Dispose();
				}
				SharedTextureBridgePlugin.LogInfo("[SharedTextureBridge] Messenger.Dispose DONE");
			}
			catch (Exception ex2)
			{
				SharedTextureBridgePlugin.LogError("[SharedTextureBridge] Messenger.Dispose failed", ex2);
			}
			_messenger = null;
			Messenger.OnWarning -= OnWarning;
			Messenger.OnFailure -= OnFailure;
			SharedTextureBridgePlugin.LogInfo("[SharedTextureBridge] Disposed");
		}
	}
	[BepInPlugin("net.desktopbuddy.sharedtexturebridge", "DesktopBuddySharedTextureBridge", "1.1.0")]
	public class SharedTextureBridgePlugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		private SharedTextureBridge _bridge;

		private void Awake()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			LogInfo("DesktopBuddySharedTextureBridge starting...");
			try
			{
				new Harmony("net.desktopbuddy.sharedtexturebridge").PatchAll();
				LogInfo("Harmony patches applied");
			}
			catch (Exception ex)
			{
				LogError("Harmony PatchAll failed", ex);
				throw;
			}
			try
			{
				_bridge = new SharedTextureBridge(Log);
				LogInfo("SharedTextureBridge created");
			}
			catch (Exception ex2)
			{
				LogError("SharedTextureBridge creation failed", ex2);
				throw;
			}
			LogInfo("DesktopBuddySharedTextureBridge ready");
		}

		private void Update()
		{
			try
			{
				_bridge?.Update();
			}
			catch (Exception ex)
			{
				LogError("Update failed", ex);
			}
		}

		private void OnDestroy()
		{
			LogInfo("DesktopBuddySharedTextureBridge OnDestroy START");
			try
			{
				_bridge?.Dispose();
				LogInfo("SharedTextureBridge disposed");
			}
			catch (Exception ex)
			{
				LogError("SharedTextureBridge dispose failed", ex);
			}
			try
			{
				UnityD3D11Device.Dispose();
				LogInfo("UnityD3D11Device disposed");
			}
			catch (Exception ex2)
			{
				LogError("UnityD3D11Device dispose failed", ex2);
			}
			LogInfo("DesktopBuddySharedTextureBridge OnDestroy DONE");
		}

		internal static void LogInfo(string message)
		{
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogInfo((object)message);
			}
		}

		internal static void LogWarning(string message)
		{
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogWarning((object)message);
			}
		}

		internal static void LogError(string message, Exception ex)
		{
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogError((object)$"{message}: {ex}");
			}
		}
	}
	[HarmonyPatch(typeof(DisplayDriver), "TryGetDisplayTexture")]
	internal static class SharedTextureIndexPatch
	{
		private static bool Prefix(int index, ref IDisplayTextureSource __result)
		{
			try
			{
				if (index < 10000)
				{
					return true;
				}
				IDisplayTextureSource slotForBridgeIndex = SharedTextureBridge.GetSlotForBridgeIndex(index);
				__result = slotForBridgeIndex;
				return false;
			}
			catch (Exception ex)
			{
				SharedTextureBridgePlugin.LogError($"[SharedTextureIndexPatch] Prefix failed index={index}", ex);
				__result = null;
				return false;
			}
		}
	}
	internal sealed class SharedTextureSlot : IBridgeTextureSlot, IDisplayTextureSource, IDisposable
	{
		private struct DeferredNativeRelease
		{
			public IntPtr ShaderResourceView;

			public IntPtr OpenedTexture;

			public long SharedHandle;

			public int FramesRemaining;
		}

		private struct D3D11_TEX2D_SRV
		{
			public uint MostDetailedMip;

			public uint MipLevels;
		}

		private struct D3D11_SHADER_RESOURCE_VIEW_DESC
		{
			public uint Format;

			public uint ViewDimension;

			public D3D11_TEX2D_SRV Texture2D;
		}

		private const int ID3D11Device_OpenSharedResource = 28;

		private const int ID3D11Device_CreateShaderResourceView = 7;

		private const uint DXGI_FORMAT_B8G8R8A8_UNORM_SRGB = 91u;

		private const uint D3D11_SRV_DIMENSION_TEXTURE2D = 4u;

		private static readonly Guid Texture2DGuid = new Guid("6f15aaf2-d208-4e89-9ab4-489535d34f9c");

		private const int DeferredReleaseFrames = 3;

		private static readonly ConcurrentQueue<DeferredNativeRelease> DeferredReleases = new ConcurrentQueue<DeferredNativeRelease>();

		private readonly ManualLogSource _log;

		private readonly IntPtr _sharedHandle;

		private readonly HashSet<Action> _requests = new HashSet<Action>();

		private IntPtr _openedTexture;

		private IntPtr _shaderResourceView;

		private Texture2D _unityTexture;

		private bool _started;

		private bool _disposed;

		public Texture UnityTexture => (Texture)(object)_unityTexture;

		public int Width { get; }

		public int Height { get; }

		public int RequestCount => _requests.Count;

		public bool IsValid
		{
			get
			{
				if (!_disposed && _started)
				{
					return (Object)(object)_unityTexture != (Object)null;
				}
				return false;
			}
		}

		public string SourceName => "SharedTexture";

		internal SharedTextureSlot(IntPtr sharedHandle, int width, int height, ManualLogSource log)
		{
			_sharedHandle = sharedHandle;
			Width = width;
			Height = height;
			_log = log;
			SharedTextureBridgePlugin.LogInfo($"[SharedTexture] Constructed handle=0x{_sharedHandle.ToInt64():X} {Width}x{Height}");
		}

		public bool TryBind()
		{
			if (_started)
			{
				return true;
			}
			if (_disposed)
			{
				return false;
			}
			if (_sharedHandle == IntPtr.Zero || Width <= 0 || Height <= 0)
			{
				return false;
			}
			if (!UnityD3D11Device.IsReady && !UnityD3D11Device.Initialize(_log))
			{
				SharedTextureBridgePlugin.LogWarning("[SharedTexture] Renderer D3D device is not ready");
				return false;
			}
			try
			{
				OpenSharedTexture();
				CreateShaderResourceView();
				_unityTexture = Texture2D.CreateExternalTexture(Width, Height, (TextureFormat)14, false, false, _shaderResourceView);
				Texture2D unityTexture = _unityTexture;
				IntPtr sharedHandle = _sharedHandle;
				((Object)unityTexture).name = $"DesktopBuddy SharedTexture 0x{sharedHandle.ToInt64():X}";
				((Texture)_unityTexture).wrapMode = (TextureWrapMode)1;
				_started = true;
				object[] array = new object[5];
				sharedHandle = _sharedHandle;
				array[0] = sharedHandle.ToInt64();
				array[1] = _openedTexture.ToInt64();
				array[2] = _shaderResourceView.ToInt64();
				array[3] = Width;
				array[4] = Height;
				SharedTextureBridgePlugin.LogInfo(string.Format("[SharedTexture] Bound handle=0x{0:X} texture=0x{1:X} srv=0x{2:X} {3}x{4}", array));
				NotifyCallbacks();
				return true;
			}
			catch (Exception ex)
			{
				SharedTextureBridgePlugin.LogError("[SharedTexture] TryBind failed", ex);
				Dispose();
				return false;
			}
		}

		public void Tick()
		{
		}

		public void RegisterRequest(Action onTextureChanged)
		{
			try
			{
				if (onTextureChanged != null)
				{
					_requests.Add(onTextureChanged);
				}
				if ((Object)(object)_unityTexture != (Object)null)
				{
					onTextureChanged?.Invoke();
				}
			}
			catch (Exception ex)
			{
				SharedTextureBridgePlugin.LogError("[SharedTexture] RegisterRequest callback failed", ex);
			}
		}

		public void UnregisterRequest(Action onTextureChanged)
		{
			try
			{
				if (onTextureChanged != null)
				{
					_requests.Remove(onTextureChanged);
				}
			}
			catch (Exception ex)
			{
				SharedTextureBridgePlugin.LogError("[SharedTexture] UnregisterRequest failed", ex);
			}
		}

		public void Dispose()
		{
			object[] array = new object[7];
			IntPtr sharedHandle = _sharedHandle;
			array[0] = sharedHandle.ToInt64();
			array[1] = _disposed;
			array[2] = _started;
			array[3] = (Object)(object)_unityTexture != (Object)null;
			array[4] = _shaderResourceView.ToInt64();
			array[5] = _openedTexture.ToInt64();
			array[6] = _requests.Count;
			SharedTextureBridgePlugin.LogInfo(string.Format("[SharedTexture] Dispose ENTER handle=0x{0:X} disposed={1} started={2} unityTexture={3} srv=0x{4:X} texture=0x{5:X} requests={6}", array));
			if (!_disposed)
			{
				_disposed = true;
				if ((Object)(object)_unityTexture != (Object)null)
				{
					sharedHandle = _sharedHandle;
					SharedTextureBridgePlugin.LogInfo($"[SharedTexture] Unity texture Destroy START handle=0x{sharedHandle.ToInt64():X}");
					Object.Destroy((Object)(object)_unityTexture);
					_unityTexture = null;
					sharedHandle = _sharedHandle;
					SharedTextureBridgePlugin.LogInfo($"[SharedTexture] Unity texture Destroy queued handle=0x{sharedHandle.ToInt64():X}");
				}
				if (_shaderResourceView != IntPtr.Zero || _openedTexture != IntPtr.Zero)
				{
					ConcurrentQueue<DeferredNativeRelease> deferredReleases = DeferredReleases;
					DeferredNativeRelease item = new DeferredNativeRelease
					{
						ShaderResourceView = _shaderResourceView,
						OpenedTexture = _openedTexture
					};
					sharedHandle = _sharedHandle;
					item.SharedHandle = sharedHandle.ToInt64();
					item.FramesRemaining = 3;
					deferredReleases.Enqueue(item);
					object[] array2 = new object[4];
					sharedHandle = _sharedHandle;
					array2[0] = sharedHandle.ToInt64();
					array2[1] = 3;
					array2[2] = _shaderResourceView.ToInt64();
					array2[3] = _openedTexture.ToInt64();
					SharedTextureBridgePlugin.LogInfo(string.Format("[SharedTexture] Deferred native release queued handle=0x{0:X} frames={1} srv=0x{2:X} texture=0x{3:X}", array2));
					_shaderResourceView = IntPtr.Zero;
					_openedTexture = IntPtr.Zero;
				}
				_requests.Clear();
				sharedHandle = _sharedHandle;
				SharedTextureBridgePlugin.LogInfo($"[SharedTexture] Disposed handle=0x{sharedHandle.ToInt64():X}");
			}
		}

		internal static void ProcessDeferredNativeReleases()
		{
			int count = DeferredReleases.Count;
			for (int i = 0; i < count; i++)
			{
				if (!DeferredReleases.TryDequeue(out var result))
				{
					break;
				}
				result.FramesRemaining--;
				if (result.FramesRemaining > 0)
				{
					DeferredReleases.Enqueue(result);
					continue;
				}
				SharedTextureBridgePlugin.LogInfo($"[SharedTexture] Deferred native release START handle=0x{result.SharedHandle:X} srv=0x{result.ShaderResourceView.ToInt64():X} texture=0x{result.OpenedTexture.ToInt64():X}");
				try
				{
					if (result.ShaderResourceView != IntPtr.Zero)
					{
						Marshal.Release(result.ShaderResourceView);
					}
					if (result.OpenedTexture != IntPtr.Zero)
					{
						Marshal.Release(result.OpenedTexture);
					}
				}
				catch (Exception ex)
				{
					SharedTextureBridgePlugin.LogError("[SharedTexture] Deferred native release failed", ex);
				}
				SharedTextureBridgePlugin.LogInfo($"[SharedTexture] Deferred native release DONE handle=0x{result.SharedHandle:X}");
			}
		}

		private unsafe void OpenSharedTexture()
		{
			delegate* unmanaged[Stdcall]<IntPtr, IntPtr, Guid*, IntPtr*, int> delegate* = (delegate* unmanaged[Stdcall]<IntPtr, IntPtr, Guid*, IntPtr*, int>)(void*)(*(IntPtr*)((nint)(*(IntPtr*)(void*)UnityD3D11Device.D3dDevice) + (nint)28 * (nint)sizeof(IntPtr)));
			Guid texture2DGuid = Texture2DGuid;
			IntPtr intPtr = default(IntPtr);
			int num = delegate*(UnityD3D11Device.D3dDevice, _sharedHandle, &texture2DGuid, &intPtr);
			if (num < 0 || intPtr == IntPtr.Zero)
			{
				object arg = num;
				IntPtr sharedHandle = _sharedHandle;
				throw new InvalidOperationException($"OpenSharedResource failed hr=0x{arg:X8} handle=0x{sharedHandle.ToInt64():X}");
			}
			_openedTexture = intPtr;
		}

		private unsafe void CreateShaderResourceView()
		{
			D3D11_SHADER_RESOURCE_VIEW_DESC d3D11_SHADER_RESOURCE_VIEW_DESC = new D3D11_SHADER_RESOURCE_VIEW_DESC
			{
				Format = 91u,
				ViewDimension = 4u,
				Texture2D = new D3D11_TEX2D_SRV
				{
					MostDetailedMip = 0u,
					MipLevels = 1u
				}
			};
			IntPtr intPtr = default(IntPtr);
			int num = ((delegate* unmanaged[Stdcall]<IntPtr, IntPtr, D3D11_SHADER_RESOURCE_VIEW_DESC*, IntPtr*, int>)(void*)(*(IntPtr*)((nint)(*(IntPtr*)(void*)UnityD3D11Device.D3dDevice) + (nint)7 * (nint)sizeof(IntPtr))))(UnityD3D11Device.D3dDevice, _openedTexture, &d3D11_SHADER_RESOURCE_VIEW_DESC, &intPtr);
			if (num < 0 || intPtr == IntPtr.Zero)
			{
				throw new InvalidOperationException($"CreateShaderResourceView failed hr=0x{num:X8} texture=0x{_openedTexture.ToInt64():X}");
			}
			_shaderResourceView = intPtr;
		}

		private void NotifyCallbacks()
		{
			foreach (Action request in _requests)
			{
				try
				{
					request?.Invoke();
				}
				catch (Exception ex)
				{
					ManualLogSource log = _log;
					if (log != null)
					{
						log.LogWarning((object)("[SharedTexture] Callback error: " + ex.Message));
					}
				}
			}
		}
	}
	internal static class UnityD3D11Device
	{
		[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
		private struct DXGI_ADAPTER_DESC
		{
			public unsafe fixed char Description[128];

			public uint VendorId;

			public uint DeviceId;

			public uint SubSysId;

			public uint Revision;

			public UIntPtr DedicatedVideoMemory;

			public UIntPtr DedicatedSystemMemory;

			public UIntPtr SharedSystemMemory;

			public long AdapterLuid;
		}

		private const int ID3D11Resource_GetDevice = 3;

		private const int IDXGIDevice_GetAdapter = 7;

		private const int IDXGIAdapter_GetDesc = 8;

		private static readonly object Lock = new object();

		private static IntPtr _d3dDevice;

		private static bool _initialized;

		private static long _adapterLuid;

		private static int _adapterVendorId;

		private static string _adapterDescription;

		internal static IntPtr D3dDevice => _d3dDevice;

		internal static bool IsReady
		{
			get
			{
				if (_initialized)
				{
					return _d3dDevice != IntPtr.Zero;
				}
				return false;
			}
		}

		internal static long AdapterLuid => _adapterLuid;

		internal static int AdapterVendorId => _adapterVendorId;

		internal static string AdapterDescription => _adapterDescription;

		internal static bool HasAdapterInfo => _adapterLuid != 0;

		internal unsafe static bool Initialize(ManualLogSource log)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			Info(log, "[UnityD3D11] Initialize entered");
			if (IsReady)
			{
				return true;
			}
			lock (Lock)
			{
				Info(log, "[UnityD3D11] Initialize lock entered");
				if (IsReady)
				{
					return true;
				}
				try
				{
					Texture2D val = null;
					Info(log, "[UnityD3D11] Creating Unity probe texture");
					try
					{
						val = new Texture2D(1, 1, (TextureFormat)14, false, true);
						Info(log, "[UnityD3D11] Applying Unity probe texture");
						val.Apply(false, true);
						Info(log, "[UnityD3D11] Getting native texture pointer");
						IntPtr nativeTexturePtr = ((Texture)val).GetNativeTexturePtr();
						if (nativeTexturePtr == IntPtr.Zero)
						{
							Error(log, "[UnityD3D11] Unity probe texture native pointer is null");
							return false;
						}
						Info(log, $"[UnityD3D11] Probe native texture=0x{nativeTexturePtr.ToInt64():X}");
						Info(log, "[UnityD3D11] Reading D3D resource vtable");
						delegate* unmanaged[Stdcall]<IntPtr, IntPtr*, void> delegate* = (delegate* unmanaged[Stdcall]<IntPtr, IntPtr*, void>)(void*)(*(IntPtr*)((nint)(*(IntPtr*)(void*)nativeTexturePtr) + (nint)3 * (nint)sizeof(IntPtr)));
						Info(log, "[UnityD3D11] Calling ID3D11Resource.GetDevice");
						IntPtr d3dDevice = default(IntPtr);
						delegate*(nativeTexturePtr, &d3dDevice);
						_d3dDevice = d3dDevice;
					}
					finally
					{
						if ((Object)(object)val != (Object)null)
						{
							Object.Destroy((Object)(object)val);
						}
					}
					if (_d3dDevice == IntPtr.Zero)
					{
						Error(log, "[UnityD3D11] ID3D11Resource.GetDevice returned null");
						return false;
					}
					Info(log, $"[UnityD3D11] D3D device=0x{_d3dDevice.ToInt64():X}");
					TryReadAdapterInfo(log);
					_initialized = true;
					Info(log, $"[UnityD3D11] Unity D3D11 device ready device=0x{_d3dDevice.ToInt64():X} adapter='{_adapterDescription}' vendor=0x{_adapterVendorId:X4} LUID=0x{_adapterLuid:X16}");
					return true;
				}
				catch (Exception arg)
				{
					if (log != null)
					{
						log.LogError((object)$"[UnityD3D11] Renderer device init failed: {arg}");
					}
					return false;
				}
			}
		}

		private unsafe static void TryReadAdapterInfo(ManualLogSource log)
		{
			Guid iid = new Guid("54ec77fa-1377-44e6-8c32-88fd5f44c84c");
			IntPtr ppv = IntPtr.Zero;
			IntPtr zero = IntPtr.Zero;
			try
			{
				int num = Marshal.QueryInterface(_d3dDevice, in iid, out ppv);
				if (num < 0 || ppv == IntPtr.Zero)
				{
					Info(log, $"[UnityD3D11] IDXGIDevice QueryInterface failed hr=0x{num:X8}");
					return;
				}
				num = ((delegate* unmanaged[Stdcall]<IntPtr, IntPtr*, int>)(void*)(*(IntPtr*)((nint)(*(IntPtr*)(void*)ppv) + (nint)7 * (nint)sizeof(IntPtr))))(ppv, &zero);
				if (num < 0 || zero == IntPtr.Zero)
				{
					Info(log, $"[UnityD3D11] IDXGIDevice.GetAdapter failed hr=0x{num:X8}");
					return;
				}
				DXGI_ADAPTER_DESC dXGI_ADAPTER_DESC = default(DXGI_ADAPTER_DESC);
				num = ((delegate* unmanaged[Stdcall]<IntPtr, DXGI_ADAPTER_DESC*, int>)(void*)(*(IntPtr*)((nint)(*(IntPtr*)(void*)zero) + (nint)8 * (nint)sizeof(IntPtr))))(zero, &dXGI_ADAPTER_DESC);
				if (num < 0)
				{
					Info(log, $"[UnityD3D11] IDXGIAdapter.GetDesc failed hr=0x{num:X8}");
					return;
				}
				_adapterLuid = dXGI_ADAPTER_DESC.AdapterLuid;
				_adapterVendorId = (int)dXGI_ADAPTER_DESC.VendorId;
				_adapterDescription = new string(dXGI_ADAPTER_DESC.Description).TrimEnd(new char[1]);
				Info(log, $"[UnityD3D11] Adapter '{_adapterDescription}' VendorId=0x{dXGI_ADAPTER_DESC.VendorId:X4} LUID=0x{dXGI_ADAPTER_DESC.AdapterLuid:X16}");
			}
			catch (Exception ex)
			{
				if (log != null)
				{
					log.LogWarning((object)("[UnityD3D11] Failed to read adapter info: " + ex.Message));
				}
			}
			finally
			{
				if (zero != IntPtr.Zero)
				{
					Marshal.Release(zero);
				}
				if (ppv != IntPtr.Zero)
				{
					Marshal.Release(ppv);
				}
			}
		}

		internal static void Dispose()
		{
			SharedTextureBridgePlugin.LogInfo($"[UnityD3D11] Dispose ENTER initialized={_initialized} device=0x{_d3dDevice.ToInt64():X}");
			lock (Lock)
			{
				SharedTextureBridgePlugin.LogInfo("[UnityD3D11] Dispose lock entered");
				if (_d3dDevice != IntPtr.Zero)
				{
					try
					{
						Marshal.Release(_d3dDevice);
					}
					catch (Exception ex)
					{
						SharedTextureBridgePlugin.LogError("[UnityD3D11] Device release failed", ex);
					}
					_d3dDevice = IntPtr.Zero;
				}
				_initialized = false;
				_adapterLuid = 0L;
				_adapterVendorId = 0;
				_adapterDescription = null;
			}
			SharedTextureBridgePlugin.LogInfo("[UnityD3D11] Dispose EXIT");
		}

		private static void Info(ManualLogSource log, string message)
		{
			if (log != null)
			{
				log.LogInfo((object)message);
			}
		}

		private static void Error(ManualLogSource log, string message)
		{
			if (log != null)
			{
				log.LogError((object)message);
			}
		}
	}
	internal static class BridgeVersionInfo
	{
		internal const string Version = "1.1.0";
	}
}

plugins/DesktopBuddy/DesktopBuddy.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.NetworkInformation;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Security.Principal;
using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Awwdio;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using BepInEx.NET.Common;
using BepInExResoniteShim;
using BepisResoniteWrapper;
using BepuPhysics.Collidables;
using DesktopBuddy.Shared;
using Elements.Assets;
using Elements.Core;
using FFmpeg.AutoGen;
using FrooxEngine;
using FrooxEngine.CommonAvatar;
using FrooxEngine.UIX;
using HarmonyLib;
using InterprocessLib;
using Microsoft.CodeAnalysis;
using Microsoft.Win32;
using Microsoft.Win32.SafeHandles;
using Renderite.Shared;
using SkyFrost.Base;
using WinRT;
using Windows.Foundation;
using Windows.Foundation.Metadata;
using Windows.Graphics;
using Windows.Graphics.Capture;
using Windows.Graphics.DirectX;
using Windows.Graphics.DirectX.Direct3D11;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(/*Could not decode attribute arguments.*/)]
[assembly: TargetFramework(".NETCoreApp,Version=v10.0", FrameworkDisplayName = ".NET 10.0")]
[assembly: AssemblyCompany("DesktopBuddy")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+e5251e37dd743ac1b5ffad5e3f95aa6063a3aabc")]
[assembly: AssemblyProduct("DesktopBuddy")]
[assembly: AssemblyTitle("DesktopBuddy")]
[assembly: TargetPlatform("Windows10.0.26100.0")]
[assembly: SupportedOSPlatform("Windows10.0.19041.0")]
[assembly: SecurityPermission((SecurityAction)8, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace BepInEx
{
	[AttributeUsage(/*Could not decode attribute arguments.*/)]
	[Conditional("CodeGeneration")]
	[Embedded]
	internal sealed class BepInAutoPluginAttribute : global::System.Attribute
	{
		public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null, string? authors = null, string? link = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(/*Could not decode attribute arguments.*/)]
	[Conditional("CodeGeneration")]
	[Embedded]
	internal sealed class PatcherAutoPluginAttribute : global::System.Attribute
	{
		public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace Microsoft.CodeAnalysis
{
	[Embedded]
	internal sealed class EmbeddedAttribute : global::System.Attribute
	{
	}
}
namespace DesktopBuddy
{
	internal static class DesktopBuddyFirstRunSetup
	{
		internal enum SetupAction
		{
			SoftCamRegistration,
			VBCableInstall,
			VBCableLoopback,
			UrlAcl
		}

		internal sealed class SetupState
		{
			internal static readonly SetupState Ok = new SetupState();

			[field: CompilerGenerated]
			internal global::System.Collections.Generic.IReadOnlyList<SetupItem> Items
			{
				[CompilerGenerated]
				get;
				[CompilerGenerated]
				init;
			} = global::System.Array.Empty<SetupItem>();

			[field: CompilerGenerated]
			internal global::System.Collections.Generic.IReadOnlyList<SetupAction> RequiredActions
			{
				[CompilerGenerated]
				get;
				[CompilerGenerated]
				init;
			} = global::System.Array.Empty<SetupAction>();

			internal bool HasIssues => Enumerable.Any<SetupItem>((global::System.Collections.Generic.IEnumerable<SetupItem>)Items, (Func<SetupItem, bool>)((SetupItem item) => !item.IsOk));

			internal bool HasRequiredActions => ((global::System.Collections.Generic.IReadOnlyCollection<SetupAction>)RequiredActions).Count > 0;
		}

		internal sealed class SetupItem
		{
			[field: CompilerGenerated]
			internal string Name
			{
				[CompilerGenerated]
				get;
				[CompilerGenerated]
				init;
			}

			[field: CompilerGenerated]
			internal string Status
			{
				[CompilerGenerated]
				get;
				[CompilerGenerated]
				init;
			}

			[field: CompilerGenerated]
			internal string Detail
			{
				[CompilerGenerated]
				get;
				[CompilerGenerated]
				init;
			}

			[field: CompilerGenerated]
			internal bool IsOk
			{
				[CompilerGenerated]
				get;
				[CompilerGenerated]
				init;
			}

			[field: CompilerGenerated]
			internal bool RequiresAdminAction
			{
				[CompilerGenerated]
				get;
				[CompilerGenerated]
				init;
			}

			[field: CompilerGenerated]
			internal SetupAction? Action
			{
				[CompilerGenerated]
				get;
				[CompilerGenerated]
				init;
			}
		}

		[CompilerGenerated]
		private sealed class <GetSoftCamInprocKeys>d__31 : global::System.Collections.Generic.IEnumerable<ValueTuple<RegistryKey, string>>, global::System.Collections.IEnumerable, global::System.Collections.Generic.IEnumerator<ValueTuple<RegistryKey, string>>, global::System.Collections.IEnumerator, global::System.IDisposable
		{
			private int <>1__state;

			private ValueTuple<RegistryKey, string> <>2__current;

			private int <>l__initialThreadId;

			ValueTuple<RegistryKey, string> global::System.Collections.Generic.IEnumerator<ValueTuple<RegistryKey, string>>.Current
			{
				[DebuggerHidden]
				get
				{
					//IL_0001: Unknown result type (might be due to invalid IL or missing references)
					return <>2__current;
				}
			}

			object global::System.Collections.IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					//IL_0001: Unknown result type (might be due to invalid IL or missing references)
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <GetSoftCamInprocKeys>d__31(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void global::System.IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0039: 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_005e: 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_0083: 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_00a8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
				//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = new ValueTuple<RegistryKey, string>(Registry.ClassesRoot, "CLSID\\{AEF3B972-5FA5-4647-9571-358EB472BC9E}\\InprocServer32");
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<>2__current = new ValueTuple<RegistryKey, string>(Registry.CurrentUser, "Software\\Classes\\CLSID\\{AEF3B972-5FA5-4647-9571-358EB472BC9E}\\InprocServer32");
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -1;
					<>2__current = new ValueTuple<RegistryKey, string>(Registry.CurrentUser, "Software\\Classes\\WOW6432Node\\CLSID\\{AEF3B972-5FA5-4647-9571-358EB472BC9E}\\InprocServer32");
					<>1__state = 3;
					return true;
				case 3:
					<>1__state = -1;
					<>2__current = new ValueTuple<RegistryKey, string>(Registry.LocalMachine, "Software\\Classes\\CLSID\\{AEF3B972-5FA5-4647-9571-358EB472BC9E}\\InprocServer32");
					<>1__state = 4;
					return true;
				case 4:
					<>1__state = -1;
					<>2__current = new ValueTuple<RegistryKey, string>(Registry.LocalMachine, "Software\\Classes\\WOW6432Node\\CLSID\\{AEF3B972-5FA5-4647-9571-358EB472BC9E}\\InprocServer32");
					<>1__state = 5;
					return true;
				case 5:
					<>1__state = -1;
					return false;
				}
			}

			bool global::System.Collections.IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void global::System.Collections.IEnumerator.Reset()
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			global::System.Collections.Generic.IEnumerator<ValueTuple<RegistryKey, string>> global::System.Collections.Generic.IEnumerable<ValueTuple<RegistryKey, string>>.GetEnumerator()
			{
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					return this;
				}
				return new <GetSoftCamInprocKeys>d__31(0);
			}

			[DebuggerHidden]
			global::System.Collections.IEnumerator global::System.Collections.IEnumerable.GetEnumerator()
			{
				return (global::System.Collections.IEnumerator)((global::System.Collections.Generic.IEnumerable<ValueTuple<RegistryKey, string>>)this).GetEnumerator();
			}
		}

		[CompilerGenerated]
		private sealed class <GetSoftCamRegisteredDlls>d__30 : global::System.Collections.Generic.IEnumerable<string>, global::System.Collections.IEnumerable, global::System.Collections.Generic.IEnumerator<string>, global::System.Collections.IEnumerator, global::System.IDisposable
		{
			private int <>1__state;

			private string <>2__current;

			private int <>l__initialThreadId;

			private global::System.Collections.Generic.IEnumerator<ValueTuple<RegistryKey, string>> <>7__wrap1;

			private RegistryKey <opened>5__3;

			string global::System.Collections.Generic.IEnumerator<string>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object global::System.Collections.IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <GetSoftCamRegisteredDlls>d__30(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void global::System.IDisposable.Dispose()
			{
				int num = <>1__state;
				if ((uint)(num - -4) <= 1u || num == 1)
				{
					try
					{
						if (num == -4 || num == 1)
						{
							try
							{
							}
							finally
							{
								<>m__Finally2();
							}
						}
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<>7__wrap1 = null;
				<opened>5__3 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//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_0046: Unknown result type (might be due to invalid IL or missing references)
				//IL_004c: Unknown result type (might be due to invalid IL or missing references)
				try
				{
					int num = <>1__state;
					if (num != 0)
					{
						if (num != 1)
						{
							return false;
						}
						<>1__state = -4;
						goto IL_00aa;
					}
					<>1__state = -1;
					<>7__wrap1 = GetSoftCamInprocKeys().GetEnumerator();
					<>1__state = -3;
					goto IL_00b7;
					IL_00aa:
					<>m__Finally2();
					<opened>5__3 = null;
					goto IL_00b7;
					IL_00b7:
					if (((global::System.Collections.IEnumerator)<>7__wrap1).MoveNext())
					{
						ValueTuple<RegistryKey, string> current = <>7__wrap1.Current;
						<opened>5__3 = current.Item1.OpenSubKey(current.Item2);
						<>1__state = -4;
						RegistryKey obj = <opened>5__3;
						string text = ((obj != null) ? obj.GetValue("") : null) as string;
						if (!string.IsNullOrWhiteSpace(text))
						{
							<>2__current = text.Trim('"');
							<>1__state = 1;
							return true;
						}
						goto IL_00aa;
					}
					<>m__Finally1();
					<>7__wrap1 = null;
					return false;
				}
				catch
				{
					//try-fault
					((global::System.IDisposable)this).Dispose();
					throw;
				}
			}

			bool global::System.Collections.IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				if (<>7__wrap1 != null)
				{
					((global::System.IDisposable)<>7__wrap1).Dispose();
				}
			}

			private void <>m__Finally2()
			{
				<>1__state = -3;
				if (<opened>5__3 != null)
				{
					((global::System.IDisposable)<opened>5__3).Dispose();
				}
			}

			[DebuggerHidden]
			void global::System.Collections.IEnumerator.Reset()
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			global::System.Collections.Generic.IEnumerator<string> global::System.Collections.Generic.IEnumerable<string>.GetEnumerator()
			{
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					return this;
				}
				return new <GetSoftCamRegisteredDlls>d__30(0);
			}

			[DebuggerHidden]
			global::System.Collections.IEnumerator global::System.Collections.IEnumerable.GetEnumerator()
			{
				return (global::System.Collections.IEnumerator)((global::System.Collections.Generic.IEnumerable<string>)this).GetEnumerator();
			}
		}

		[CompilerGenerated]
		private sealed class <GetSoftCamRegistryTrees>d__32 : global::System.Collections.Generic.IEnumerable<ValueTuple<RegistryKey, string>>, global::System.Collections.IEnumerable, global::System.Collections.Generic.IEnumerator<ValueTuple<RegistryKey, string>>, global::System.Collections.IEnumerator, global::System.IDisposable
		{
			private int <>1__state;

			private ValueTuple<RegistryKey, string> <>2__current;

			private int <>l__initialThreadId;

			ValueTuple<RegistryKey, string> global::System.Collections.Generic.IEnumerator<ValueTuple<RegistryKey, string>>.Current
			{
				[DebuggerHidden]
				get
				{
					//IL_0001: Unknown result type (might be due to invalid IL or missing references)
					return <>2__current;
				}
			}

			object global::System.Collections.IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					//IL_0001: Unknown result type (might be due to invalid IL or missing references)
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <GetSoftCamRegistryTrees>d__32(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void global::System.IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//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)
				//IL_007a: Unknown result type (might be due to invalid IL or missing references)
				//IL_007f: Unknown result type (might be due to invalid IL or missing references)
				//IL_009f: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
				//IL_010e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0113: Unknown result type (might be due to invalid IL or missing references)
				//IL_0133: 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_0158: Unknown result type (might be due to invalid IL or missing references)
				//IL_015d: Unknown result type (might be due to invalid IL or missing references)
				//IL_017d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0182: Unknown result type (might be due to invalid IL or missing references)
				//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
				//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
				//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
				//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = new ValueTuple<RegistryKey, string>(Registry.CurrentUser, "Software\\Classes\\CLSID\\{AEF3B972-5FA5-4647-9571-358EB472BC9E}");
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<>2__current = new ValueTuple<RegistryKey, string>(Registry.CurrentUser, "Software\\Classes\\WOW6432Node\\CLSID\\{AEF3B972-5FA5-4647-9571-358EB472BC9E}");
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -1;
					<>2__current = new ValueTuple<RegistryKey, string>(Registry.LocalMachine, "Software\\Classes\\CLSID\\{AEF3B972-5FA5-4647-9571-358EB472BC9E}");
					<>1__state = 3;
					return true;
				case 3:
					<>1__state = -1;
					<>2__current = new ValueTuple<RegistryKey, string>(Registry.LocalMachine, "Software\\Classes\\WOW6432Node\\CLSID\\{AEF3B972-5FA5-4647-9571-358EB472BC9E}");
					<>1__state = 4;
					return true;
				case 4:
					<>1__state = -1;
					<>2__current = new ValueTuple<RegistryKey, string>(Registry.CurrentUser, "Software\\Classes\\CLSID\\{860BB310-5D01-11d0-BD3B-00A0C911CE86}\\Instance\\DesktopBuddy - Camera");
					<>1__state = 5;
					return true;
				case 5:
					<>1__state = -1;
					<>2__current = new ValueTuple<RegistryKey, string>(Registry.CurrentUser, "Software\\Classes\\CLSID\\{860BB310-5D01-11d0-BD3B-00A0C911CE86}\\Instance\\DirectShow Softcam");
					<>1__state = 6;
					return true;
				case 6:
					<>1__state = -1;
					<>2__current = new ValueTuple<RegistryKey, string>(Registry.CurrentUser, "Software\\Classes\\WOW6432Node\\CLSID\\{860BB310-5D01-11d0-BD3B-00A0C911CE86}\\Instance\\DesktopBuddy - Camera");
					<>1__state = 7;
					return true;
				case 7:
					<>1__state = -1;
					<>2__current = new ValueTuple<RegistryKey, string>(Registry.CurrentUser, "Software\\Classes\\WOW6432Node\\CLSID\\{860BB310-5D01-11d0-BD3B-00A0C911CE86}\\Instance\\DirectShow Softcam");
					<>1__state = 8;
					return true;
				case 8:
					<>1__state = -1;
					<>2__current = new ValueTuple<RegistryKey, string>(Registry.LocalMachine, "Software\\Classes\\CLSID\\{860BB310-5D01-11d0-BD3B-00A0C911CE86}\\Instance\\DesktopBuddy - Camera");
					<>1__state = 9;
					return true;
				case 9:
					<>1__state = -1;
					<>2__current = new ValueTuple<RegistryKey, string>(Registry.LocalMachine, "Software\\Classes\\CLSID\\{860BB310-5D01-11d0-BD3B-00A0C911CE86}\\Instance\\DirectShow Softcam");
					<>1__state = 10;
					return true;
				case 10:
					<>1__state = -1;
					<>2__current = new ValueTuple<RegistryKey, string>(Registry.LocalMachine, "Software\\Classes\\WOW6432Node\\CLSID\\{860BB310-5D01-11d0-BD3B-00A0C911CE86}\\Instance\\DesktopBuddy - Camera");
					<>1__state = 11;
					return true;
				case 11:
					<>1__state = -1;
					<>2__current = new ValueTuple<RegistryKey, string>(Registry.LocalMachine, "Software\\Classes\\WOW6432Node\\CLSID\\{860BB310-5D01-11d0-BD3B-00A0C911CE86}\\Instance\\DirectShow Softcam");
					<>1__state = 12;
					return true;
				case 12:
					<>1__state = -1;
					return false;
				}
			}

			bool global::System.Collections.IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void global::System.Collections.IEnumerator.Reset()
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			global::System.Collections.Generic.IEnumerator<ValueTuple<RegistryKey, string>> global::System.Collections.Generic.IEnumerable<ValueTuple<RegistryKey, string>>.GetEnumerator()
			{
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					return this;
				}
				return new <GetSoftCamRegistryTrees>d__32(0);
			}

			[DebuggerHidden]
			global::System.Collections.IEnumerator global::System.Collections.IEnumerable.GetEnumerator()
			{
				return (global::System.Collections.IEnumerator)((global::System.Collections.Generic.IEnumerable<ValueTuple<RegistryKey, string>>)this).GetEnumerator();
			}
		}

		[CompilerGenerated]
		private sealed class <GetSoftCamUnregisterCandidates>d__29 : global::System.Collections.Generic.IEnumerable<string>, global::System.Collections.IEnumerable, global::System.Collections.Generic.IEnumerator<string>, global::System.Collections.IEnumerator, global::System.IDisposable
		{
			private int <>1__state;

			private string <>2__current;

			private int <>l__initialThreadId;

			private string runtimeDir;

			public string <>3__runtimeDir;

			private global::System.Collections.Generic.IEnumerator<string> <>7__wrap1;

			string global::System.Collections.Generic.IEnumerator<string>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object global::System.Collections.IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <GetSoftCamUnregisterCandidates>d__29(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void global::System.IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || num == 3)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<>7__wrap1 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				try
				{
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						<>2__current = Path.Combine(runtimeDir, "softcam64.dll");
						<>1__state = 1;
						return true;
					case 1:
						<>1__state = -1;
						<>2__current = Path.Combine(runtimeDir, "softcam.dll");
						<>1__state = 2;
						return true;
					case 2:
						<>1__state = -1;
						<>7__wrap1 = GetSoftCamRegisteredDlls().GetEnumerator();
						<>1__state = -3;
						break;
					case 3:
						<>1__state = -3;
						break;
					}
					if (((global::System.Collections.IEnumerator)<>7__wrap1).MoveNext())
					{
						string current = <>7__wrap1.Current;
						<>2__current = current;
						<>1__state = 3;
						return true;
					}
					<>m__Finally1();
					<>7__wrap1 = null;
					return false;
				}
				catch
				{
					//try-fault
					((global::System.IDisposable)this).Dispose();
					throw;
				}
			}

			bool global::System.Collections.IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				if (<>7__wrap1 != null)
				{
					((global::System.IDisposable)<>7__wrap1).Dispose();
				}
			}

			[DebuggerHidden]
			void global::System.Collections.IEnumerator.Reset()
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			global::System.Collections.Generic.IEnumerator<string> global::System.Collections.Generic.IEnumerable<string>.GetEnumerator()
			{
				<GetSoftCamUnregisterCandidates>d__29 <GetSoftCamUnregisterCandidates>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<GetSoftCamUnregisterCandidates>d__ = this;
				}
				else
				{
					<GetSoftCamUnregisterCandidates>d__ = new <GetSoftCamUnregisterCandidates>d__29(0);
				}
				<GetSoftCamUnregisterCandidates>d__.runtimeDir = <>3__runtimeDir;
				return <GetSoftCamUnregisterCandidates>d__;
			}

			[DebuggerHidden]
			global::System.Collections.IEnumerator global::System.Collections.IEnumerable.GetEnumerator()
			{
				return (global::System.Collections.IEnumerator)((global::System.Collections.Generic.IEnumerable<string>)this).GetEnumerator();
			}
		}

		private const string SoftCamClsid = "{AEF3B972-5FA5-4647-9571-358EB472BC9E}";

		private const string VideoInputCategoryClsid = "{860BB310-5D01-11d0-BD3B-00A0C911CE86}";

		private const string SetupHashFile = "DesktopBuddySetupHashes.txt";

		private const string PackagedSetupHashFile = "DesktopBuddySetupPayloads.md5";

		internal static SetupState Check()
		{
			try
			{
				string runtimeDir = GetRuntimeDir();
				Log.Msg("[Setup] Checking DesktopBuddy local setup");
				Log.Msg("[Setup] Runtime path: " + runtimeDir);
				global::System.Collections.Generic.IReadOnlyList<SetupItem> setupItems = GetSetupItems(runtimeDir);
				return new SetupState
				{
					Items = setupItems,
					RequiredActions = (global::System.Collections.Generic.IReadOnlyList<SetupAction>)GetRequiredActions(setupItems)
				};
			}
			catch (global::System.Exception ex)
			{
				Log.Msg($"[Setup] First-run setup check failed: {ex}");
				SetupState setupState = new SetupState();
				setupState.Items = new SetupItem[1]
				{
					new SetupItem
					{
						Name = "Setup check",
						Status = "Error",
						Detail = ex.Message,
						IsOk = false
					}
				};
				return setupState;
			}
		}

		internal static Process StartElevatedSetup(global::System.Collections.Generic.IReadOnlyCollection<SetupAction> actions = null)
		{
			string runtimeDir = GetRuntimeDir();
			List<SetupAction> val = ((actions == null || actions.Count == 0) ? GetRequiredAdminActions(runtimeDir) : NormalizeSetupActions((global::System.Collections.Generic.IEnumerable<SetupAction>)actions));
			if (val.Count == 0)
			{
				Log.Msg("[Setup] No elevated setup actions are required");
				return null;
			}
			Log.Msg("[Setup] User requested admin setup: " + string.Join(", ", Enumerable.Select<SetupAction, string>((global::System.Collections.Generic.IEnumerable<SetupAction>)val, (Func<SetupAction, string>)GetActionLabel)));
			if (IsAdministrator())
			{
				RunAdminSetup((global::System.Collections.Generic.IReadOnlyCollection<SetupAction>)val, runtimeDir);
				return null;
			}
			return StartElevatedSetupHelper((global::System.Collections.Generic.IReadOnlyCollection<SetupAction>)val, runtimeDir);
		}

		private static List<SetupAction> GetRequiredAdminActions(string runtimeDir)
		{
			return GetRequiredActions(GetSetupItems(runtimeDir));
		}

		private static List<SetupAction> GetRequiredActions(global::System.Collections.Generic.IReadOnlyList<SetupItem> items)
		{
			return NormalizeSetupActions(Enumerable.Select<SetupItem, SetupAction>(Enumerable.Where<SetupItem>((global::System.Collections.Generic.IEnumerable<SetupItem>)items, (Func<SetupItem, bool>)((SetupItem item) => item.RequiresAdminAction && item.Action.HasValue)), (Func<SetupItem, SetupAction>)((SetupItem item) => item.Action.Value)));
		}

		private static List<SetupAction> NormalizeSetupActions(global::System.Collections.Generic.IEnumerable<SetupAction> actions)
		{
			List<SetupAction> val = Enumerable.ToList<SetupAction>(Enumerable.Distinct<SetupAction>(actions));
			if (val.Contains(SetupAction.VBCableInstall) && !val.Contains(SetupAction.VBCableLoopback))
			{
				int num = val.IndexOf(SetupAction.VBCableInstall);
				val.Insert(num + 1, SetupAction.VBCableLoopback);
			}
			return val;
		}

		private static string GetActionLabel(SetupAction action)
		{
			return action switch
			{
				SetupAction.SoftCamRegistration => "SoftCam registration", 
				SetupAction.VBCableInstall => "VB-Cable install", 
				SetupAction.VBCableLoopback => "VB-Cable loopback disable", 
				SetupAction.UrlAcl => "streaming access", 
				_ => ((object)action/*cast due to .constrained prefix*/).ToString(), 
			};
		}

		private static global::System.Collections.Generic.IReadOnlyList<SetupItem> GetSetupItems(string runtimeDir)
		{
			List<SetupItem> obj = new List<SetupItem>();
			obj.Add(GetSoftCamSetupItem(runtimeDir));
			obj.Add(GetVBCableInstallSetupItem(runtimeDir));
			obj.Add(GetVBCableLoopbackSetupItem());
			obj.Add(GetUrlAclSetupItem());
			return (global::System.Collections.Generic.IReadOnlyList<SetupItem>)obj;
		}

		private static SetupItem GetSoftCamSetupItem(string runtimeDir)
		{
			string text = ((File.Exists(Path.Combine(runtimeDir, "softcam64.dll")) || !File.Exists(Path.Combine(runtimeDir, "softcam.dll"))) ? "softcam64.dll" : "softcam.dll");
			string text2 = Path.Combine(runtimeDir, text);
			string text3 = ReadPackagedSetupHash(runtimeDir, text);
			string text4 = Enumerable.FirstOrDefault<string>(GetSoftCamRegisteredDlls());
			string text5 = ReadSetupHash(runtimeDir, text);
			global::System.Collections.Generic.IReadOnlyList<string> runningRestartSensitiveProcesses = GetRunningRestartSensitiveProcesses();
			bool flag = !File.Exists(text2);
			bool flag2 = string.IsNullOrWhiteSpace(text4);
			bool flag3 = !flag2 && !PathsEqual(text4, text2);
			bool flag4 = !flag && !string.IsNullOrWhiteSpace(text3) && !string.Equals(text5, text3, (StringComparison)5);
			bool flag5 = flag || flag2 || flag3 || flag4;
			return new SetupItem
			{
				Name = "SoftCam",
				Status = (flag5 ? "Not installed" : "Installed"),
				Detail = (flag5 ? GetSoftCamSetupDetail(runningRestartSensitiveProcesses) : "Virtual camera support."),
				IsOk = !flag5,
				RequiresAdminAction = (flag5 && !flag),
				Action = SetupAction.SoftCamRegistration
			};
		}

		private static string GetSoftCamSetupDetail(global::System.Collections.Generic.IReadOnlyList<string> runningApps)
		{
			if (runningApps == null || ((global::System.Collections.Generic.IReadOnlyCollection<string>)runningApps).Count == 0)
			{
				return "Virtual camera support.";
			}
			string[] array = Enumerable.ToArray<string>(Enumerable.Take<string>((global::System.Collections.Generic.IEnumerable<string>)runningApps, 3));
			string text = ((((global::System.Collections.Generic.IReadOnlyCollection<string>)runningApps).Count > array.Length) ? $" +{((global::System.Collections.Generic.IReadOnlyCollection<string>)runningApps).Count - array.Length}" : "");
			return "Restart: " + string.Join(", ", array) + text;
		}

		private static SetupItem GetVBCableInstallSetupItem(string runtimeDir)
		{
			string text = Path.Combine(runtimeDir, "VBCABLE_Setup_x64.exe");
			string text2 = ReadPackagedSetupHash(runtimeDir, "VBCABLE_Setup_x64.exe");
			string text3 = ReadSetupHash(runtimeDir, "VBCABLE_Setup_x64.exe");
			bool num = IsVBCableInstalled();
			bool flag = !File.Exists(text);
			bool flag2 = num && !string.IsNullOrWhiteSpace(text2) && !string.Equals(text3, text2, (StringComparison)5);
			bool flag3 = !num || flag2;
			string status = (flag3 ? "Not installed" : "Installed");
			string detail = "Virtual microphone audio route.";
			return new SetupItem
			{
				Name = "VB-Cable",
				Status = status,
				Detail = detail,
				IsOk = !flag3,
				RequiresAdminAction = (flag3 && !flag),
				Action = SetupAction.VBCableInstall
			};
		}

		private static SetupItem GetVBCableLoopbackSetupItem()
		{
			bool flag = IsVBCableInstalled();
			bool flag2 = IsVBCableLoopbackDisabled();
			return new SetupItem
			{
				Name = "VB-Cable loopback",
				Status = ((!flag || flag2) ? "Installed" : "Not installed"),
				Detail = "Prevents microphone echo.",
				IsOk = (!flag || flag2),
				RequiresAdminAction = (flag && !flag2),
				Action = SetupAction.VBCableLoopback
			};
		}

		private static SetupItem GetUrlAclSetupItem()
		{
			bool flag = IsUrlAclConfigured();
			return new SetupItem
			{
				Name = "Streaming access",
				Status = (flag ? "Installed" : "Not installed"),
				Detail = "Allows local stream hosting.",
				IsOk = flag,
				RequiresAdminAction = !flag,
				Action = SetupAction.UrlAcl
			};
		}

		private static void RunAdminSetup(global::System.Collections.Generic.IReadOnlyCollection<SetupAction> actions, string runtimeDir)
		{
			Log.Msg("[Setup] Running admin setup inside DesktopBuddy");
			global::System.Collections.Generic.IEnumerator<SetupAction> enumerator = ((global::System.Collections.Generic.IEnumerable<SetupAction>)actions).GetEnumerator();
			try
			{
				while (((global::System.Collections.IEnumerator)enumerator).MoveNext())
				{
					switch (enumerator.Current)
					{
					case SetupAction.SoftCamRegistration:
						RegisterSoftCam(runtimeDir);
						break;
					case SetupAction.VBCableInstall:
						InstallVBCable(runtimeDir);
						break;
					case SetupAction.VBCableLoopback:
						ConfigureVBCableLoopback();
						break;
					case SetupAction.UrlAcl:
						ConfigureUrlAcl();
						break;
					}
				}
			}
			finally
			{
				((global::System.IDisposable)enumerator)?.Dispose();
			}
			WriteSetupHashes(runtimeDir);
			Log.Msg("[Setup] Admin setup complete");
		}

		private static Process StartElevatedSetupHelper(global::System.Collections.Generic.IReadOnlyCollection<SetupAction> actions, string runtimeDir)
		{
			//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_004e: 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_005c: 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_0070: Expected O, but got Unknown
			string logPath = Path.Combine(runtimeDir, "DesktopBuddySetup.log");
			string text = BuildElevatedSetupScript(actions, runtimeDir, logPath);
			string text2 = Path.Combine(runtimeDir, "DesktopBuddyElevatedSetup.ps1");
			File.WriteAllText(text2, text, Encoding.UTF8);
			string arguments = "-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File \"" + text2 + "\"";
			ProcessStartInfo val = new ProcessStartInfo
			{
				FileName = "powershell.exe",
				Arguments = arguments,
				UseShellExecute = true,
				Verb = "runas",
				WindowStyle = (ProcessWindowStyle)1
			};
			try
			{
				Log.Msg("[Setup] Requesting administrator permission for user-approved setup");
				Process val2 = Process.Start(val);
				if (val2 == null)
				{
					Log.Msg("[Setup] Elevated setup helper did not start");
					return null;
				}
				return val2;
			}
			catch (object obj) when (((Func<bool>)delegate
			{
				// Could not convert BlockContainer to single expression
				object obj2 = ((obj is Win32Exception) ? obj : null);
				return obj2 != null && ((Win32Exception)obj2).NativeErrorCode == 1223;
			}).Invoke())
			{
				Log.Msg("[Setup] Administrator setup was cancelled by the user");
			}
			catch (global::System.Exception ex)
			{
				Log.Msg("[Setup] Failed to start elevated setup helper: " + ex.Message);
			}
			return null;
		}

		private static string BuildElevatedSetupScript(global::System.Collections.Generic.IReadOnlyCollection<SetupAction> actions, string runtimeDir, string logPath)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			StringBuilder val = new StringBuilder();
			val.AppendLine("$ErrorActionPreference = 'Continue'");
			StringBuilder val2 = val;
			StringBuilder obj = val2;
			AppendInterpolatedStringHandler val3 = default(AppendInterpolatedStringHandler);
			((AppendInterpolatedStringHandler)(ref val3))..ctor(11, 1, val2);
			((AppendInterpolatedStringHandler)(ref val3)).AppendLiteral("$runtime = ");
			((AppendInterpolatedStringHandler)(ref val3)).AppendFormatted(PsSingleQuote(runtimeDir));
			obj.AppendLine(ref val3);
			val2 = val;
			StringBuilder obj2 = val2;
			((AppendInterpolatedStringHandler)(ref val3))..ctor(7, 1, val2);
			((AppendInterpolatedStringHandler)(ref val3)).AppendLiteral("$log = ");
			((AppendInterpolatedStringHandler)(ref val3)).AppendFormatted(PsSingleQuote(logPath));
			obj2.AppendLine(ref val3);
			val.AppendLine("New-Item -ItemType Directory -Force -Path (Split-Path -Parent $log) | Out-Null");
			val.AppendLine("\"[{0:yyyy-MM-dd HH:mm:ss}] DesktopBuddy elevated setup started\" -f (Get-Date) | Set-Content -LiteralPath $log");
			val.AppendLine("function Write-SetupLog([string]$Message) { Add-Content -LiteralPath $log -Value (\"[{0:HH:mm:ss}] {1}\" -f (Get-Date), $Message) }");
			val.AppendLine("function Run-SetupProcess([string]$File, [string]$Arguments, [string]$WorkingDirectory = $runtime, [int]$TimeoutMs = 60000) {");
			val.AppendLine("  Write-SetupLog ($File + ' ' + $Arguments)");
			val.AppendLine("  try {");
			val.AppendLine("    $process = Start-Process -FilePath $File -ArgumentList $Arguments -WorkingDirectory $WorkingDirectory -WindowStyle Hidden -PassThru");
			val.AppendLine("    if (-not $process.WaitForExit($TimeoutMs)) { try { $process.Kill() } catch {}; Write-SetupLog ($File + ' timed out'); return }");
			val.AppendLine("    Write-SetupLog ($File + ' exit=' + $process.ExitCode)");
			val.AppendLine("  } catch { Write-SetupLog ($File + ' failed: ' + $_.Exception.Message) }");
			val.AppendLine("}");
			val2 = val;
			StringBuilder obj3 = val2;
			((AppendInterpolatedStringHandler)(ref val3))..ctor(16, 1, val2);
			((AppendInterpolatedStringHandler)(ref val3)).AppendLiteral("$softCamClsid = ");
			((AppendInterpolatedStringHandler)(ref val3)).AppendFormatted(PsSingleQuote("{AEF3B972-5FA5-4647-9571-358EB472BC9E}"));
			obj3.AppendLine(ref val3);
			val2 = val;
			StringBuilder obj4 = val2;
			((AppendInterpolatedStringHandler)(ref val3))..ctor(27, 1, val2);
			((AppendInterpolatedStringHandler)(ref val3)).AppendLiteral("$videoInputCategoryClsid = ");
			((AppendInterpolatedStringHandler)(ref val3)).AppendFormatted(PsSingleQuote("{860BB310-5D01-11d0-BD3B-00A0C911CE86}"));
			obj4.AppendLine(ref val3);
			global::System.Collections.Generic.IEnumerator<SetupAction> enumerator = ((global::System.Collections.Generic.IEnumerable<SetupAction>)actions).GetEnumerator();
			try
			{
				while (((global::System.Collections.IEnumerator)enumerator).MoveNext())
				{
					switch (enumerator.Current)
					{
					case SetupAction.SoftCamRegistration:
						AppendSoftCamRegistrationScript(val);
						break;
					case SetupAction.VBCableInstall:
						AppendVBCableInstallScript(val);
						break;
					case SetupAction.VBCableLoopback:
						AppendVBCableLoopbackScript(val);
						break;
					case SetupAction.UrlAcl:
						AppendUrlAclScript(val);
						break;
					}
				}
			}
			finally
			{
				((global::System.IDisposable)enumerator)?.Dispose();
			}
			AppendSetupHashScript(val);
			val.AppendLine("Write-SetupLog 'DesktopBuddy elevated setup finished'");
			return ((object)val).ToString();
		}

		private static void AppendSoftCamRegistrationScript(StringBuilder script)
		{
			script.AppendLine("Write-SetupLog 'Registering SoftCam'");
			script.AppendLine("$softCamCandidates = @((Join-Path $runtime 'softcam64.dll'), (Join-Path $runtime 'softcam.dll'))");
			script.AppendLine("foreach ($candidate in $softCamCandidates) { if (Test-Path -LiteralPath $candidate) { Run-SetupProcess 'regsvr32.exe' ('/s /u \"' + $candidate + '\"') $runtime 10000 } }");
			script.AppendLine("$softCamKeys = @(");
			script.AppendLine("  'HKCU:\\Software\\Classes\\CLSID\\' + $softCamClsid,");
			script.AppendLine("  'HKCU:\\Software\\Classes\\WOW6432Node\\CLSID\\' + $softCamClsid,");
			script.AppendLine("  'HKLM:\\Software\\Classes\\CLSID\\' + $softCamClsid,");
			script.AppendLine("  'HKLM:\\Software\\Classes\\WOW6432Node\\CLSID\\' + $softCamClsid,");
			script.AppendLine("  'HKCU:\\Software\\Classes\\CLSID\\' + $videoInputCategoryClsid + '\\Instance\\DesktopBuddy - Camera',");
			script.AppendLine("  'HKCU:\\Software\\Classes\\CLSID\\' + $videoInputCategoryClsid + '\\Instance\\DirectShow Softcam',");
			script.AppendLine("  'HKCU:\\Software\\Classes\\WOW6432Node\\CLSID\\' + $videoInputCategoryClsid + '\\Instance\\DesktopBuddy - Camera',");
			script.AppendLine("  'HKCU:\\Software\\Classes\\WOW6432Node\\CLSID\\' + $videoInputCategoryClsid + '\\Instance\\DirectShow Softcam',");
			script.AppendLine("  'HKLM:\\Software\\Classes\\CLSID\\' + $videoInputCategoryClsid + '\\Instance\\DesktopBuddy - Camera',");
			script.AppendLine("  'HKLM:\\Software\\Classes\\CLSID\\' + $videoInputCategoryClsid + '\\Instance\\DirectShow Softcam',");
			script.AppendLine("  'HKLM:\\Software\\Classes\\WOW6432Node\\CLSID\\' + $videoInputCategoryClsid + '\\Instance\\DesktopBuddy - Camera',");
			script.AppendLine("  'HKLM:\\Software\\Classes\\WOW6432Node\\CLSID\\' + $videoInputCategoryClsid + '\\Instance\\DirectShow Softcam'");
			script.AppendLine(")");
			script.AppendLine("foreach ($key in $softCamKeys) { if (Test-Path -LiteralPath $key) { Remove-Item -LiteralPath $key -Recurse -Force -ErrorAction SilentlyContinue; Write-SetupLog ('Removed registry key ' + $key) } }");
			script.AppendLine("$softCamDll = Join-Path $runtime 'softcam64.dll'");
			script.AppendLine("if (-not (Test-Path -LiteralPath $softCamDll)) { $softCamDll = Join-Path $runtime 'softcam.dll' }");
			script.AppendLine("if (Test-Path -LiteralPath $softCamDll) { Run-SetupProcess 'regsvr32.exe' ('/s \"' + $softCamDll + '\"') $runtime 10000 } else { Write-SetupLog 'SoftCam DLL missing' }");
		}

		private static void AppendVBCableInstallScript(StringBuilder script)
		{
			script.AppendLine("Write-SetupLog 'Installing VB-Cable'");
			script.AppendLine("$vbCableInstaller = Join-Path $runtime 'VBCABLE_Setup_x64.exe'");
			script.AppendLine("if (Test-Path -LiteralPath $vbCableInstaller) { Run-SetupProcess $vbCableInstaller '-i -h' $runtime 60000 } else { Write-SetupLog 'VB-Cable installer missing' }");
		}

		private static void AppendVBCableLoopbackScript(StringBuilder script)
		{
			script.AppendLine("Write-SetupLog 'Disabling VB-Cable loopback'");
			script.AppendLine("$vbCableKey = 'HKLM:\\Software\\VB-Audio\\Cable'");
			script.AppendLine("if (Test-Path -LiteralPath $vbCableKey) {");
			script.AppendLine("  Set-ItemProperty -LiteralPath $vbCableKey -Name 'VBAudioCableWDM_LoopBack' -Type DWord -Value 0");
			script.AppendLine("  Run-SetupProcess 'net.exe' 'stop \"AudioEndpointBuilder\" /yes' $runtime 15000");
			script.AppendLine("  Run-SetupProcess 'net.exe' 'start \"AudioEndpointBuilder\"' $runtime 15000");
			script.AppendLine("  Run-SetupProcess 'net.exe' 'stop \"AudioSrv\" /yes' $runtime 15000");
			script.AppendLine("  Run-SetupProcess 'net.exe' 'start \"AudioSrv\"' $runtime 15000");
			script.AppendLine("} else { Write-SetupLog 'VB-Cable registry key not present yet' }");
		}

		private static void AppendUrlAclScript(StringBuilder script)
		{
			script.AppendLine("Write-SetupLog 'Configuring HTTP URL ACL'");
			script.AppendLine("Run-SetupProcess 'netsh' 'http add urlacl url=http://+:48080/ sddl=D:(A;;GX;;;S-1-1-0)' $runtime 10000");
		}

		private static void AppendSetupHashScript(StringBuilder script)
		{
			script.AppendLine("$packagedHashFile = Join-Path $runtime 'DesktopBuddySetupPayloads.md5'");
			script.AppendLine("$hashFile = Join-Path $runtime 'DesktopBuddySetupHashes.txt'");
			script.AppendLine("if (Test-Path -LiteralPath $packagedHashFile) { Copy-Item -LiteralPath $packagedHashFile -Destination $hashFile -Force; Write-SetupLog ('Wrote setup hash marker ' + $hashFile) }");
			script.AppendLine("else { Write-SetupLog 'Packaged setup hash manifest missing' }");
		}

		private static string PsSingleQuote(string value)
		{
			return "'" + value.Replace("'", "''") + "'";
		}

		private static void RegisterSoftCam(string runtimeDir)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//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_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			Log.Msg("[Setup] Registering SoftCam");
			global::System.Collections.Generic.IEnumerator<string> enumerator = GetSoftCamUnregisterCandidates(runtimeDir).GetEnumerator();
			try
			{
				while (((global::System.Collections.IEnumerator)enumerator).MoveNext())
				{
					string current = enumerator.Current;
					if (File.Exists(current))
					{
						RunProcess("regsvr32.exe", "/s /u \"" + current + "\"", null, 10000);
					}
				}
			}
			finally
			{
				((global::System.IDisposable)enumerator)?.Dispose();
			}
			global::System.Collections.Generic.IEnumerator<ValueTuple<RegistryKey, string>> enumerator2 = GetSoftCamRegistryTrees().GetEnumerator();
			try
			{
				while (((global::System.Collections.IEnumerator)enumerator2).MoveNext())
				{
					ValueTuple<RegistryKey, string> current2 = enumerator2.Current;
					DeleteRegistryTree(current2.Item1, current2.Item2);
				}
			}
			finally
			{
				((global::System.IDisposable)enumerator2)?.Dispose();
			}
			string text = Path.Combine(runtimeDir, "softcam64.dll");
			if (!File.Exists(text))
			{
				text = Path.Combine(runtimeDir, "softcam.dll");
			}
			if (!File.Exists(text))
			{
				Log.Msg("[Setup] SoftCam DLL missing in " + runtimeDir);
				return;
			}
			RunProcess("regsvr32.exe", "/s \"" + text + "\"", null, 10000);
			Log.Msg(IsSoftCamRegistered(runtimeDir) ? "[Setup] SoftCam registered" : "[Setup] WARNING: SoftCam registration did not resolve to expected path");
		}

		[IteratorStateMachine(typeof(<GetSoftCamUnregisterCandidates>d__29))]
		private static global::System.Collections.Generic.IEnumerable<string> GetSoftCamUnregisterCandidates(string runtimeDir)
		{
			yield return Path.Combine(runtimeDir, "softcam64.dll");
			yield return Path.Combine(runtimeDir, "softcam.dll");
			global::System.Collections.Generic.IEnumerator<string> enumerator = GetSoftCamRegisteredDlls().GetEnumerator();
			try
			{
				while (((global::System.Collections.IEnumerator)enumerator).MoveNext())
				{
					yield return enumerator.Current;
				}
			}
			finally
			{
				((global::System.IDisposable)enumerator)?.Dispose();
			}
		}

		[IteratorStateMachine(typeof(<GetSoftCamRegisteredDlls>d__30))]
		private static global::System.Collections.Generic.IEnumerable<string> GetSoftCamRegisteredDlls()
		{
			global::System.Collections.Generic.IEnumerator<ValueTuple<RegistryKey, string>> enumerator = GetSoftCamInprocKeys().GetEnumerator();
			try
			{
				while (((global::System.Collections.IEnumerator)enumerator).MoveNext())
				{
					ValueTuple<RegistryKey, string> current = enumerator.Current;
					RegistryKey opened = current.Item1.OpenSubKey(current.Item2);
					try
					{
						string text = ((opened != null) ? opened.GetValue("") : null) as string;
						if (!string.IsNullOrWhiteSpace(text))
						{
							yield return text.Trim('"');
						}
					}
					finally
					{
						((global::System.IDisposable)opened)?.Dispose();
					}
				}
			}
			finally
			{
				((global::System.IDisposable)enumerator)?.Dispose();
			}
		}

		[IteratorStateMachine(typeof(<GetSoftCamInprocKeys>d__31))]
		private static global::System.Collections.Generic.IEnumerable<ValueTuple<RegistryKey, string>> GetSoftCamInprocKeys()
		{
			yield return new ValueTuple<RegistryKey, string>(Registry.ClassesRoot, "CLSID\\{AEF3B972-5FA5-4647-9571-358EB472BC9E}\\InprocServer32");
			yield return new ValueTuple<RegistryKey, string>(Registry.CurrentUser, "Software\\Classes\\CLSID\\{AEF3B972-5FA5-4647-9571-358EB472BC9E}\\InprocServer32");
			yield return new ValueTuple<RegistryKey, string>(Registry.CurrentUser, "Software\\Classes\\WOW6432Node\\CLSID\\{AEF3B972-5FA5-4647-9571-358EB472BC9E}\\InprocServer32");
			yield return new ValueTuple<RegistryKey, string>(Registry.LocalMachine, "Software\\Classes\\CLSID\\{AEF3B972-5FA5-4647-9571-358EB472BC9E}\\InprocServer32");
			yield return new ValueTuple<RegistryKey, string>(Registry.LocalMachine, "Software\\Classes\\WOW6432Node\\CLSID\\{AEF3B972-5FA5-4647-9571-358EB472BC9E}\\InprocServer32");
		}

		[IteratorStateMachine(typeof(<GetSoftCamRegistryTrees>d__32))]
		private static global::System.Collections.Generic.IEnumerable<ValueTuple<RegistryKey, string>> GetSoftCamRegistryTrees()
		{
			yield return new ValueTuple<RegistryKey, string>(Registry.CurrentUser, "Software\\Classes\\CLSID\\{AEF3B972-5FA5-4647-9571-358EB472BC9E}");
			yield return new ValueTuple<RegistryKey, string>(Registry.CurrentUser, "Software\\Classes\\WOW6432Node\\CLSID\\{AEF3B972-5FA5-4647-9571-358EB472BC9E}");
			yield return new ValueTuple<RegistryKey, string>(Registry.LocalMachine, "Software\\Classes\\CLSID\\{AEF3B972-5FA5-4647-9571-358EB472BC9E}");
			yield return new ValueTuple<RegistryKey, string>(Registry.LocalMachine, "Software\\Classes\\WOW6432Node\\CLSID\\{AEF3B972-5FA5-4647-9571-358EB472BC9E}");
			yield return new ValueTuple<RegistryKey, string>(Registry.CurrentUser, "Software\\Classes\\CLSID\\{860BB310-5D01-11d0-BD3B-00A0C911CE86}\\Instance\\DesktopBuddy - Camera");
			yield return new ValueTuple<RegistryKey, string>(Registry.CurrentUser, "Software\\Classes\\CLSID\\{860BB310-5D01-11d0-BD3B-00A0C911CE86}\\Instance\\DirectShow Softcam");
			yield return new ValueTuple<RegistryKey, string>(Registry.CurrentUser, "Software\\Classes\\WOW6432Node\\CLSID\\{860BB310-5D01-11d0-BD3B-00A0C911CE86}\\Instance\\DesktopBuddy - Camera");
			yield return new ValueTuple<RegistryKey, string>(Registry.CurrentUser, "Software\\Classes\\WOW6432Node\\CLSID\\{860BB310-5D01-11d0-BD3B-00A0C911CE86}\\Instance\\DirectShow Softcam");
			yield return new ValueTuple<RegistryKey, string>(Registry.LocalMachine, "Software\\Classes\\CLSID\\{860BB310-5D01-11d0-BD3B-00A0C911CE86}\\Instance\\DesktopBuddy - Camera");
			yield return new ValueTuple<RegistryKey, string>(Registry.LocalMachine, "Software\\Classes\\CLSID\\{860BB310-5D01-11d0-BD3B-00A0C911CE86}\\Instance\\DirectShow Softcam");
			yield return new ValueTuple<RegistryKey, string>(Registry.LocalMachine, "Software\\Classes\\WOW6432Node\\CLSID\\{860BB310-5D01-11d0-BD3B-00A0C911CE86}\\Instance\\DesktopBuddy - Camera");
			yield return new ValueTuple<RegistryKey, string>(Registry.LocalMachine, "Software\\Classes\\WOW6432Node\\CLSID\\{860BB310-5D01-11d0-BD3B-00A0C911CE86}\\Instance\\DirectShow Softcam");
		}

		private static void DeleteRegistryTree(RegistryKey root, string subKey)
		{
			try
			{
				root.DeleteSubKeyTree(subKey, false);
				Log.Msg("[Setup] Removed registry key " + root.Name + "\\" + subKey);
			}
			catch (global::System.Exception ex)
			{
				Log.Msg($"[Setup] Unable to remove registry key {root.Name}\\{subKey}: {ex.Message}");
			}
		}

		private static bool IsSoftCamRegistered(string runtimeDir)
		{
			RegistryKey val = Registry.ClassesRoot.OpenSubKey("CLSID\\{AEF3B972-5FA5-4647-9571-358EB472BC9E}\\InprocServer32");
			try
			{
				string text = ((val != null) ? val.GetValue("") : null) as string;
				if (string.IsNullOrWhiteSpace(text))
				{
					return false;
				}
				string text2 = Path.Combine(runtimeDir, "softcam64.dll");
				return string.Equals(text.Trim('"'), text2, (StringComparison)5);
			}
			finally
			{
				((global::System.IDisposable)val)?.Dispose();
			}
		}

		private static void WriteSetupHashes(string runtimeDir)
		{
			try
			{
				Directory.CreateDirectory(runtimeDir);
				string text = Path.Combine(runtimeDir, "DesktopBuddySetupPayloads.md5");
				if (File.Exists(text))
				{
					File.Copy(text, Path.Combine(runtimeDir, "DesktopBuddySetupHashes.txt"), true);
				}
			}
			catch (global::System.Exception ex)
			{
				Log.Msg("[Setup] Failed to write setup hash marker: " + ex.Message);
			}
		}

		private static string ReadSetupHash(string runtimeDir, string fileName)
		{
			return ReadHashFile(Path.Combine(runtimeDir, "DesktopBuddySetupHashes.txt"), fileName);
		}

		private static string ReadPackagedSetupHash(string runtimeDir, string fileName)
		{
			return ReadHashFile(Path.Combine(runtimeDir, "DesktopBuddySetupPayloads.md5"), fileName);
		}

		private static string ReadHashFile(string path, string fileName)
		{
			if (string.IsNullOrWhiteSpace(path) || string.IsNullOrWhiteSpace(fileName))
			{
				return null;
			}
			try
			{
				if (!File.Exists(path))
				{
					return null;
				}
				global::System.Collections.Generic.IEnumerator<string> enumerator = File.ReadLines(path).GetEnumerator();
				try
				{
					while (((global::System.Collections.IEnumerator)enumerator).MoveNext())
					{
						string current = enumerator.Current;
						int num = current.IndexOf('=');
						if (num > 0 && string.Equals(current.Substring(0, num).Trim(), fileName, (StringComparison)5))
						{
							return current.Substring(num + 1).Trim();
						}
					}
				}
				finally
				{
					((global::System.IDisposable)enumerator)?.Dispose();
				}
			}
			catch (global::System.Exception ex)
			{
				Log.Msg("[Setup] Failed to read setup hash marker: " + ex.Message);
			}
			return null;
		}

		private static bool PathsEqual(string left, string right)
		{
			if (string.IsNullOrWhiteSpace(left) || string.IsNullOrWhiteSpace(right))
			{
				return false;
			}
			try
			{
				left = Path.GetFullPath(left.Trim('"'));
				right = Path.GetFullPath(right.Trim('"'));
			}
			catch
			{
				left = left.Trim('"');
				right = right.Trim('"');
			}
			return string.Equals(left, right, (StringComparison)5);
		}

		private static global::System.Collections.Generic.IReadOnlyList<string> GetRunningRestartSensitiveProcesses()
		{
			HashSet<string> val = new HashSet<string>((global::System.Collections.Generic.IEnumerable<string>)new string[16]
			{
				"Discord", "DiscordCanary", "DiscordPTB", "obs64", "obs32", "zoom", "Teams", "ms-teams", "chrome", "msedge",
				"firefox", "brave", "slack", "Skype", "Webex", "ManyCam"
			}, (IEqualityComparer<string>)(object)StringComparer.OrdinalIgnoreCase);
			SortedSet<string> val2 = new SortedSet<string>((IComparer<string>)(object)StringComparer.OrdinalIgnoreCase);
			try
			{
				Process[] processes = Process.GetProcesses();
				foreach (Process val3 in processes)
				{
					Process val4 = val3;
					try
					{
						string processName = val3.ProcessName;
						if (val.Contains(processName))
						{
							val2.Add(processName);
						}
					}
					finally
					{
						((global::System.IDisposable)val4)?.Dispose();
					}
				}
			}
			catch
			{
			}
			return Enumerable.ToArray<string>((global::System.Collections.Generic.IEnumerable<string>)val2);
		}

		private static void InstallVBCable(string runtimeDir)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			string text = Path.Combine(runtimeDir, "VBCABLE_Setup_x64.exe");
			if (!File.Exists(text))
			{
				Log.Msg("[Setup] VB-Cable installer missing at " + text);
				return;
			}
			RunProcess(text, "-i -h", runtimeDir);
			Log.Msg(IsVBCableInstalled() ? "[Setup] VB-Cable detected" : "[Setup] VB-Cable not detected yet; reboot may be required");
		}

		private static bool IsVBCableInstalled()
		{
			RegistryKey val = Registry.LocalMachine.OpenSubKey("Software\\VB-Audio\\Cable");
			try
			{
				return val != null;
			}
			finally
			{
				((global::System.IDisposable)val)?.Dispose();
			}
		}

		private static void ConfigureVBCableLoopback()
		{
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			RegistryKey val = Registry.LocalMachine.OpenSubKey("Software\\VB-Audio\\Cable", true);
			try
			{
				if (val == null)
				{
					Log.Msg("[Setup] VB-Cable registry key not present yet");
					return;
				}
				if (val.GetValue("VBAudioCableWDM_LoopBack") as int? == 0)
				{
					Log.Msg("[Setup] VB-Cable loopback already disabled");
					return;
				}
				val.SetValue("VBAudioCableWDM_LoopBack", (object)0, (RegistryValueKind)4);
				Log.Msg("[Setup] VB-Cable loopback disabled");
				RunProcess("net.exe", "stop \"AudioEndpointBuilder\" /yes", null, 15000);
				RunProcess("net.exe", "start \"AudioEndpointBuilder\"", null, 15000);
				RunProcess("net.exe", "stop \"AudioSrv\" /yes", null, 15000);
				RunProcess("net.exe", "start \"AudioSrv\"", null, 15000);
			}
			finally
			{
				((global::System.IDisposable)val)?.Dispose();
			}
		}

		private static bool IsVBCableLoopbackDisabled()
		{
			RegistryKey val = Registry.LocalMachine.OpenSubKey("Software\\VB-Audio\\Cable");
			try
			{
				return ((val != null) ? val.GetValue("VBAudioCableWDM_LoopBack") : null) as int? == 0;
			}
			finally
			{
				((global::System.IDisposable)val)?.Dispose();
			}
		}

		private static void ConfigureUrlAcl()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			if (IsUrlAclConfigured())
			{
				Log.Msg("[Setup] HTTP URL ACL already configured");
				return;
			}
			RunProcess("netsh", "http add urlacl url=http://+:48080/ sddl=D:(A;;GX;;;S-1-1-0)", null, 10000);
			Log.Msg(IsUrlAclConfigured() ? "[Setup] HTTP URL ACL added" : "[Setup] WARNING: HTTP URL ACL was not detected after setup");
		}

		private static bool IsUrlAclConfigured()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: 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_001f: Unknown result type (might be due to invalid IL or missing references)
			ValueTuple<int, string> val = RunProcess("netsh", "http show urlacl url=http://+:48080/", null, 10000, captureOutput: true);
			if (val.Item1 == 0)
			{
				return val.Item2.Contains("48080", (StringComparison)5);
			}
			return false;
		}

		private static ValueTuple<int, string> RunProcess(string fileName, string arguments, string workingDirectory = null, int timeoutMs = 60000, bool captureOutput = false)
		{
			//IL_0000: 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_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: 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_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: 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_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			Process val = Process.Start(new ProcessStartInfo
			{
				FileName = fileName,
				Arguments = arguments,
				WorkingDirectory = (workingDirectory ?? ResolveResoniteRoot()),
				UseShellExecute = false,
				CreateNoWindow = true,
				RedirectStandardOutput = captureOutput,
				RedirectStandardError = captureOutput,
				WindowStyle = (ProcessWindowStyle)1
			});
			try
			{
				if (val == null)
				{
					return new ValueTuple<int, string>(-1, "");
				}
				if (!val.WaitForExit(timeoutMs))
				{
					try
					{
						val.Kill();
					}
					catch
					{
					}
					Log.Msg("[Setup] " + fileName + " timed out");
					return new ValueTuple<int, string>(-1, "");
				}
				string text = "";
				if (captureOutput)
				{
					text = (((TextReader)val.StandardOutput).ReadToEnd() + "\n" + ((TextReader)val.StandardError).ReadToEnd()).Trim();
				}
				Log.Msg($"[Setup] {fileName} {arguments} exit={val.ExitCode}");
				return new ValueTuple<int, string>(val.ExitCode, text);
			}
			finally
			{
				((global::System.IDisposable)val)?.Dispose();
			}
		}

		private static bool IsAdministrator()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			WindowsIdentity current = WindowsIdentity.GetCurrent();
			try
			{
				return new WindowsPrincipal(current).IsInRole((WindowsBuiltInRole)544);
			}
			finally
			{
				((global::System.IDisposable)current)?.Dispose();
			}
		}

		private static string GetRuntimeDir()
		{
			return DesktopBuddyRuntimePaths.GetDirectory();
		}

		private static string ResolveResoniteRoot()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			string text = Path.GetDirectoryName(typeof(DesktopBuddyMod).Assembly.Location) ?? ".";
			for (DirectoryInfo val = new DirectoryInfo(text); val != null; val = val.Parent)
			{
				if (File.Exists(Path.Combine(((FileSystemInfo)val).FullName, "Resonite.exe")))
				{
					return ((FileSystemInfo)val).FullName;
				}
			}
			return AppDomain.CurrentDomain.BaseDirectory ?? text;
		}
	}
	[ResonitePlugin("com.devl0rd.DesktopBuddy", "DesktopBuddy", "1.1.0", "DevL0rd", "https://github.com/DevL0rd/DesktopBuddy")]
	[BepInPlugin("com.devl0rd.DesktopBuddy", "DesktopBuddy", "1.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class DesktopBuddyMod : BasePlugin
	{
		[UnmanagedFunctionPointer(/*Could not decode attribute arguments.*/)]
		private delegate int UnhandledExceptionFilterDelegate(nint exceptionPointers);

		private struct JOBOBJECT_BASIC_LIMIT_INFORMATION
		{
			public long PerProcessUserTimeLimit;

			public long PerJobUserTimeLimit;

			public uint LimitFlags;

			public nuint MinimumWorkingSetSize;

			public nuint MaximumWorkingSetSize;

			public uint ActiveProcessLimit;

			public long Affinity;

			public uint PriorityClass;

			public uint SchedulingClass;
		}

		private struct IO_COUNTERS
		{
			public ulong ReadOperationCount;

			public ulong WriteOperationCount;

			public ulong OtherOperationCount;

			public ulong ReadTransferCount;

			public ulong WriteTransferCount;

			public ulong OtherTransferCount;
		}

		private struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION
		{
			public JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation;

			public IO_COUNTERS IoInfo;

			public nuint ProcessMemoryLimit;

			public nuint JobMemoryLimit;

			public nuint PeakProcessMemoryUsed;

			public nuint PeakJobMemoryUsed;
		}

		private sealed class SetupStatusRowRefs
		{
			public Text Name;

			public Text Detail;

			public Text Status;

			public Image Badge;
		}

		[CompilerGenerated]
		private static class <>O
		{
			public static Action<string> <0>__Msg;

			public static ThreadStart <1>__WindowPollerLoop;

			public static ResolveEventHandler <2>__ResolveDesktopBuddyManagedDependency;

			public static UnhandledExceptionFilterDelegate <3>__NativeCrashFilter;

			public static Func<global::System.Exception, bool> <4>__IsGitHubReleaseNotFound;

			public static Action <5>__CloseSetupPanel;

			public static Action <6>__PollSetupInstall;
		}

		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static UnhandledExceptionEventHandler <>9__13_0;

			public static EventHandler<UnobservedTaskExceptionEventArgs> <>9__13_1;

			public static Action <>9__14_0;

			public static Action <>9__14_1;

			public static Action <>9__14_2;

			public static EventHandler <>9__15_0;

			public static Action <>9__249_0;

			public static DataReceivedEventHandler <>9__250_1;

			public static DataReceivedEventHandler <>9__250_2;

			public static Action <>9__261_0;

			public static Predicate<Image> <>9__281_10;

			public static Predicate<Image> <>9__281_14;

			public static ButtonEventHandler <>9__282_0;

			public static Func<User, bool> <>9__312_0;

			public static Action<string> <>9__355_0;

			public static Action<bool> <>9__355_1;

			public static Action<float> <>9__355_2;

			public static Action<string> <>9__355_3;

			public static Action<string> <>9__355_4;

			public static Action<float> <>9__355_5;

			public static Action<float> <>9__355_6;

			public static Action<float> <>9__355_7;

			public static Action<float> <>9__355_8;

			public static Action<float> <>9__355_9;

			public static Action<float> <>9__355_10;

			public static Action<string> <>9__355_11;

			public static Action<bool> <>9__355_12;

			public static Action<float> <>9__355_13;

			public static Action<float> <>9__355_14;

			public static Action<int> <>9__355_15;

			public static Action<bool> <>9__375_0;

			public static Action <>9__375_1;

			public static Action<bool> <>9__379_0;

			public static Action<bool> <>9__379_1;

			public static Action<bool> <>9__379_2;

			public static Action<bool> <>9__379_3;

			public static Action<bool> <>9__379_4;

			public static Action<bool> <>9__379_5;

			public static Action<bool> <>9__379_6;

			public static Action<bool> <>9__393_1;

			public static Action<string> <>9__393_2;

			public static Action<string> <>9__393_3;

			public static Func<ValueTuple<int, string>, ValueTuple<string, string>> <>9__405_0;

			public static Func<ValueTuple<int, string>, ValueTuple<string, string>> <>9__405_2;

			public static Func<WgcCapture.GpuAdapterInfo, bool> <>9__405_6;

			public static Func<WgcCapture.GpuAdapterInfo, string> <>9__405_7;

			public static Func<IGrouping<string, WgcCapture.GpuAdapterInfo>, WgcCapture.GpuAdapterInfo> <>9__405_8;

			public static Func<WgcCapture.GpuAdapterInfo, ValueTuple<string, string>> <>9__405_9;

			public static Func<User, bool> <>9__450_0;

			public static Func<User, string> <>9__450_1;

			public static Func<DesktopSession, int> <>9__451_1;

			public static Func<DesktopSession, bool> <>9__451_3;

			public static Func<IGrouping<int, DesktopSession>, DesktopSession> <>9__451_2;

			public static Func<User, bool> <>9__461_1;

			public static Func<User, string> <>9__461_2;

			public static Action<IDestroyable> <>9__477_0;

			public static Func<DesktopBuddyFirstRunSetup.SetupItem, bool> <>9__488_0;

			internal void <InitializeCore>b__13_0(object sender, UnhandledExceptionEventArgs e)
			{
				Log.Msg($"UNHANDLED EXCEPTION (terminating={e.IsTerminating}):\n{e.ExceptionObject}");
			}

			internal void <InitializeCore>b__13_1(object? sender, UnobservedTaskExceptionEventArgs e)
			{
				Log.Msg($"UNOBSERVED TASK EXCEPTION:\n{e.Exception}");
				e.SetObserved();
			}

			internal void <EnsureDependencyRuntimeStarted>b__14_0()
			{
				StartTunnel();
			}

			internal void <EnsureDependencyRuntimeStarted>b__14_1()
			{
				try
				{
					if (SoftCam.IsFilterRegistered())
					{
						VCam = new VirtualCamera();
						VCam.StartIdle();
					}
					else
					{
						Msg("[VirtualCamera] DirectShow filter not registered, virtual camera unavailable");
					}
				}
				catch (global::System.Exception ex)
				{
					Msg("[VirtualCamera] Setup error: " + ex.Message);
				}
				try
				{
					if (!VBCable.HasCableInputDevice())
					{
						Msg("[VirtualMic] VB-Cable not installed, virtual mic unavailable");
					}
				}
				catch (global::System.Exception ex2)
				{
					Msg("[VirtualMic] Setup error: " + ex2.Message);
				}
			}

			internal void <EnsureDependencyRuntimeStarted>b__14_2()
			{
				try
				{
					VirtualCamera virtualCamera = new VirtualCamera();
					if (virtualCamera.StartIdle())
					{
						VCam = virtualCamera;
						Msg("[VirtualCamera] Linux v4l2 virtual camera ready");
					}
					else
					{
						virtualCamera.Dispose();
						Msg("[VirtualCamera] Linux virtual camera unavailable; run setup in the Devices tab");
					}
				}
				catch (global::System.Exception ex)
				{
					Msg("[VirtualCamera] Linux setup error: " + ex.Message);
				}
			}

			internal void <RegisterShutdownCleanup>b__15_0(object? s, EventArgs e)
			{
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				HashSet<uint> val = new HashSet<uint>();
				Enumerator<DesktopSession> enumerator = ActiveSessions.GetEnumerator();
				try
				{
					while (enumerator.MoveNext())
					{
						DesktopSession current = enumerator.Current;
						if (!DesktopBuddyPlatform.IsLinux && current.OwnsAudioRedirect && current.ProcessId != 0 && val.Add(current.ProcessId))
						{
							AudioRouter.ResetProcessToDefault(current.ProcessId);
						}
					}
				}
				finally
				{
					((global::System.IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
				}
				KillTunnel();
				RemovePortForwardNatMapping();
				try
				{
					StreamServer?.Dispose();
				}
				catch
				{
				}
			}

			internal void <RestartTunnel>b__249_0()
			{
				try
				{
					Msg("[Tunnel] === RESTART ===");
					KillTunnel();
					TunnelUrl = null;
					Thread.Sleep(2000);
					StartTunnel();
				}
				catch (global::System.Exception ex)
				{
					Msg($"[Tunnel] Restart task error: {ex}");
				}
				finally
				{
					_tunnelRestarting = false;
				}
			}

			internal void <StartTunnel>b__250_1(object s, DataReceivedEventArgs e)
			{
				//IL_006e: Unknown result type (might be due to invalid IL or missing references)
				if (e.Data == null)
				{
					return;
				}
				if (e.Data.Contains("https://") && e.Data.Contains(".trycloudflare.com"))
				{
					int num = e.Data.IndexOf("https://");
					string text = e.Data.Substring(num).Trim();
					int num2 = text.IndexOf(' ');
					if (num2 > 0)
					{
						text = text.Substring(0, num2);
					}
					try
					{
						text = new Uri(text).GetLeftPart((UriPartial)1);
					}
					catch (global::System.Exception ex)
					{
						Msg("[Tunnel] URL parse error: " + ex.Message);
					}
					string tunnelUrl = TunnelUrl;
					TunnelUrl = text;
					if (tunnelUrl != text)
					{
						Msg("[Tunnel] PUBLIC URL: " + TunnelUrl);
						try
						{
							UpdateSessionTunnelUrls();
						}
						catch (global::System.Exception ex2)
						{
							Msg($"[Tunnel] PUBLIC URL refresh error: {ex2}");
						}
					}
				}
				else if (ShouldLogCloudflaredLine(e.Data))
				{
					Msg("[Tunnel] " + e.Data);
				}
				OnTunnelError(e.Data);
			}

			internal void <StartTunnel>b__250_2(object s, DataReceivedEventArgs e)
			{
				if (e.Data != null && ShouldLogCloudflaredLine(e.Data))
				{
					Msg("[Tunnel] " + e.Data);
				}
			}

			internal void <ApplyStreamNetworkMode>b__261_0()
			{
				StartTunnel();
			}

			internal bool <FinishStartStreaming>b__281_10(Image image)
			{
				return ((Component)image).Slot.Name == "Background";
			}

			internal bool <FinishStartStreaming>b__281_14(Image image)
			{
				return ((Component)image).Slot.Name == "Background";
			}

			internal void <CreateVirtualDeviceControls>b__282_0(IButton b, ButtonEventData d)
			{
				if (VCam == null)
				{
					Msg("[VirtualCamera] Not available");
					return;
				}
				VCam.ManuallyDisabled = !VCam.ManuallyDisabled;
				Msg("[VirtualCamera] " + (VCam.ManuallyDisabled ? "Disabled" : "Enabled"));
			}

			internal bool <CreateViewerCullingGate>b__312_0(User u)
			{
				return u.IsPresentInWorld;
			}

			internal void <BuildAudioTab>b__355_0(string value)
			{
				SaveConfigValue(StreamAudioGlobalMode, NormalizeStreamAudioGlobalMode(value));
				ApplyStreamAudioSettingsToAllSessions();
			}

			internal void <BuildAudioTab>b__355_1(bool value)
			{
				SaveConfigValue(StreamAudioSpatialize, value);
				ApplyStreamAudioSettingsToAllSessions();
			}

			internal void <BuildAudioTab>b__355_2(float value)
			{
				SaveConfigValue(StreamAudioSpatialBlend, Math.Clamp(value, 0f, 1f));
				ApplyStreamAudioSettingsToAllSessions();
			}

			internal void <BuildAudioTab>b__355_3(string value)
			{
				SaveConfigValue(StreamAudioDistanceSpace, NormalizeStreamAudioDistanceSpace(value));
				ApplyStreamAudioSettingsToAllSessions();
			}

			internal void <BuildAudioTab>b__355_4(string value)
			{
				SaveConfigValue(StreamAudioRolloffMode, NormalizeStreamAudioRolloffMode(value));
				ApplyStreamAudioSettingsToAllSessions();
			}

			internal void <BuildAudioTab>b__355_5(float value)
			{
				SaveConfigValue(StreamAudioMinDistance, Math.Clamp(value, 0f, 10f));
				ApplyStreamAudioSettingsToAllSessions();
			}

			internal void <BuildAudioTab>b__355_6(float value)
			{
				SaveConfigValue(StreamAudioMaxDistance, Math.Clamp(value, 1f, 50f));
				ApplyStreamAudioSettingsToAllSessions();
			}

			internal void <BuildAudioTab>b__355_7(float value)
			{
				SaveConfigValue(StreamAudioSpatializationStartDistance, Math.Clamp(value, 0f, 10f));
				ApplyStreamAudioSettingsToAllSessions();
			}

			internal void <BuildAudioTab>b__355_8(float value)
			{
				SaveConfigValue(StreamAudioSpatializationTransitionRange, Math.Clamp(value, 0f, 10f));
				ApplyStreamAudioSettingsToAllSessions();
			}

			internal void <BuildAudioTab>b__355_9(float value)
			{
				SaveConfigValue(StreamAudioMinScale, Math.Clamp(value, 0f, 1000f));
				ApplyStreamAudioSettingsToAllSessions();
			}

			internal void <BuildAudioTab>b__355_10(float value)
			{
				SaveConfigValue(StreamAudioMaxScale, Math.Clamp(value, 0f, 1000f));
				ApplyStreamAudioSettingsToAllSessions();
			}

			internal void <BuildAudioTab>b__355_11(string value)
			{
				SaveConfigValue(StreamAudioTypeGroup, NormalizeStreamAudioTypeGroup(value));
				ApplyStreamAudioSettingsToAllSessions();
			}

			internal void <BuildAudioTab>b__355_12(bool value)
			{
				SaveConfigValue(StreamAudioIgnoreAudioEffects, value);
				ApplyStreamAudioSettingsToAllSessions();
			}

			internal void <BuildAudioTab>b__355_13(float value)
			{
				SaveConfigValue(StreamAudioPitch, Math.Clamp(value, 0.5f, 2f));
				ApplyStreamAudioSettingsToAllSessions();
			}

			internal void <BuildAudioTab>b__355_14(float value)
			{
				SaveConfigValue(StreamAudioDopplerLevel, Math.Clamp(value, 0f, 1f));
				ApplyStreamAudioSettingsToAllSessions();
			}

			internal void <BuildAudioTab>b__355_15(int value)
			{
				SaveConfigValue(StreamAudioPriority, Math.Clamp(value, 0, 256));
				ApplyStreamAudioSettingsToAllSessions();
			}

			internal void <BuildDevicesTab>b__375_0(bool value)
			{
				if (VCam != null)
				{
					VCam.ManuallyDisabled = !value;
				}
			}

			internal void <BuildDevicesTab>b__375_1()
			{
				LinuxVirtualCameraSetup.Run();
			}

			internal void <BuildGeneralTab>b__379_0(bool value)
			{
				SaveConfigValue(ShowContextMenuItem, value);
			}

			internal void <BuildGeneralTab>b__379_1(bool value)
			{
				SaveConfigValue(ThrowToDestroy, value);
			}

			internal void <BuildGeneralTab>b__379_2(bool value)
			{
				SaveConfigValue(DynamicLightsEnabled, value);
			}

			internal void <BuildGeneralTab>b__379_3(bool value)
			{
				SaveConfigValue(SpawnNewWindowsInGame, value);
			}

			internal void <BuildGeneralTab>b__379_4(bool value)
			{
				SaveConfigValue(SpawnNewWindowsPrivate, value);
			}

			internal void <BuildGeneralTab>b__379_5(bool value)
			{
				SaveConfigValue(NewWindowsStartPrivate, value);
			}

			internal void <BuildGeneralTab>b__379_6(bool value)
			{
				SaveConfigValue(SpatialAudioEnabled, value);
			}

			internal void <BuildNetworkTab>b__393_1(bool value)
			{
				SaveConfigValue(PortForwardUseNat, value);
				ApplyStreamNetworkMode();
			}

			internal void <BuildNetworkTab>b__393_2(string value)
			{
				SaveConfigValue(PortForwardHostMode, NormalizePortForwardHostMode(value));
				ApplyStreamNetworkMode();
			}

			internal void <BuildNetworkTab>b__393_3(string value)
			{
				SaveConfigValue(PortForwardHost, value.Trim());
				ApplyStreamNetworkMode();
			}

			internal ValueTuple<string, string> <BuildStreamTab>b__405_0(ValueTuple<int, string> option)
			{
				//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)
				return new ValueTuple<string, string>(option.Item1.ToString((IFormatProvider)(object)CultureInfo.InvariantCulture), option.Item2);
			}

			internal ValueTuple<string, string> <BuildStreamTab>b__405_2(ValueTuple<int, string> option)
			{
				//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)
				return new ValueTuple<string, string>(option.Item1.ToString((IFormatProvider)(object)CultureInfo.InvariantCulture), option.Item2);
			}

			internal bool <BuildStreamTab>b__405_6(WgcCapture.GpuAdapterInfo g)
			{
				if (!g.IsBasicRenderDriver)
				{
					return !string.IsNullOrWhiteSpace(g.Name);
				}
				return false;
			}

			internal string <BuildStreamTab>b__405_7(WgcCapture.GpuAdapterInfo g)
			{
				return NormalizeGpuDisplayName(g.Name);
			}

			internal WgcCapture.GpuAdapterInfo <BuildStreamTab>b__405_8(IGrouping<string, WgcCapture.GpuAdapterInfo> group)
			{
				return Enumerable.First<WgcCapture.GpuAdapterInfo>((global::System.Collections.Generic.IEnumerable<WgcCapture.GpuAdapterInfo>)group);
			}

			internal ValueTuple<string, string> <BuildStreamTab>b__405_9(WgcCapture.GpuAdapterInfo gpu)
			{
				//IL_002b: Unknown result type (might be due to invalid IL or missing references)
				return new ValueTuple<string, string>("0x" + gpu.Luid.ToString("X16", (IFormatProvider)(object)CultureInfo.InvariantCulture), NormalizeGpuDisplayName(gpu.Name));
			}

			internal bool <BuildViewersTab>b__450_0(User u)
			{
				return u.IsPresentInWorld;
			}

			internal string <BuildViewersTab>b__450_1(User u)
			{
				return u.UserName;
			}

			internal int <RequestStreamEncoderRestart>b__451_1(DesktopSession s)
			{
				return s.StreamId;
			}

			internal DesktopSession <RequestStreamEncoderRestart>b__451_2(IGrouping<int, DesktopSession> group)
			{
				global::System.Collections.Generic.IEnumerator<DesktopSession> enumerator = ((global::System.Collections.Generic.IEnumerable<DesktopSession>)group).GetEnumerator();
				try
				{
					while (((global::System.Collections.IEnumerator)enumerator).MoveNext())
					{
						DesktopSession current = enumerator.Current;
						DesktopSession sharedStreamDriver = GetSharedStreamDriver(current.Hwnd, current.StreamId);
						if (sharedStreamDriver != null && Enumerable.Contains<DesktopSession>((global::System.Collections.Generic.IEnumerable<DesktopSession>)group, sharedStreamDriver))
						{
							return sharedStreamDriver;
						}
					}
				}
				finally
				{
					((global::System.IDisposable)enumerator)?.Dispose();
				}
				return Enumerable.FirstOrDefault<DesktopSession>((global::System.Collections.Generic.IEnumerable<DesktopSession>)group, (Func<DesktopSession, bool>)((DesktopSession s) => s.Streamer != null)) ?? Enumerable.First<DesktopSession>((global::System.Collections.Generic.IEnumerable<DesktopSession>)group);
			}

			internal bool <RequestStreamEncoderRestart>b__451_3(DesktopSession s)
			{
				return s.Streamer != null;
			}

			internal bool <ScheduleViewerListRefresh>b__461_1(User u)
			{
				return u.IsPresentInWorld;
			}

			internal string <ScheduleViewerListRefresh>b__461_2(User u)
			{
				return u.UserName;
			}

			internal void <ShowSetupPanel>b__477_0(IDestroyable _)
			{
				bool num = _setupCompleteAwaitingClose && !_setupNoticeDismissed;
				if (_setupPanelRoot != null && ((ContainerWorker<Component>)(object)_setupPanelRoot).IsDestroyed)
				{
					_setupPanelRoot = null;
				}
				_setupPanelCanvas = null;
				_setupBodyText = null;
				_setupInstallButtonSlot = null;
				_setupStatusRows.Clear();
				if (num)
				{
					Msg("[SetupPanel] Setup panel closed after completion; continuing DesktopBuddy initialization");
					_setupNoticeDismissed = true;
					_setupCompleteAwaitingClose = false;
					EnsureDependencyRuntimeStarted();
				}
			}

			internal bool <GetSetupPanelMessage>b__488_0(DesktopBuddyFirstRunSetup.SetupItem item)
			{
				if (!item.IsOk)
				{
					return !item.RequiresAdminAction;
				}
				return false;
			}

			internal bool <.cctor>b__499_0()
			{
				return false;
			}

			internal bool <.cctor>b__499_1()
			{
				return true;
			}

			internal bool <.cctor>b__499_2()
			{
				return true;
			}

			internal bool <.cctor>b__499_3()
			{
				return true;
			}

			internal bool <.cctor>b__499_4()
			{
				return true;
			}

			internal bool <.cctor>b__499_5()
			{
				return true;
			}

			internal bool <.cctor>b__499_6()
			{
				return false;
			}

			internal bool <.cctor>b__499_7()
			{
				return false;
			}

			internal int <.cctor>b__499_8()
			{
				return 10;
			}

			internal int <.cctor>b__499_9()
			{
				return 60;
			}

			internal int <.cctor>b__499_10()
			{
				return 2560;
			}

			internal bool <.cctor>b__499_11()
			{
				return false;
			}

			internal string <.cctor>b__499_12()
			{
				return "";
			}

			internal int <.cctor>b__499_13()
			{
				return 8554;
			}

			internal string <.cctor>b__499_14()
			{
				return "";
			}

			internal string <.cctor>b__499_15()
			{
				return "cloudflare";
			}

			internal string <.cctor>b__499_16()
			{
				return "auto";
			}

			internal string <.cctor>b__499_17()
			{
				return "external";
			}

			internal string <.cctor>b__499_18()
			{
				return "";
			}

			internal bool <.cctor>b__499_19()
			{
				return false;
			}

			internal string <.cctor>b__499_20()
			{
				return "";
			}

			internal string <.cctor>b__499_21()
			{
				return "";
			}

			internal string <.cctor>b__499_22()
			{
				return "frustum";
			}

			internal bool <.cctor>b__499_23()
			{
				return false;
			}

			internal float <.cctor>b__499_24()
			{
				return 120f;
			}

			internal float <.cctor>b__499_25()
			{
				return 3f;
			}

			internal float <.cctor>b__499_26()
			{
				return 3f;
			}

			internal string <.cctor>b__499_27()
			{
				return "auto";
			}

			internal string <.cctor>b__499_28()
			{
				return "";
			}

			internal float <.cctor>b__499_29()
			{
				return 0f;
			}

			internal string <.cctor>b__499_30()
			{
				return "positional";
			}

			internal bool <.cctor>b__499_31()
			{
				return true;
			}

			internal float <.cctor>b__499_32()
			{
				return 1f;
			}

			internal string <.cctor>b__499_33()
			{
				return "global";
			}

			internal float <.cctor>b__499_34()
			{
				return 0f;
			}

			internal float <.cctor>b__499_35()
			{
				return 1f;
			}

			internal bool <.cctor>b__499_36()
			{
				return true;
			}

			internal string <.cctor>b__499_37()
			{
				return "multimedia";
			}

			internal string <.cctor>b__499_38()
			{
				return "linear";
			}

			internal float <.cctor>b__499_39()
			{
				return 1f;
			}

			internal float <.cctor>b__499_40()
			{
				return 30f;
			}

			internal float <.cctor>b__499_41()
			{
				return 0.01f;
			}

			internal float <.cctor>b__499_42()
			{
				return 0.01f;
			}

			internal int <.cctor>b__499_43()
			{
				return 128;
			}

			internal float <.cctor>b__499_44()
			{
				return 0f;
			}

			internal float <.cctor>b__499_45()
			{
				return 1000f;
			}
		}

		[CompilerGenerated]
		private sealed class <>c__DisplayClass281_1
		{
			[StructLayout((LayoutKind)3)]
			private struct <<FinishStartStreaming>b__34>d : IAsyncStateMachine
			{
				public int <>1__state;

				public AsyncTaskMethodBuilder <>t__builder;

				public <>c__DisplayClass281_1 <>4__this;

				private <>c__DisplayClass281_2 <>8__1;

				private ConfiguredTaskAwaiter<Uri> <>u__1;

				private void MoveNext()
				{
					//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
					//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
					//IL_00b4: 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_004c: Expected O, but got Unknown
					//IL_0069: 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_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_008c: Unknown result type (might be due to invalid IL or missing references)
					//IL_008e: Unknown result type (might be due to invalid IL or missing references)
					//IL_012a: Unknown result type (might be due to invalid IL or missing references)
					//IL_0134: Expected O, but got Unknown
					//IL_012f: Unknown result type (might be due to invalid IL or missing references)
					int num = <>1__state;
					<>c__DisplayClass281_1 <>c__DisplayClass281_ = <>4__this;
					try
					{
						try
						{
							ConfiguredTaskAwaiter<Uri> val2;
							if (num != 0)
							{
								<>8__1 = new <>c__DisplayClass281_2();
								<>8__1.CS$<>8__locals1 = <>c__DisplayClass281_;
								Bitmap2D val = new Bitmap2D(<>c__DisplayClass281_.data, <>c__DisplayClass281_.texW, <>c__DisplayClass281_.texH, (TextureFormat)18, false, (ColorProfile)0, false, (string)null);
								val2 = <>c__DisplayClass281_.engine.LocalDB.SaveAssetAsync(val, "webp", 2147483647, true).ConfigureAwait(false).GetAwaiter();
								if (!val2.IsCompleted)
								{
									num = (<>1__state = 0);
									<>u__1 = val2;
									((AsyncTaskMethodBuilder)(ref <>t__builder)).AwaitUnsafeOnCompleted<ConfiguredTaskAwaiter<Uri>, <<FinishStartStreaming>b__34>d>(ref val2, ref this);
									return;
								}
							}
							else
							{
								val2 = <>u__1;
								<>u__1 = default(ConfiguredTaskAwaiter<Uri>);
								num = (<>1__state = -1);
							}
							Uri result = val2.GetResult();
							<>8__1.uri = result;
							if (!(<>8__1.uri == (Uri)null))
							{
								World world = ((Worker)<>c__DisplayClass281_.tex).World;
								if (world != null && !((ComponentBase<Component>)(object)<>c__DisplayClass281_.tex).IsDestroyed && !((ComponentBase<Component>)(object)<>c__DisplayClass281_.blur).IsDestroyed)
								{
									world.RunInUpdates(0, (Action)delegate
									{
										//IL_0070: Unknown result type (might be due to invalid IL or missing references)
										//IL_008a: Unknown result type (might be due to invalid IL or missing references)
										if (!((ComponentBase<Component>)(object)<>8__1.CS$<>8__locals1.tex).IsDestroyed && !((ComponentBase<Component>)(object)<>8__1.CS$<>8__locals1.blur).IsDestroyed)
										{
											((SyncField<Uri>)(object)((StaticAssetProvider<Texture2D, BitmapMetadata, Texture2DVariantDescriptor>)(object)<>8__1.CS$<>8__locals1.tex).URL).Value = <>8__1.uri;
											((SyncRef<IAssetProvider<ITexture2D>>)(object)<>8__1.CS$<>8__locals1.blur.SpreadMagnitudeTexture).Target = (IAssetProvider<ITexture2D>)(object)<>8__1.CS$<>8__locals1.tex;
											((SyncField<float2>)(object)<>8__1.CS$<>8__locals1.blur.SpreadTextureScale).Value = float2.One;
											((SyncField<float2>)(object)<>8__1.CS$<>8__locals1.blur.SpreadTextureOffset).Value = float2.Zero;
										}
									});
									<>8__1 = null;
								}
							}
						}
						catch (global::System.Exception ex)
						{
							Msg("[TopBar] Blur mask generation failed: " + ex.Message);
						}
					}
					catch (global::System.Exception exception)
					{
						<>1__state = -2;
						((AsyncTaskMethodBuilder)(ref <>t__builder)).SetException(exception);
						return;
					}
					<>1__state = -2;
					((AsyncTaskMethodBuilder)(ref <>t__builder)).SetResult();
				}

				[DebuggerHidden]
				private void SetStateMachine(IAsyncStateMachine stateMachine)
				{
					((AsyncTaskMethodBuilder)(ref <>t__builder)).SetStateMachine(stateMachine);
				}
			}

			public byte[] data;

			public int texW;

			public int texH;

			public Engine engine;

			public StaticTexture2D tex;

			public BlurMaterial blur;

			[AsyncStateMachine(typeof(<<FinishStartStreaming>b__34>d))]
			internal global::System.Threading.Tasks.Task? <FinishStartStreaming>b__34()
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				<<FinishStartStreaming>b__34>d <<FinishStartStreaming>b__34>d = default(<<FinishStartStreaming>b__34>d);
				<<FinishStartStreaming>b__34>d.<>t__builder = AsyncTaskMethodBuilder.Create();
				<<FinishStartStreaming>b__34>d.<>4__this = this;
				<<FinishStartStreaming>b__34>d.<>1__state = -1;
				((AsyncTaskMethodBuilder)(ref <<FinishStartStreaming>b__34>d.<>t__builder)).Start<<<FinishStartStreaming>b__34>d>(ref <<FinishStartStreaming>b__34>d);
				return ((AsyncTaskMethodBuilder)(ref <<FinishStartStreaming>b__34>d.<>t__builder)).Task;
			}
		}

		[CompilerGenerated]
		private sealed class <>c__DisplayClass281_2
		{
			public Uri uri;

			public <>c__DisplayClass281_1 CS$<>8__locals1;

			internal void <FinishStartStreaming>b__35()
			{
				//IL_0070: Unknown result type (might be due to invalid IL or missing references)
				//IL_008a: Unknown result type (might be due to invalid IL or missing references)
				if (!((ComponentBase<Component>)(object)CS$<>8__locals1.tex).IsDestroyed && !((ComponentBase<Component>)(object)CS$<>8__locals1.blur).IsDestroyed)
				{
					((SyncField<Uri>)(object)((StaticAssetProvider<Texture2D, BitmapMetadata, Texture2DVariantDescriptor>)(object)CS$<>8__locals1.tex).URL).Value = uri;
					((SyncRef<IAssetProvider<ITexture2D>>)(object)CS$<>8__locals1.blur.SpreadMagnitudeTexture).Target = (IAssetProvider<ITexture2D>)(object)CS$<>8__locals1.tex;
					((SyncField<float2>)(object)CS$<>8__locals1.blur.SpreadTextureScale).Value = float2.One;
					((SyncField<float2>)(object)CS$<>8__locals1.blur.SpreadTextureOffset).Value = float2.Zero;
				}
			}
		}

		[CompilerGenerated]
		private sealed class <>c__DisplayClass384_0
		{
			[StructLayout((LayoutKind)3)]
			private struct <<UpdateSettingsBlurMask>b__0>d : IAsyncStateMachine
			{
				public int <>1__state;

				public AsyncTaskMethodBuilder <>t__builder;

				public <>c__DisplayClass384_0 <>4__this;

				private <>c__DisplayClass384_1 <>8__1;

				private ConfiguredTaskAwaiter<Uri> <>u__1;

				private void MoveNext()
				{
					//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
					//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
					//IL_00b4: 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_004c: Expected O, but got Unknown
					//IL_0069: 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_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_008c: Unknown result type (might be due to invalid IL or missing references)
					//IL_008e: Unknown result type (might be due to invalid IL or missing references)
					//IL_0104: Unknown result type (might be due to invalid IL or missing references)
					//IL_010e: Expected O, but got Unknown
					//IL_0109: Unknown result type (might be due to invalid IL or missing references)
					int num = <>1__state;
					<>c__DisplayClass384_0 <>c__DisplayClass384_ = <>4__this;
					try
					{
						try
						{
							ConfiguredTaskAwaiter<Uri> val2;
							if (num != 0)
							{
								<>8__1 = new <>c__DisplayClass384_1();
								<>8__1.CS$<>8__locals1 = <>c__DisplayClass384_;
								Bitmap2D val = new Bitmap2D(<>c__DisplayClass384_.data, <>c__DisplayClass384_.texW, <>c__DisplayClass384_.texH, (TextureFormat)18, false, (ColorProfile)0, false, (string)null);
								val2 = <>c__DisplayClass384_.engine.LocalDB.SaveAssetAsync(val, "webp", 2147483647, true).ConfigureAwait(false).GetAwaiter();
								if (!val2.IsCompleted)
								{
									num = (<>1__state = 0);
									<>u__1 = val2;
									((AsyncTaskMethodBuilder)(ref <>t__builder)).AwaitUnsafeOnCompleted<ConfiguredTaskAwaiter<Uri>, <<UpdateSettingsBlurMask>b__0>d>(ref val2, ref this);
									return;
								}
							}
							else
							{
								val2 = <>u__1;
								<>u__1 = default(ConfiguredTaskAwaiter<Uri>);
								num = (<>1__state = -1);
							}
							Uri result = val2.GetResult();
							<>8__1.uri = result;
							if (!(<>8__1.uri == (Uri)null))
							{
								((Worker)<>c__DisplayClass384_.tex).World.RunInUpdates(0, (Action)delegate
								{
									//IL_0070: Unknown result type (might be due to invalid IL or missing references)
									//IL_008a: Unknown result type (might be due to invalid IL or missing references)
									if (!((ComponentBase<Component>)(object)<>8__1.CS$<>8__locals1.tex).IsDestroyed && !((ComponentBase<Component>)(object)<>8__1.CS$<>8__locals1.blur).IsDestroyed)
									{
										((SyncField<Uri>)(object)((StaticAssetProvider<Texture2D, BitmapMetadata, Texture2DVariantDescriptor>)(object)<>8__1.CS$<>8__locals1.tex).URL).Value = <>8__1.uri;
										((SyncRef<IAssetProvider<ITexture2D>>)(object)<>8__1.CS$<>8__locals1.blur.SpreadMagnitudeTexture).Target = (IAssetProvider<ITexture2D>)(object)<>8__1.CS$<>8__locals1.tex;
										((SyncField<float2>)(object)<>8__1.CS$<>8__locals1.blur.SpreadTextureScale).Value = float2.One;
										((SyncField<float2>)(object)<>8__1.CS$<>8__locals1.blur.SpreadTextureOffset).Value = float2.Zero;
									}
								});
								<>8__1 = null;
							}
						}
						catch (global::System.Exception ex)
						{
							Msg("[Settings] Blur mask generation failed: " + ex.Message);
						}
					}
					catch (global::System.Exception exception)
					{
						<>1__state = -2;
						((AsyncTaskMethodBuilder)(ref <>t__builder)).SetException(exception);
						return;
					}
					<>1__state = -2;
					((AsyncTaskMethodBuilder)(ref <>t__builder)).SetResult();
				}

				[DebuggerHidden]
				private void SetStateMachine(IAsyncStateMachine stateMachine)
				{
					((AsyncTaskMethodBuilder)(ref <>t__builder)).SetStateMachine(stateMachine);
				}
			}

			public byte[] data;

			public int texW;

			public int texH;

			public Engine engine;

			public StaticTexture2D tex;

			public BlurMaterial blur;

			[AsyncStateMachine(typeof(<<UpdateSettingsBlurMask>b__0>d))]
			internal global::System.Threading.Tasks.Task? <UpdateSettingsBlurMask>b__0()
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				<<UpdateSettingsBlurMask>b__0>d <<UpdateSettingsBlurMask>b__0>d = default(<<UpdateSettingsBlurMask>b__0>d);
				<<UpdateSettingsBlurMask>b__0>d.<>t__builder = AsyncTaskMethodBuilder.Create();
				<<UpdateSettingsBlurMask>b__0>d.<>4__this = this;
				<<UpdateSettingsBlurMask>b__0>d.<>1__state = -1;
				((AsyncTaskMethodBuilder)(ref <<UpdateSettingsBlurMask>b__0>d.<>t__builder)).Start<<<UpdateSettingsBlurMask>b__0>d>(ref <<UpdateSettingsBlurMask>b__0>d);
				return ((AsyncTaskMethodBuilder)(ref <<UpdateSettingsBlurMask>b__0>d.<>t__builder)).Task;
			}
		}

		[CompilerGenerated]
		private sealed class <>c__DisplayClass384_1
		{
			public Uri uri;

			public <>c__DisplayClass384_0 CS$<>8__locals1;

			internal void <UpdateSettingsBlurMask>b__1()
			{
				//IL_0070: Unknown result type (might be due to invalid IL or missing references)
				//IL_008a: Unknown result type (might be due to invalid IL or missing references)
				if (!((ComponentBase<Component>)(object)CS$<>8__locals1.tex).IsDestroyed && !((ComponentBase<Component>)(object)CS$<>8__locals1.blur).IsDestroyed)
				{
					((SyncField<Uri>)(object)((StaticAssetProvider<Texture2D, BitmapMetadata, Texture2DVariantDescriptor>)(object)CS$<>8__locals1.tex).URL).Value = uri;
					((SyncRef<IAssetProvider<ITexture2D>>)(object)CS$<>8__locals1.blur.SpreadMagnitudeTexture).Target = (IAssetProvider<ITexture2D>)(object)CS$<>8__locals1.tex;
					((SyncField<float2>)(object)CS$<>8__locals1.blur.SpreadTextureScale).Value = float2.One;
					((SyncField<float2>)(object)CS$<>8__locals1.blur.SpreadTextureOffset).Value = float2.Zero;
				}
			}
		}

		[CompilerGenerated]
		private sealed class <>c__DisplayClass449_0
		{
			[StructLayout((LayoutKind)3)]
			private struct <<LoadViewerAvatarIcon>b__0>d : IAsyncStateMachine
			{
				public int <>1__state;

				public AsyncTaskMethodBuilder <>t__builder;

				public <>c__DisplayClass449_0 <>4__this;

				private <>c__DisplayClass449_1 <>8__1;

				private ConfiguredTaskAwaiter<CloudResult<User>> <>u__1;

				private void MoveNext()
				{
					//IL_0083: 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_008f: 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_004c: 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_0055: Unknown result type (might be due to invalid IL or missing references)
					//IL_0069: 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_00f9: Unknown result type (might be due to invalid IL or missing references)
					//IL_0103: Expected O, but got Unknown
					//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
					int num = <>1__state;
					<>c__DisplayClass449_0 <>c__DisplayClass449_ = <>4__this;
					try
					{
						try
						{
							ConfiguredTaskAwaiter<CloudResult<User>> val;
							if (num != 0)
							{
								<>8__1 = new <>c__DisplayClass449_1();
								<>8__1.CS$<>8__locals1 = <>c__DisplayClass449_;
								val = ((SkyFrostInterface)<>c__DisplayClass449_.engine.Cloud).Users.GetUserCached(<>c__DisplayClass449_.userId).ConfigureAwait(false).GetAwaiter();
								if (!val.IsCompleted)
								{
									num = (<>1__state = 0);
									<>u__1 = val;
									((AsyncTaskMethodBuilder)(ref <>t__builder)).AwaitUnsafeOnCompleted<ConfiguredTaskAwaiter<CloudResult<User>>, <<LoadViewerAvatarIcon>b__0>d>(ref val, ref this);
									return;
								}
							}
							else
							{
								val = <>u__1;
								<>u__1 = default(ConfiguredTaskAwaiter<CloudResult<User>>);
								num = (<>1__state = -1);
							}
							CloudResult<User> result = val.GetResult();
							if (result != null && ((CloudResult)result).IsOK)
							{
								User entity = result.Entity;
								object obj;
								if (entity == null)
								{
									obj = null;
								}
								else
								{
									UserProfile profile = entity.Profile;
									obj = ((profile != null) ? profile.IconUrl : null);
								}
								if (Uri.TryCreate((string)obj, (UriKind)1, ref <>8__1.iconUri))
								{
									<>c__DisplayClass449_.world.RunInUpdates(0, (Action)delegate
									{
										if (<>8__1.CS$<>8__locals1.avatarRoot != null && !((ContainerWorker<Component>)(object)<>8__1.CS$<>8__locals1.avatarRoot).IsDestroyed && <>8__1.CS$<>8__locals1.avatarTex != null && !((ComponentBase<Component>)(object)<>8__1.CS$<>8__locals1.avatarTex).IsDestroyed)
										{
											((SyncField<Uri>)(object)((StaticAssetProvider<Texture2D, BitmapMetadata, Texture2DVariantDescriptor>)(object)<>8__1.CS$<>8__locals1.avatarTex).URL).Value = <>8__1.iconUri;
										}
									});
									<>8__1 = null;
								}
							}
						}
						catch
						{
						}
					}
					catch (global::System.Exception exception)
					{
						<>1__state = -2;
						((AsyncTaskMethodBuilder)(ref <>t__builder)).SetException(exception);
						return;
					}
					<>1__state = -2;
					((AsyncTaskMethodBuilder)(ref <>t__builder)).SetResult();
				}

				[DebuggerHidden]
				private void SetStateMachine(IAsyncStateMachine stateMachine)
				{
					((AsyncTaskMethodBuilder)(ref <>t__builder)).SetStateMachine(stateMachine);
				}
			}

			public Engine engine;

			public string userId;

			public World world;

			public Slot avatarRoot;

			public StaticTexture2D avatarTex;

			[AsyncStateMachine(typeof(<<LoadViewerAvatarIcon>b__0>d))]
			internal global::System.Threading.Tasks.Task? <LoadViewerAvatarIcon>b__0()
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				<<LoadViewerAvatarIcon>b__0>d <<LoadViewerAvatarIcon>b__0>d = default(<<LoadViewerAvatarIcon>b__0>d);
				<<LoadViewerAvatarIcon>b__