Decompiled source of REPOCinema v0.9.1

REPOCinema.dll

Decompiled 9 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Photon.Pun;
using Photon.Realtime;
using REPOCinema.Core;
using Steamworks;
using Steamworks.Data;
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Networking;
using UnityEngine.Rendering;
using UnityEngine.Rendering.PostProcessing;
using UnityEngine.SceneManagement;
using UnityEngine.Video;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("REPOCinema")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.6.0.0")]
[assembly: AssemblyInformationalVersion("0.6.0")]
[assembly: AssemblyProduct("REPOCinema")]
[assembly: AssemblyTitle("REPOCinema")]
[assembly: AssemblyVersion("0.6.0.0")]
namespace REPOCinema
{
	internal sealed class CinemaAudioCapture : IDisposable
	{
		[ComVisible(true)]
		[ClassInterface(ClassInterfaceType.None)]
		private sealed class CompletionHandler : IActivateAudioInterfaceCompletionHandler, IAgileObject
		{
			public readonly ManualResetEvent Done = new ManualResetEvent(initialState: false);

			public int ActivateCompleted(IActivateAudioInterfaceAsyncOperation op)
			{
				Done.Set();
				return 0;
			}
		}

		private struct AUDIOCLIENT_ACTIVATION_PARAMS
		{
			public int ActivationType;

			public uint TargetProcessId;

			public int ProcessLoopbackMode;
		}

		[StructLayout(LayoutKind.Sequential, Pack = 2)]
		private struct WAVEFORMATEX
		{
			public ushort wFormatTag;

			public ushort nChannels;

			public int nSamplesPerSec;

			public int nAvgBytesPerSec;

			public ushort nBlockAlign;

			public ushort wBitsPerSample;

			public ushort cbSize;
		}

		[ComImport]
		[Guid("41D949AB-9862-444A-80F6-C261334DA5EB")]
		[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
		private interface IActivateAudioInterfaceCompletionHandler
		{
			[PreserveSig]
			int ActivateCompleted(IActivateAudioInterfaceAsyncOperation op);
		}

		[ComImport]
		[Guid("72A22D78-CDE4-431D-B8CC-843A71199B6D")]
		[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
		private interface IActivateAudioInterfaceAsyncOperation
		{
			void GetActivateResult(out int activateResult, [MarshalAs(UnmanagedType.IUnknown)] out object activatedInterface);
		}

		[ComImport]
		[Guid("94EA2B94-E9CC-49E0-C0FF-EE64CA8F5B90")]
		[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
		private interface IAgileObject
		{
		}

		[ComImport]
		[Guid("1CB9AD4C-DBFA-4C32-B178-C2F568A703B2")]
		[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
		private interface IAudioClient
		{
			[PreserveSig]
			int Initialize(int shareMode, uint streamFlags, long bufferDuration, long periodicity, ref WAVEFORMATEX format, IntPtr sessionGuid);

			[PreserveSig]
			int GetBufferSize(out uint frames);

			[PreserveSig]
			int GetStreamLatency(out long latency);

			[PreserveSig]
			int GetCurrentPadding(out uint frames);

			[PreserveSig]
			int IsFormatSupported(int shareMode, IntPtr format, out IntPtr closest);

			[PreserveSig]
			int GetMixFormat(out IntPtr format);

			[PreserveSig]
			int GetDevicePeriod(out long def, out long min);

			[PreserveSig]
			int Start();

			[PreserveSig]
			int Stop();

			[PreserveSig]
			int Reset();

			[PreserveSig]
			int SetEventHandle(IntPtr handle);

			[PreserveSig]
			int GetService(ref Guid iid, [MarshalAs(UnmanagedType.IUnknown)] out object service);
		}

		[ComImport]
		[Guid("C8ADBD64-E71E-48A0-A4DE-185C395CD317")]
		[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
		private interface IAudioCaptureClient
		{
			[PreserveSig]
			int GetBuffer(out IntPtr data, out uint frames, out uint flags, out ulong devicePosition, out ulong qpcPosition);

			[PreserveSig]
			int ReleaseBuffer(uint frames);

			[PreserveSig]
			int GetNextPacketSize(out uint frames);
		}

		public const int SampleRate = 48000;

		public const int Channels = 2;

		public const int BytesPerFrame = 4;

		private readonly uint _pid;

		private readonly byte[] _ring = new byte[384000];

		private int _write;

		private int _count;

		private readonly object _lock = new object();

		private Thread _thread;

		private volatile bool _running;

		private byte[] _scratch = new byte[0];

		private const string VIRTUAL_AUDIO_DEVICE_PROCESS_LOOPBACK = "VAD\\Process_Loopback";

		private const int AUDIOCLIENT_ACTIVATION_TYPE_PROCESS_LOOPBACK = 1;

		private const int PROCESS_LOOPBACK_MODE_INCLUDE_TARGET_PROCESS_TREE = 0;

		private const short VT_BLOB = 65;

		private const uint AUDCLNT_STREAMFLAGS_LOOPBACK = 131072u;

		private const uint AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM = 2147483648u;

		private const uint AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY = 134217728u;

		private const uint AUDCLNT_BUFFERFLAGS_SILENT = 2u;

		public string Error { get; private set; }

		public bool Running => _running;

		public CinemaAudioCapture(uint processId)
		{
			_pid = processId;
		}

		public void Start()
		{
			_running = true;
			_thread = new Thread(Loop)
			{
				IsBackground = true,
				Name = "REPOCinemaAudio"
			};
			_thread.Start();
		}

		public int Read(byte[] dst, int max)
		{
			lock (_lock)
			{
				int num = Math.Min(Math.Min(max, _count), dst.Length);
				num -= num % 4;
				int num2 = (_write - _count + _ring.Length) % _ring.Length;
				for (int i = 0; i < num; i++)
				{
					dst[i] = _ring[(num2 + i) % _ring.Length];
				}
				_count -= num;
				return num;
			}
		}

		private void Push(IntPtr data, int bytes, bool silent)
		{
			if (_scratch.Length < bytes)
			{
				_scratch = new byte[bytes];
			}
			if (silent)
			{
				Array.Clear(_scratch, 0, bytes);
			}
			else
			{
				Marshal.Copy(data, _scratch, 0, bytes);
			}
			lock (_lock)
			{
				for (int i = 0; i < bytes; i++)
				{
					_ring[_write] = _scratch[i];
					_write = (_write + 1) % _ring.Length;
				}
				_count = Math.Min(_count + bytes, _ring.Length);
			}
		}

		private void Loop()
		{
			IAudioClient audioClient = null;
			IAudioCaptureClient audioCaptureClient = null;
			try
			{
				audioClient = Activate(_pid);
				WAVEFORMATEX format = new WAVEFORMATEX
				{
					wFormatTag = 1,
					nChannels = 2,
					nSamplesPerSec = 48000,
					wBitsPerSample = 16,
					nBlockAlign = 4,
					nAvgBytesPerSec = 192000
				};
				Check(audioClient.Initialize(0, 2281832448u, 2000000L, 0L, ref format, IntPtr.Zero), "Initialize");
				Guid iid = typeof(IAudioCaptureClient).GUID;
				Check(audioClient.GetService(ref iid, out var service), "GetService");
				audioCaptureClient = (IAudioCaptureClient)service;
				Check(audioClient.Start(), "Start");
				REPOCinemaPlugin.Log.LogInfo((object)$"Stream audio capture started (process {_pid} and children).");
				while (_running)
				{
					Thread.Sleep(10);
					uint frames;
					while (audioCaptureClient.GetNextPacketSize(out frames) == 0 && frames != 0)
					{
						Check(audioCaptureClient.GetBuffer(out var data, out var frames2, out var flags, out var _, out var _), "GetBuffer");
						Push(data, (int)(frames2 * 4), (flags & 2) != 0);
						audioCaptureClient.ReleaseBuffer(frames2);
					}
				}
				audioClient.Stop();
			}
			catch (Exception ex)
			{
				Error = ex.Message;
				REPOCinemaPlugin.Log.LogWarning((object)("Stream audio unavailable (picture continues without sound): " + ex.Message));
			}
			finally
			{
				if (audioCaptureClient != null)
				{
					Marshal.ReleaseComObject(audioCaptureClient);
				}
				if (audioClient != null)
				{
					Marshal.ReleaseComObject(audioClient);
				}
				_running = false;
			}
		}

		public void Dispose()
		{
			_running = false;
			_thread?.Join(500);
		}

		private static IAudioClient Activate(uint pid)
		{
			int num = Marshal.SizeOf(typeof(AUDIOCLIENT_ACTIVATION_PARAMS));
			IntPtr intPtr = Marshal.AllocHGlobal(num);
			IntPtr intPtr2 = Marshal.AllocHGlobal(24);
			try
			{
				Marshal.StructureToPtr(new AUDIOCLIENT_ACTIVATION_PARAMS
				{
					ActivationType = 1,
					TargetProcessId = pid,
					ProcessLoopbackMode = 0
				}, intPtr, fDeleteOld: false);
				for (int i = 0; i < 24; i++)
				{
					Marshal.WriteByte(intPtr2, i, 0);
				}
				Marshal.WriteInt16(intPtr2, 0, 65);
				Marshal.WriteInt32(intPtr2, 8, num);
				Marshal.WriteIntPtr(intPtr2, 16, intPtr);
				CompletionHandler completionHandler = new CompletionHandler();
				Guid riid = typeof(IAudioClient).GUID;
				Check(ActivateAudioInterfaceAsync("VAD\\Process_Loopback", ref riid, intPtr2, completionHandler, out var activationOperation), "ActivateAudioInterfaceAsync");
				if (!completionHandler.Done.WaitOne(5000))
				{
					throw new TimeoutException("audio activation timed out");
				}
				activationOperation.GetActivateResult(out var activateResult, out var activatedInterface);
				Check(activateResult, "ActivateResult");
				return (IAudioClient)activatedInterface;
			}
			finally
			{
				Marshal.FreeHGlobal(intPtr2);
				Marshal.FreeHGlobal(intPtr);
			}
		}

		private static void Check(int hr, string what)
		{
			if (hr < 0)
			{
				throw new COMException($"{what} failed (0x{hr:X8})", hr);
			}
		}

		[DllImport("Mmdevapi.dll", ExactSpelling = true)]
		private static extern int ActivateAudioInterfaceAsync([MarshalAs(UnmanagedType.LPWStr)] string deviceInterfacePath, ref Guid riid, IntPtr activationParams, IActivateAudioInterfaceCompletionHandler completionHandler, out IActivateAudioInterfaceAsyncOperation activationOperation);

		[DllImport("user32.dll")]
		public static extern uint GetWindowThreadProcessId(IntPtr hwnd, out uint pid);
	}
	internal sealed class CinemaAudioPlayer
	{
		internal sealed class Tap : MonoBehaviour
		{
			public volatile CinemaAudioPlayer Player;

			public double Step = 1.0;

			private void OnAudioFilterRead(float[] data, int channels)
			{
				CinemaAudioPlayer player = Player;
				if (player == null)
				{
					Array.Clear(data, 0, data.Length);
				}
				else
				{
					player.Fill(data, channels, Step);
				}
			}
		}

		private const int InRate = 48000;

		private const int TargetFrames = 3840;

		private const int MaxFrames = 12000;

		private readonly float[] _ring = new float[192000];

		private int _write;

		private double _read;

		private int _count;

		private bool _primed;

		private readonly object _lock = new object();

		private AudioSource _source;

		private AudioClip _ones;

		private Tap _tap;

		public void Attach(AudioSource source)
		{
			if (!((Object)(object)_source == (Object)(object)source) || !((Object)(object)_tap != (Object)null))
			{
				Detach();
				_source = source;
				int outputSampleRate = AudioSettings.outputSampleRate;
				_ones = AudioClip.Create("REPOCinemaStreamCarrier", outputSampleRate, 1, outputSampleRate, false);
				float[] array = new float[outputSampleRate];
				for (int i = 0; i < array.Length; i++)
				{
					array[i] = 1f;
				}
				_ones.SetData(array, 0);
				_tap = ((Component)source).gameObject.GetComponent<Tap>() ?? ((Component)source).gameObject.AddComponent<Tap>();
				_tap.Player = this;
				_tap.Step = 48000.0 / (double)outputSampleRate;
				source.clip = _ones;
				source.loop = true;
				source.Play();
			}
		}

		public void Detach()
		{
			if ((Object)(object)_tap != (Object)null)
			{
				_tap.Player = null;
			}
			if ((Object)(object)_source != (Object)null && (Object)(object)_source.clip == (Object)(object)_ones)
			{
				_source.Stop();
				_source.clip = null;
			}
			if ((Object)(object)_ones != (Object)null)
			{
				Object.Destroy((Object)(object)_ones);
			}
			_ones = null;
			_source = null;
			_tap = null;
			lock (_lock)
			{
				_count = 0;
				_primed = false;
			}
		}

		public void Push(byte[] pcm, int offset, int length)
		{
			int num = length / 4;
			int num2 = _ring.Length / 2;
			lock (_lock)
			{
				for (int i = 0; i < num; i++)
				{
					int num3 = offset + i * 4;
					_ring[_write * 2] = (float)(short)(pcm[num3] | (pcm[num3 + 1] << 8)) / 32768f;
					_ring[_write * 2 + 1] = (float)(short)(pcm[num3 + 2] | (pcm[num3 + 3] << 8)) / 32768f;
					_write = (_write + 1) % num2;
				}
				_count = Math.Min(_count + num, num2 - 1);
				if (_count > 12000)
				{
					_count = 3840;
				}
				_read = (_write - _count + num2) % num2;
			}
		}

		private void Fill(float[] data, int channels, double step)
		{
			int num = _ring.Length / 2;
			lock (_lock)
			{
				if (!_primed && _count >= 3840)
				{
					_primed = true;
				}
				for (int i = 0; i < data.Length; i += channels)
				{
					float num2 = 0f;
					float num3 = 0f;
					if (_primed && _count > 1)
					{
						int num4 = (int)_read;
						int num5 = (num4 + 1) % num;
						float num6 = (float)(_read - (double)num4);
						num2 = _ring[num4 * 2] + (_ring[num5 * 2] - _ring[num4 * 2]) * num6;
						num3 = _ring[num4 * 2 + 1] + (_ring[num5 * 2 + 1] - _ring[num4 * 2 + 1]) * num6;
						double num7 = _read + step;
						int num8 = (int)num7 - num4;
						_read = num7 % (double)num;
						_count -= num8;
					}
					if (channels == 1)
					{
						data[i] *= (num2 + num3) * 0.5f;
						continue;
					}
					data[i] *= num2;
					data[i + 1] *= num3;
					for (int j = 2; j < channels; j++)
					{
						data[i + j] *= (num2 + num3) * 0.5f;
					}
				}
				if (_count <= 1)
				{
					_primed = false;
				}
			}
		}
	}
	internal static class CinemaBackgroundLimit
	{
		private static bool _active;

		private static int _prevTarget;

		private static int _prevVsync;

		public static void Apply(bool showRunning)
		{
			int value = REPOCinemaPlugin.BackgroundFps.Value;
			bool flag = showRunning && !Application.isFocused && value > 0;
			if (flag != _active)
			{
				if (flag)
				{
					_prevTarget = Application.targetFrameRate;
					_prevVsync = QualitySettings.vSyncCount;
					QualitySettings.vSyncCount = 0;
					Application.targetFrameRate = value;
					REPOCinemaPlugin.Log.LogInfo((object)$"Game in background during a show: frame rate capped at {value}.");
				}
				else
				{
					QualitySettings.vSyncCount = _prevVsync;
					Application.targetFrameRate = _prevTarget;
					REPOCinemaPlugin.Log.LogInfo((object)"Frame-rate cap removed.");
				}
				_active = flag;
			}
		}
	}
	public class CinemaController : MonoBehaviour
	{
		private CinemaNetwork _net;

		private CinemaPlayback _playback;

		private bool _open;

		private string _url = "";

		private string _localError = "";

		private CursorLockMode _prevLock;

		private bool _prevVisible;

		private Rect _window = new Rect(40f, 40f, 760f, 600f);

		private const float WindowHeight = 600f;

		private const float ViewerWidth = 440f;

		private const float ViewerHeight = 560f;

		private static GUISkin _darkSkin;

		private float _pendingInches = -1f;

		private float _pendingAt = float.MaxValue;

		private float _pendingZone = -1f;

		private float _pendingZoneAt = float.MaxValue;

		private readonly CinemaUrlValidator _validator = new CinemaUrlValidator();

		public CinemaShow Show;

		private const float WindowWidth = 760f;

		private const string UrlField = "REPOCinemaUrl";

		private static readonly List<InputKey> NoKeys = new List<InputKey>();

		private bool _carrying;

		private float _carryDist;

		private float _carryInches;

		private float _carryLift;

		private Vector3 _carryPos;

		private float _carryYaw;

		private const float MaxLift = 4f;

		private GUIStyle _carryStyle;

		private bool _hintShown;

		private float _hintUntil;

		private float _bannerUntil;

		private const float BannerSeconds = 8f;

		private GUIStyle _bannerStyle;

		private GUIStyle _bannerSubStyle;

		private string _seat = "";

		private string _entered = "";

		private Texture2D _bannerFrame;

		public CinemaFun Fun;

		private int _section;

		private static readonly string[] Sections = new string[6] { "Playback", "Stream", "Screen", "Show", "Audience", "People" };

		private GUIStyle _side;

		private GUIStyle _sideOn;

		private GUIStyle _head;

		private GUIStyle _hint;

		private GUIStyle _on;

		private GUIStyle _off;

		private Vector2 _scroll;

		private const float PanelHeight = 430f;

		private Vector2 _viewerScroll;

		private string _title = "";

		private string _lastFocus = "";

		private string _nowTitle;

		private string _announce = "";

		private int _breakMinutes = 5;

		private readonly string[] _voteTitles = new string[3] { "", "", "" };

		private readonly string[] _voteUrls = new string[3] { "", "", "" };

		private string _quizQ = "";

		private readonly string[] _quizA = new string[3] { "", "", "" };

		private int _quizCorrect;

		private int _quizSeconds = 20;

		private bool _pickingWindow;

		private List<KeyValuePair<IntPtr, string>> _windows;

		private Vector2 _windowScroll;

		public static bool PanelOpen { get; private set; }

		private static KeyCode MenuKey
		{
			get
			{
				//IL_0017: 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)
				if (!CinemaIdentity.LocalIsOwner)
				{
					return REPOCinemaPlugin.ViewerMenuKey.Value;
				}
				return REPOCinemaPlugin.PanelKey.Value;
			}
		}

		private static string ViewerHint => "In the outlined zone in front of the screen: hold Space to float up, Ctrl to go down.\nReact or vote: keys 1-4 (or [ ] ; ').   Your menu: " + ((object)REPOCinemaPlugin.ViewerMenuKey.Value/*cast due to .constrained prefix*/).ToString();

		private static GUISkin DarkSkin()
		{
			//IL_0027: 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_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Expected O, but got Unknown
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: 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_013d: 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_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_darkSkin != (Object)null)
			{
				return _darkSkin;
			}
			Texture2D val = Tex(new Color(0.09f, 0.09f, 0.11f, 0.97f));
			Texture2D val2 = Tex(new Color(0.15f, 0.15f, 0.18f));
			Texture2D val3 = Tex(new Color(0.21f, 0.21f, 0.26f));
			Texture2D val4 = Tex(new Color(0.06f, 0.06f, 0.08f));
			Texture2D val5 = Tex(new Color(0.85f, 0.65f, 0.1f));
			Color val6 = default(Color);
			((Color)(ref val6))..ctor(0.9f, 0.9f, 0.92f);
			GUISkin val7 = Object.Instantiate<GUISkin>(GUI.skin);
			((Object)val7).hideFlags = (HideFlags)61;
			Flat(val7.window, val, val, val6);
			val7.window.onNormal.background = val;
			val7.window.padding = new RectOffset(10, 10, 26, 10);
			Flat(val7.box, val2, val2, val6);
			Flat(val7.button, val2, val3, val6);
			Flat(val7.textField, val4, val4, Color.white);
			Flat(val7.textArea, val4, val4, Color.white);
			val7.settings.cursorColor = new Color(1f, 0.8f, 0.2f);
			val7.settings.selectionColor = new Color(0.85f, 0.65f, 0.1f, 0.4f);
			Flat(val7.label, null, null, val6);
			val7.label.normal.background = null;
			GUIStyleState[] array = (GUIStyleState[])(object)new GUIStyleState[3]
			{
				val7.label.hover,
				val7.label.active,
				val7.label.focused
			};
			for (int i = 0; i < array.Length; i++)
			{
				array[i].background = null;
			}
			Flat(val7.horizontalSlider, val4, val4, val6);
			Flat(val7.horizontalSliderThumb, val5, val5, val6);
			Flat(val7.verticalScrollbar, val4, val4, val6);
			Flat(val7.verticalScrollbarThumb, val3, val3, val6);
			Flat(val7.horizontalScrollbar, val4, val4, val6);
			Flat(val7.horizontalScrollbarThumb, val3, val3, val6);
			val7.scrollView.normal.background = null;
			array = (GUIStyleState[])(object)new GUIStyleState[8]
			{
				val7.toggle.normal,
				val7.toggle.hover,
				val7.toggle.active,
				val7.toggle.focused,
				val7.toggle.onNormal,
				val7.toggle.onHover,
				val7.toggle.onActive,
				val7.toggle.onFocused
			};
			for (int i = 0; i < array.Length; i++)
			{
				array[i].textColor = val6;
			}
			return _darkSkin = val7;
			static void Flat(GUIStyle st, Texture2D normal, Texture2D over, Color fg)
			{
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_0048: Unknown result type (might be due to invalid IL or missing references)
				//IL_0095: Unknown result type (might be due to invalid IL or missing references)
				st.normal.background = normal;
				st.normal.textColor = fg;
				GUIStyleState[] array2 = (GUIStyleState[])(object)new GUIStyleState[3] { st.hover, st.active, st.focused };
				foreach (GUIStyleState obj in array2)
				{
					obj.background = over;
					obj.textColor = Color.white;
				}
				array2 = (GUIStyleState[])(object)new GUIStyleState[4] { st.onNormal, st.onHover, st.onActive, st.onFocused };
				foreach (GUIStyleState obj2 in array2)
				{
					obj2.background = over;
					obj2.textColor = Color.white;
				}
			}
			static Texture2D Tex(Color c)
			{
				//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)
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				//IL_001f: Expected O, but got Unknown
				Texture2D val8 = new Texture2D(1, 1)
				{
					hideFlags = (HideFlags)61
				};
				val8.SetPixel(0, 0, c);
				val8.Apply();
				return val8;
			}
		}

		public void Init(CinemaNetwork net, CinemaPlayback playback)
		{
			_net = net;
			_playback = playback;
			_net.StateChanged += _playback.Apply;
		}

		private void Update()
		{
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			if (!CinemaIdentity.LocalIsOwner)
			{
				if (!_net.InRoom)
				{
					_hintShown = false;
				}
				else if (!_hintShown && _net.HostIsOwner && _net.Gate.Current != null)
				{
					_hintShown = true;
					_bannerUntil = Time.unscaledTime + 8f;
					_hintUntil = _bannerUntil + 12f;
				}
			}
			if (Input.GetKeyDown(MenuKey))
			{
				SetOpen(!_open);
			}
			if (_open && Input.GetKeyDown((KeyCode)27))
			{
				SetOpen(open: false);
			}
			if (_net.CanControl && Input.GetKeyDown(REPOCinemaPlugin.PlaceKey.Value))
			{
				if (_carrying)
				{
					DropScreen();
				}
				else if ((Object)(object)_playback.TvTransform == (Object)null)
				{
					PlaceTv();
				}
				else
				{
					StartCarry();
				}
			}
			if (_carrying)
			{
				UpdateCarry();
			}
			if (_pendingInches > 0f && Time.unscaledTime - _pendingAt > 0.3f && _net.CanControl)
			{
				CinemaState current = _net.Current;
				CinemaState cinemaState = CinemaCommands.Resize(current, _pendingInches);
				if (cinemaState != current)
				{
					_net.Publish(cinemaState);
				}
				_pendingAt = float.MaxValue;
			}
			if (_pendingZone > 0f && Time.unscaledTime - _pendingZoneAt > 0.3f && _net.CanControl)
			{
				CinemaState current2 = _net.Current;
				CinemaState cinemaState2 = CinemaCommands.SetZone(current2, _pendingZone);
				if (cinemaState2 != current2)
				{
					_net.Publish(cinemaState2);
				}
				_pendingZoneAt = float.MaxValue;
			}
			if (!_open && _pendingZoneAt == float.MaxValue)
			{
				_pendingZone = -1f;
			}
			if (!_open && _pendingAt == float.MaxValue)
			{
				_pendingInches = -1f;
			}
			if (_open)
			{
				Cursor.lockState = (CursorLockMode)0;
				Cursor.visible = true;
				BlockGameInput();
			}
		}

		private static void BlockGameInput()
		{
			InputManager instance = InputManager.instance;
			if (!((Object)(object)instance == (Object)null))
			{
				instance.DisableMovement(0.2f);
				instance.DisableAiming(0.2f);
				instance.DisableControlsExcept(0.2f, NoKeys);
			}
		}

		private void SetOpen(bool open)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			if (open != _open)
			{
				_open = open;
				PanelOpen = open;
				if (open)
				{
					_prevLock = Cursor.lockState;
					_prevVisible = Cursor.visible;
				}
				else
				{
					Cursor.lockState = _prevLock;
					Cursor.visible = _prevVisible;
					GUIUtility.keyboardControl = 0;
				}
			}
		}

		private void PlaceTv()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			Camera main = Camera.main;
			if (!((Object)(object)main == (Object)null))
			{
				Vector3 val = Vector3.ProjectOnPlane(((Component)main).transform.forward, Vector3.up);
				Vector3 normalized = ((Vector3)(ref val)).normalized;
				Vector3 val2 = ((Component)main).transform.position + normalized * 4f;
				RaycastHit val3 = default(RaycastHit);
				if (Physics.Raycast(val2 + Vector3.up, Vector3.down, ref val3, 10f))
				{
					val2 = ((RaycastHit)(ref val3)).point;
				}
				CinemaState cinemaState = _net.Current.Clone();
				cinemaState.Revision++;
				float[] obj = new float[5] { val2.x, val2.y, val2.z, 0f, 0f };
				Quaternion val4 = Quaternion.LookRotation(normalized);
				obj[3] = ((Quaternion)(ref val4)).eulerAngles.y;
				obj[4] = cinemaState.TvPose[4];
				cinemaState.TvPose = obj;
				_net.Publish(cinemaState);
			}
		}

		private void StartCarry()
		{
			//IL_003c: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			Camera main = Camera.main;
			Transform tvTransform = _playback.TvTransform;
			if (!((Object)(object)main == (Object)null) && !((Object)(object)tvTransform == (Object)null))
			{
				if (_open)
				{
					SetOpen(open: false);
				}
				_carrying = true;
				Vector3 val = Vector3.ProjectOnPlane(tvTransform.position - ((Component)main).transform.position, Vector3.up);
				_carryDist = Mathf.Clamp(((Vector3)(ref val)).magnitude, 2f, 40f);
				_carryInches = _net.Current.TvPose[4];
				RaycastHit val2 = default(RaycastHit);
				_carryLift = (Physics.Raycast(tvTransform.position + Vector3.up * 3f, Vector3.down, ref val2, 10f) ? Mathf.Clamp(tvTransform.position.y - ((RaycastHit)(ref val2)).point.y, -4f, 4f) : 0f);
			}
		}

		private void UpdateCarry()
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			Camera main = Camera.main;
			if ((Object)(object)main == (Object)null || (Object)(object)_playback.TvTransform == (Object)null || !_net.CanControl)
			{
				CancelCarry();
				return;
			}
			if (Input.GetKeyDown((KeyCode)27) || Input.GetMouseButtonDown(1))
			{
				CancelCarry();
				return;
			}
			if (Input.GetMouseButtonDown(0))
			{
				DropScreen();
				return;
			}
			float y = Input.mouseScrollDelta.y;
			if (y != 0f)
			{
				if (Input.GetKey((KeyCode)308) || Input.GetKey((KeyCode)307))
				{
					_carryLift = Mathf.Clamp(_carryLift + y * 0.1f, -4f, 4f);
				}
				else if (Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303))
				{
					_carryDist = Mathf.Clamp(_carryDist + y * 0.5f, 2f, 40f);
				}
				else
				{
					_carryInches = Mathf.Clamp(Mathf.Round(_carryInches * (1f + 0.1f * Mathf.Sign(y))), 24f, 600f);
				}
			}
			Vector3 val = Vector3.ProjectOnPlane(((Component)main).transform.forward, Vector3.up);
			Vector3 normalized = ((Vector3)(ref val)).normalized;
			if (!(((Vector3)(ref normalized)).sqrMagnitude < 0.01f))
			{
				Vector3 val2 = ((Component)main).transform.position + normalized * _carryDist;
				RaycastHit val3 = default(RaycastHit);
				if (Physics.Raycast(val2 + Vector3.up, Vector3.down, ref val3, 10f))
				{
					val2 = ((RaycastHit)(ref val3)).point;
				}
				else
				{
					val2.y = ((Component)main).transform.position.y - 1.5f;
				}
				if (Input.GetKey((KeyCode)280))
				{
					_carryLift = Mathf.Min(4f, _carryLift + Time.unscaledDeltaTime);
				}
				if (Input.GetKey((KeyCode)281))
				{
					_carryLift = Mathf.Max(-4f, _carryLift - Time.unscaledDeltaTime);
				}
				val2.y += _carryLift;
				_carryPos = val2;
				Quaternion val4 = Quaternion.LookRotation(normalized);
				_carryYaw = ((Quaternion)(ref val4)).eulerAngles.y;
				_playback.PreviewPose(_carryPos, _carryYaw, _carryInches);
			}
		}

		private void DropScreen()
		{
			_carrying = false;
			CinemaState cinemaState = CinemaCommands.Move(_net.Current, _carryPos.x, _carryPos.y, _carryPos.z, _carryYaw);
			cinemaState.TvPose[4] = _carryInches;
			_net.Publish(cinemaState);
			_pendingInches = -1f;
		}

		private void CancelCarry()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			_carrying = false;
			float[] tvPose = _net.Current.TvPose;
			_playback.PreviewPose(new Vector3(tvPose[0], tvPose[1], tvPose[2]), tvPose[3], tvPose[4]);
		}

		private void DrawCarryHint()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			GUI.Box(new Rect((float)Screen.width / 2f - 340f, (float)(Screen.height - 120), 680f, 60f), $"<b>Moving the screen</b>  ({_carryInches:0}\", height {_carryLift:+0.0;-0.0;0} m)\nScroll: size   Shift+Scroll: distance   Alt+Scroll or PgUp/PgDn: height   Click/{REPOCinemaPlugin.PlaceKey.Value}: drop   Right-click/Esc: cancel", _carryStyle);
		}

		private void DrawBanner()
		{
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: 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_001b: 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_003d: Expected O, but got Unknown
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Expected O, but got Unknown
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_034f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0374: Unknown result type (might be due to invalid IL or missing references)
			//IL_0394: Unknown result type (might be due to invalid IL or missing references)
			//IL_0410: Unknown result type (might be due to invalid IL or missing references)
			//IL_0470: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0517: Unknown result type (might be due to invalid IL or missing references)
			//IL_056c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0660: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_06e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0736: Unknown result type (might be due to invalid IL or missing references)
			//IL_0780: Unknown result type (might be due to invalid IL or missing references)
			//IL_0787: Unknown result type (might be due to invalid IL or missing references)
			//IL_078e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0799: Unknown result type (might be due to invalid IL or missing references)
			//IL_0828: Unknown result type (might be due to invalid IL or missing references)
			//IL_0804: Unknown result type (might be due to invalid IL or missing references)
			if (_bannerStyle == null)
			{
				_bannerStyle = new GUIStyle(GUI.skin.label)
				{
					fontSize = 46,
					fontStyle = (FontStyle)1,
					alignment = (TextAnchor)4,
					richText = true
				};
				_bannerSubStyle = new GUIStyle(_bannerStyle)
				{
					fontSize = 18,
					fontStyle = (FontStyle)0
				};
				_bannerFrame = new Texture2D(1, 1);
				_bannerFrame.SetPixel(0, 0, Color.white);
				_bannerFrame.Apply();
				Random random = new Random();
				_seat = $"Row {(char)(65 + random.Next(8))}  Seat {random.Next(1, 21)}";
				_entered = DateTime.Now.ToString("HH:mm");
			}
			float unscaledTime = Time.unscaledTime;
			float num = _bannerUntil - unscaledTime;
			float num2 = 8f - num;
			float num3 = Mathf.Clamp01(Mathf.Min(num2, num) / 0.6f);
			float num4 = (1f - Mathf.Clamp01(num2 / 0.6f)) * -50f;
			Color color = GUI.color;
			float num5 = Screen.width;
			float num6 = Mathf.Min(760f, num5 - 40f);
			Rect val = default(Rect);
			((Rect)(ref val))..ctor((num5 - num6) / 2f, (float)Screen.height * 0.16f + num4, num6, 210f);
			float num7 = 170f;
			Rect val2 = default(Rect);
			((Rect)(ref val2))..ctor(((Rect)(ref val)).x, ((Rect)(ref val)).y, ((Rect)(ref val)).width - num7, ((Rect)(ref val)).height);
			Rect val3 = default(Rect);
			((Rect)(ref val3))..ctor(((Rect)(ref val2)).xMax, ((Rect)(ref val)).y, num7, ((Rect)(ref val)).height);
			string myTitle = CinemaWelcome.MyTitle;
			Color val4 = ((myTitle.Length > 0) ? new Color(0.68f, 0.4f, 1f, num3) : new Color(1f, 0.82f, 0.25f, num3));
			string text = ((myTitle.Length > 0) ? "#B57BFF" : "#FFD700");
			GUI.color = new Color(0.06f, 0.05f, 0.1f, 0.9f * num3);
			GUI.DrawTexture(val2, (Texture)(object)_bannerFrame);
			GUI.color = new Color(0.1f, 0.08f, 0.15f, 0.9f * num3);
			GUI.DrawTexture(val3, (Texture)(object)_bannerFrame);
			GUI.color = val4;
			GUI.DrawTexture(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y, ((Rect)(ref val)).width, 4f), (Texture)(object)_bannerFrame);
			GUI.DrawTexture(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).yMax - 4f, ((Rect)(ref val)).width, 4f), (Texture)(object)_bannerFrame);
			for (float num8 = ((Rect)(ref val)).y + 10f; num8 < ((Rect)(ref val)).yMax - 10f; num8 += 14f)
			{
				GUI.DrawTexture(new Rect(((Rect)(ref val3)).x - 1f, num8, 2f, 7f), (Texture)(object)_bannerFrame);
			}
			float num9 = Mathf.Repeat(unscaledTime * 0.45f, 1f) * (((Rect)(ref val)).width - 140f);
			GUI.color = new Color(1f, 1f, 1f, 0.75f * num3);
			GUI.DrawTexture(new Rect(((Rect)(ref val)).x + num9, ((Rect)(ref val)).y, 140f, 4f), (Texture)(object)_bannerFrame);
			GUI.color = new Color(1f, 1f, 1f, num3);
			string text2 = ((_net.Gate.Current != null && _net.Gate.Current.RoomName.Length > 0) ? _net.Gate.Current.RoomName : REPOCinemaPlugin.RoomName.Value);
			GUI.Label(new Rect(((Rect)(ref val2)).x, ((Rect)(ref val2)).y + 14f, ((Rect)(ref val2)).width, 26f), "<color=" + text + "><b>A D M I T   O N E</b></color>   <size=15>" + Greeting() + ",</size>", _bannerSubStyle);
			GUI.Label(new Rect(((Rect)(ref val2)).x, ((Rect)(ref val2)).y + 42f, ((Rect)(ref val2)).width, 60f), CinemaText.Colorize(PlayerName(), CinemaText.VipPalette, (int)(unscaledTime * 8f)), _bannerStyle);
			if (myTitle.Length > 0)
			{
				Rect val5 = new Rect(((Rect)(ref val2)).x + ((Rect)(ref val2)).width / 2f - 90f, ((Rect)(ref val2)).y + 104f, 180f, 26f);
				GUI.color = new Color(0.45f, 0.2f, 0.8f, 0.95f * num3);
				GUI.DrawTexture(val5, (Texture)(object)_bannerFrame);
				GUI.color = new Color(1f, 1f, 1f, num3);
				GUI.Label(val5, "<b>" + myTitle + "</b>", _bannerSubStyle);
			}
			GUI.Label(new Rect(((Rect)(ref val2)).x, ((Rect)(ref val2)).y + (float)((myTitle.Length > 0) ? 136 : 112), ((Rect)(ref val2)).width, 32f), "<size=24>Welcome to <b><color=" + text + ">" + text2 + "</color></b> Room</size>", _bannerSubStyle);
			string text3 = ((_net.Gate.Current != null && _net.Gate.Current.NowPlaying.Length > 0 && _playback.ContentShowing) ? ("<color=" + text + ">Now playing:</color> <b>" + _net.Gate.Current.NowPlaying + "</b>") : "Enjoy the show");
			GUI.Label(new Rect(((Rect)(ref val2)).x, ((Rect)(ref val2)).y + (float)((myTitle.Length > 0) ? 170 : 154), ((Rect)(ref val2)).width, 26f), "<size=15>" + text3 + "</size>", _bannerSubStyle);
			GUI.Label(new Rect(((Rect)(ref val3)).x, ((Rect)(ref val3)).y + 22f, ((Rect)(ref val3)).width, 24f), "<color=" + text + "><b>REPO CINEMA</b></color>", _bannerSubStyle);
			GUI.Label(new Rect(((Rect)(ref val3)).x, ((Rect)(ref val3)).y + 70f, ((Rect)(ref val3)).width, 50f), "<size=15>" + _seat.Replace("  ", "\n") + "</size>", _bannerSubStyle);
			GUI.Label(new Rect(((Rect)(ref val3)).x, ((Rect)(ref val3)).y + 140f, ((Rect)(ref val3)).width, 44f), "<size=13>Entry</size>\n<b>" + _entered + "</b>", _bannerSubStyle);
			for (int i = 0; i < 12; i++)
			{
				float num10 = Mathf.Abs(Mathf.Sin(unscaledTime * 2.2f + (float)i * 1.7f));
				GUI.color = new Color(val4.r, val4.g, val4.b, num10 * num3);
				GUI.Label(new Rect(((Rect)(ref val)).x + ((float)(i % 6) + 0.5f) / 6f * ((Rect)(ref val)).width + Mathf.Sin((float)i * 3.1f) * 25f - 10f, (i < 6) ? (((Rect)(ref val)).y - 20f) : ((Rect)(ref val)).yMax, 20f, 20f), "<size=16>*</size>", _bannerSubStyle);
			}
			GUI.color = color;
		}

		private static string Greeting()
		{
			int hour = DateTime.Now.Hour;
			if (hour < 5 || hour >= 12)
			{
				if (hour < 12 || hour >= 18)
				{
					return "Good evening";
				}
				return "Good afternoon";
			}
			return "Good morning";
		}

		private static string PlayerName()
		{
			try
			{
				string name = SteamClient.Name;
				if (!string.IsNullOrEmpty(name))
				{
					return name.Replace("<", "").Replace(">", "").Trim();
				}
			}
			catch (Exception)
			{
			}
			return "Movie fan";
		}

		private void OnGUI()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: 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_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Expected O, but got Unknown
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Expected O, but got Unknown
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			if (_carrying)
			{
				if (_carryStyle == null)
				{
					_carryStyle = new GUIStyle(GUI.skin.box)
					{
						richText = true,
						fontSize = 14,
						alignment = (TextAnchor)4
					};
					_carryStyle.normal.textColor = Color.white;
				}
				DrawCarryHint();
			}
			if (Time.unscaledTime < _bannerUntil)
			{
				DrawBanner();
			}
			else if (Time.unscaledTime < _hintUntil)
			{
				GUIStyle val = new GUIStyle(GUI.skin.box)
				{
					fontSize = 22,
					alignment = (TextAnchor)4,
					wordWrap = true
				};
				float num = Mathf.Min(720f, (float)Screen.width - 40f);
				GUI.Box(new Rect(((float)Screen.width - num) / 2f, 60f, num, 150f), ViewerHint, val);
			}
			if (!_open)
			{
				return;
			}
			GUISkin skin = GUI.skin;
			GUI.skin = DarkSkin();
			int num2;
			float num3;
			if (!_net.CanControl)
			{
				if ((Object)(object)Show != (Object)null)
				{
					num2 = ((!Show.IsHelper) ? 1 : 0);
					if (num2 == 0)
					{
						goto IL_012c;
					}
				}
				else
				{
					num2 = 1;
				}
				num3 = 440f;
				goto IL_0138;
			}
			num2 = 0;
			goto IL_012c;
			IL_0138:
			float num4 = num3;
			float num5 = ((num2 != 0) ? 560f : 600f);
			((Rect)(ref _window)).width = num4;
			((Rect)(ref _window)).height = num5;
			_window = GUILayout.Window(24257, _window, new WindowFunction(DrawWindow), "REPO Cinema", (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(num4),
				GUILayout.Height(num5)
			});
			GUI.skin = skin;
			return;
			IL_012c:
			num3 = 760f;
			goto IL_0138;
		}

		private void EnsureStyles()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: 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_0043: Expected O, but got Unknown
			//IL_0048: Expected O, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: 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_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Expected O, but got Unknown
			//IL_011e: 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_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Expected O, but got Unknown
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Expected O, but got Unknown
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Expected O, but got Unknown
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_0263: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Expected O, but got Unknown
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
			if (_side == null)
			{
				_side = new GUIStyle(GUI.skin.button)
				{
					alignment = (TextAnchor)3,
					fontSize = 14,
					fixedHeight = 34f,
					padding = new RectOffset(12, 6, 4, 4)
				};
				_side.normal.background = Tex(new Color(0.13f, 0.13f, 0.16f));
				_side.normal.textColor = new Color(0.8f, 0.8f, 0.85f);
				_side.hover.background = Tex(new Color(0.2f, 0.2f, 0.25f));
				_side.hover.textColor = Color.white;
				Calm(_side, _side.hover.background, Color.white);
				_sideOn = new GUIStyle(_side);
				_sideOn.normal.background = Tex(new Color(0.85f, 0.65f, 0.1f));
				_sideOn.normal.textColor = Color.black;
				_sideOn.fontStyle = (FontStyle)1;
				Calm(_sideOn, _sideOn.normal.background, Color.black);
				_head = new GUIStyle(GUI.skin.label)
				{
					fontSize = 18,
					fontStyle = (FontStyle)1,
					richText = true
				};
				_hint = new GUIStyle(GUI.skin.label)
				{
					fontSize = 11,
					wordWrap = true,
					richText = true
				};
				_hint.normal.textColor = new Color(0.7f, 0.7f, 0.75f);
				_on = new GUIStyle(GUI.skin.button)
				{
					fontStyle = (FontStyle)1,
					fixedWidth = 52f
				};
				_on.normal.background = Tex(new Color(0.15f, 0.6f, 0.25f));
				_on.normal.textColor = Color.white;
				Calm(_on, _on.normal.background, Color.white);
				_off = new GUIStyle(_on);
				_off.normal.background = Tex(new Color(0.45f, 0.15f, 0.15f));
				Calm(_off, _off.normal.background, Color.white);
			}
			static Texture2D Tex(Color c)
			{
				//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)
				//IL_000a: 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)
				//IL_0017: Expected O, but got Unknown
				Texture2D val = new Texture2D(1, 1);
				val.SetPixel(0, 0, c);
				val.Apply();
				return val;
			}
		}

		private static void Calm(GUIStyle st, Texture2D bg, Color text)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			GUIStyleState[] array = (GUIStyleState[])(object)new GUIStyleState[7] { st.hover, st.active, st.focused, st.onNormal, st.onHover, st.onActive, st.onFocused };
			foreach (GUIStyleState obj in array)
			{
				obj.background = bg;
				obj.textColor = text;
			}
		}

		private bool Switch(CinemaState s, CinemaFeature f, string label, string hint)
		{
			bool flag = s.Has(f);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (GUILayout.Button(flag ? "ON" : "OFF", flag ? _on : _off, Array.Empty<GUILayoutOption>()))
			{
				_net.Publish(CinemaCommands.SetFeature(_net.Current, f, !flag));
			}
			GUILayout.Label("<b>" + label + "</b>", _head, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(200f) });
			GUILayout.Label(hint, _hint, Array.Empty<GUILayoutOption>());
			GUILayout.EndHorizontal();
			return flag;
		}

		private void DrawWindow(int id)
		{
			//IL_0252: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_030c: Unknown result type (might be due to invalid IL or missing references)
			//IL_031b: Unknown result type (might be due to invalid IL or missing references)
			//IL_032a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0362: Unknown result type (might be due to invalid IL or missing references)
			//IL_0369: Invalid comparison between Unknown and I4
			//IL_039e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a4: Invalid comparison between Unknown and I4
			EnsureStyles();
			bool canControl = _net.CanControl;
			bool flag = !canControl && (Object)(object)Show != (Object)null && Show.IsHelper;
			CinemaState current = _net.Current;
			double now = (_net.Active ? CinemaNetwork.Now : 0.0);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("<b>" + _playback.Status + "</b>   " + Fmt(_playback.Time) + " / " + Fmt(_playback.Duration) + (((Object)(object)_playback.Stream != (Object)null && _playback.Stream.Hosting) ? ("   |   " + _playback.Stream.Status) : ""), _hint, Array.Empty<GUILayoutOption>());
			GUILayout.EndHorizontal();
			string text = ((_localError.Length > 0) ? _localError : _playback.Error);
			if (text.Length > 0)
			{
				GUILayout.Label("<color=#ff6060>" + ((text.Length > 200) ? (text.Substring(0, 200) + "...") : text) + "</color>", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(740f) });
			}
			if (!canControl && !flag)
			{
				DrawViewer(current);
				GUI.DragWindow();
				return;
			}
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(130f) });
			for (int i = 0; i < Sections.Length; i++)
			{
				if ((!flag || i == 0) && GUILayout.Button(Sections[i], (i == _section) ? _sideOn : _side, Array.Empty<GUILayoutOption>()))
				{
					_section = i;
				}
			}
			GUILayout.FlexibleSpace();
			if (GUILayout.Button("Close", _side, Array.Empty<GUILayoutOption>()))
			{
				SetOpen(open: false);
			}
			GUILayout.EndVertical();
			GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
			_scroll = GUILayout.BeginScrollView(_scroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(430f) });
			if (flag)
			{
				GUILayout.Label("<color=#FFD700>You are a host helper: you can control playback.</color>", _hint, Array.Empty<GUILayoutOption>());
				_section = 0;
			}
			switch (_section)
			{
			case 0:
				DrawPlayback(current, canControl);
				break;
			case 1:
				DrawStreamSection(current, now);
				break;
			case 2:
				DrawScreen(current);
				break;
			case 3:
				DrawShowSection(current, now);
				break;
			case 4:
				DrawAudience(current);
				break;
			case 5:
				DrawPeople(current);
				break;
			}
			GUILayout.EndScrollView();
			GUILayout.EndVertical();
			GUILayout.EndHorizontal();
			GUILayout.Label($"<size=11>Keys: {REPOCinemaPlugin.PanelKey.Value} panel  |  {REPOCinemaPlugin.PlaceKey.Value} place TV  |  {REPOCinemaPlugin.RemoteKey.Value} remote</size>", _hint, Array.Empty<GUILayoutOption>());
			if ((canControl || flag) && _section == 0)
			{
				string nameOfFocusedControl = GUI.GetNameOfFocusedControl();
				if ((int)Event.current.type == 12 && _lastFocus == "REPOCinemaUrl" && nameOfFocusedControl.Length == 0 && GUIUtility.keyboardControl == 0)
				{
					GUI.FocusControl("REPOCinemaUrl");
				}
				else if ((int)Event.current.type == 7)
				{
					_lastFocus = nameOfFocusedControl;
				}
			}
			GUI.DragWindow();
		}

		private void DrawLocal()
		{
			REPOCinemaPlugin.CinemaMode.Value = GUILayout.Toggle(REPOCinemaPlugin.CinemaMode.Value, " Cinema mode: clean, full-resolution picture while watching (this PC)", Array.Empty<GUILayoutOption>());
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Volume (this PC)", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(120f) });
			REPOCinemaPlugin.Volume.Value = GUILayout.HorizontalSlider(REPOCinemaPlugin.Volume.Value, 0f, 2f, Array.Empty<GUILayoutOption>());
			GUILayout.Label($"{REPOCinemaPlugin.Volume.Value * 100f:0}%", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(44f) });
			GUILayout.EndHorizontal();
		}

		private void DrawViewer(CinemaState s)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0433: Unknown result type (might be due to invalid IL or missing references)
			//IL_043a: Unknown result type (might be due to invalid IL or missing references)
			//IL_043f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0485: Unknown result type (might be due to invalid IL or missing references)
			_viewerScroll = GUILayout.BeginScrollView(_viewerScroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(470f) });
			if (!_net.InRoom)
			{
				GUILayout.Label("Join the host's lobby to watch.", _hint, Array.Empty<GUILayoutOption>());
			}
			else if (s.NowPlaying.Length > 0 && _playback.ContentShowing)
			{
				GUILayout.Label("<b>Now playing:</b> " + s.NowPlaying, _hint, Array.Empty<GUILayoutOption>());
			}
			GUILayout.Label("<b>Sound and picture</b>", _head, Array.Empty<GUILayoutOption>());
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("TV volume", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(110f) });
			REPOCinemaPlugin.Volume.Value = GUILayout.HorizontalSlider(REPOCinemaPlugin.Volume.Value, 0f, 2f, Array.Empty<GUILayoutOption>());
			GUILayout.Label($"{REPOCinemaPlugin.Volume.Value * 100f:0}%", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(44f) });
			GUILayout.EndHorizontal();
			REPOCinemaPlugin.CinemaMode.Value = GUILayout.Toggle(REPOCinemaPlugin.CinemaMode.Value, " Cinema mode (clean, sharp picture near the TV)", Array.Empty<GUILayoutOption>());
			REPOCinemaPlugin.CountdownBeep.Value = GUILayout.Toggle(REPOCinemaPlugin.CountdownBeep.Value, " Countdown beeps", Array.Empty<GUILayoutOption>());
			GUILayout.Space(6f);
			GUILayout.Label("<b>Floating</b>", _head, Array.Empty<GUILayoutOption>());
			REPOCinemaPlugin.FloatSeats.Value = GUILayout.Toggle(REPOCinemaPlugin.FloatSeats.Value, " Float in the zone in front of the screen (Space up, Ctrl down)", Array.Empty<GUILayoutOption>());
			if ((Object)(object)Show != (Object)null && Show.VoteOpen)
			{
				GUILayout.Space(6f);
				GUILayout.Label("<b>Vote for the next film</b>", _head, Array.Empty<GUILayoutOption>());
				for (int i = 0; i < s.VoteTitles.Length; i++)
				{
					if (GUILayout.Button(((Show.MyVote == i) ? "> " : "") + $"{i + 1}. {s.VoteTitles[i]}  ({s.VoteCounts[i]})", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }))
					{
						Show.Vote(i);
					}
				}
			}
			if ((Object)(object)Fun != (Object)null && Fun.QuizOpen)
			{
				GUILayout.Space(6f);
				GUILayout.Label("<b>Quiz:</b> " + s.QuizQuestion, _head, Array.Empty<GUILayoutOption>());
				for (int j = 0; j < s.QuizAnswers.Length; j++)
				{
					GUI.enabled = Fun.MyAnswer < 0;
					if (GUILayout.Button(((Fun.MyAnswer == j) ? "> " : "") + $"{j + 1}. {s.QuizAnswers[j]}", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }))
					{
						Fun.Answer(j);
					}
					GUI.enabled = true;
				}
			}
			if ((Object)(object)Show != (Object)null && Show.CanReact)
			{
				GUILayout.Space(6f);
				GUILayout.Label("<b>React</b>  <size=11>(or keys 1-4)</size>", _head, Array.Empty<GUILayoutOption>());
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				string[] array = new string[4] { "LOL", "<3", "WOW", "GG" };
				for (int k = 0; k < 4; k++)
				{
					if (GUILayout.Button(array[k], (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(34f) }))
					{
						Show.React(k);
					}
				}
				GUILayout.EndHorizontal();
			}
			GUILayout.Space(6f);
			GUILayout.Label("<b>Menu key</b>", _head, Array.Empty<GUILayoutOption>());
			for (int l = 0; l < 2; l++)
			{
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				for (int m = l * 5 + 1; m <= l * 5 + 5; m++)
				{
					KeyCode val = (KeyCode)(282 + m - 1);
					bool flag = REPOCinemaPlugin.ViewerMenuKey.Value == val;
					if (GUILayout.Toggle(flag, "F" + m, GUI.skin.button, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(26f) }) && !flag)
					{
						REPOCinemaPlugin.ViewerMenuKey.Value = val;
					}
				}
				GUILayout.EndHorizontal();
			}
			GUILayout.Space(6f);
			GUILayout.Label("<b>On my screen</b>", _head, Array.Empty<GUILayoutOption>());
			REPOCinemaPlugin.ShowReactions.Value = GUILayout.Toggle(REPOCinemaPlugin.ShowReactions.Value, " Show other players' reactions", Array.Empty<GUILayoutOption>());
			REPOCinemaPlugin.ShowEmojiRain.Value = GUILayout.Toggle(REPOCinemaPlugin.ShowEmojiRain.Value, " Show emoji rain", Array.Empty<GUILayoutOption>());
			GUILayout.EndScrollView();
			if (GUILayout.Button("Close", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }))
			{
				SetOpen(open: false);
			}
		}

		private void DrawNowTitle(CinemaState s)
		{
			GUILayout.Label("<b>What's playing</b>  <size=11>(shown on the welcome ticket)</size>", _head, Array.Empty<GUILayoutOption>());
			if (_nowTitle == null)
			{
				_nowTitle = s.NowPlaying;
			}
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			_nowTitle = GUILayout.TextField(_nowTitle, 64, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(410f) });
			if (GUILayout.Button((GUI.enabled = (_nowTitle ?? "").Trim() != s.NowPlaying) ? "Save" : "Saved", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) }))
			{
				_net.Publish(CinemaCommands.SetNowPlaying(_net.Current, _nowTitle));
			}
			GUI.enabled = s.NowPlaying.Length > 0;
			if (GUILayout.Button("Clear", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(55f) }))
			{
				_nowTitle = "";
				_net.Publish(CinemaCommands.SetNowPlaying(_net.Current, ""));
			}
			GUI.enabled = true;
			GUILayout.EndHorizontal();
			GUILayout.Space(8f);
		}

		private void DrawPlayback(CinemaState s, bool host)
		{
			if (host)
			{
				DrawNowTitle(s);
			}
			GUILayout.Label("<b>Video link</b>", _head, Array.Empty<GUILayoutOption>());
			GUILayout.Label("Direct HTTPS .mp4/.webm link (H.264 + AAC recommended).", _hint, Array.Empty<GUILayoutOption>());
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUI.SetNextControlName("REPOCinemaUrl");
			_url = GUILayout.TextField(_url, 2048, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(470f) });
			if (GUILayout.Button("Paste", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(55f) }))
			{
				_url = (GUIUtility.systemCopyBuffer ?? "").Trim();
			}
			if (GUILayout.Button("Clear", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) }))
			{
				_url = "";
				_localError = "";
			}
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("Load", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }))
			{
				UrlCheck urlCheck = _validator.ValidateSyntax(_url);
				_localError = (urlCheck.Ok ? "" : urlCheck.Error);
				if (urlCheck.Ok)
				{
					if (host && s.TvPose[0] == 0f && s.TvPose[1] == 0f && s.TvPose[2] == 0f)
					{
						PlaceTv();
					}
					Show.Command(CinemaShow.Cmd.Load, urlCheck.Uri.AbsoluteUri);
				}
			}
			if (GUILayout.Button((s.Status == PlaybackStatus.Playing) ? "Pause" : "Play", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }))
			{
				Show.Command((s.Status == PlaybackStatus.Playing) ? CinemaShow.Cmd.Pause : CinemaShow.Cmd.Play);
			}
			if (GUILayout.Button("Stop", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }))
			{
				Show.Command(CinemaShow.Cmd.Stop);
			}
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			int[] array = new int[4] { -30, -10, 10, 30 };
			for (int i = 0; i < array.Length; i++)
			{
				int num = array[i];
				if (GUILayout.Button(((num > 0) ? "+" : "") + num + "s", Array.Empty<GUILayoutOption>()))
				{
					Show.Command(CinemaShow.Cmd.Seek, "", num);
				}
			}
			GUILayout.EndHorizontal();
			if (!host)
			{
				return;
			}
			GUILayout.Space(8f);
			if (Switch(s, CinemaFeature.NowPlaying, "Now playing", "Film title shown in cinema style when the show starts."))
			{
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				if (_title.Length == 0 && s.NowPlaying.Length > 0)
				{
					_title = s.NowPlaying;
				}
				_title = GUILayout.TextField(_title, 64, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(470f) });
				if (GUILayout.Button("Show title now", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(130f) }))
				{
					_net.Publish(CinemaCommands.ShowTitle(_net.Current, _title, CinemaNetwork.Now));
					_nowTitle = null;
				}
				GUILayout.EndHorizontal();
			}
			GUILayout.Space(8f);
			if (GUILayout.Button("Place TV in front of me", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(28f) }))
			{
				PlaceTv();
			}
		}

		private void DrawScreen(CinemaState s)
		{
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.Label("<b>Screen and room</b>", _head, Array.Empty<GUILayoutOption>());
			if (_pendingInches < 0f)
			{
				_pendingInches = s.TvPose[4];
			}
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label($"Screen size: {_pendingInches:0}\"", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(140f) });
			float num = Mathf.Round(GUILayout.HorizontalSlider(_pendingInches, 24f, 600f, Array.Empty<GUILayoutOption>()));
			if (num != _pendingInches)
			{
				_pendingInches = num;
				_pendingAt = Time.unscaledTime;
			}
			GUILayout.EndHorizontal();
			if (_pendingZone < 0f)
			{
				_pendingZone = s.ZoneSize;
			}
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label($"Float zone: {_pendingZone:0} m", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(140f) });
			float num2 = Mathf.Round(GUILayout.HorizontalSlider(_pendingZone, 4f, 60f, Array.Empty<GUILayoutOption>()));
			if (num2 != _pendingZone)
			{
				_pendingZone = num2;
				_pendingZoneAt = Time.unscaledTime;
			}
			GUILayout.EndHorizontal();
			GUILayout.Space(4f);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (GUILayout.Button(((Object)(object)_playback.TvTransform == (Object)null) ? "Place screen here" : $"Move screen ({REPOCinemaPlugin.PlaceKey.Value})", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(26f) }))
			{
				if ((Object)(object)_playback.TvTransform == (Object)null)
				{
					PlaceTv();
				}
				else
				{
					StartCarry();
				}
			}
			GUI.enabled = (Object)(object)_playback.TvTransform != (Object)null;
			if (GUILayout.Button("Remove screen", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(26f) }))
			{
				_net.Publish(CinemaCommands.RemoveScreen(_net.Current, CinemaNetwork.Now));
			}
			GUI.enabled = true;
			GUILayout.EndHorizontal();
			GUILayout.Space(6f);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (GUILayout.Button(s.DimLights ? "ON" : "OFF", s.DimLights ? _on : _off, Array.Empty<GUILayoutOption>()))
			{
				_net.Publish(CinemaCommands.SetDim(_net.Current, !s.DimLights));
			}
			GUILayout.Label("<b>Dim the lights</b>", _head, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(200f) });
			GUILayout.Label("Lights near the TV go dark during shows.", _hint, Array.Empty<GUILayoutOption>());
			GUILayout.EndHorizontal();
			if (Switch(s, CinemaFeature.Spotlight, "Host spotlight", "A warm spotlight follows you during shows."))
			{
				GUILayout.Space(2f);
			}
			GUILayout.Space(10f);
			GUILayout.Label("<b>This PC only</b>", _head, Array.Empty<GUILayoutOption>());
			DrawLocal();
		}

		private void DrawShowSection(CinemaState s, double now)
		{
			if (Switch(s, CinemaFeature.Countdown, "Countdown", "Big countdown with beeps before a film or stream."))
			{
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.Label($"{REPOCinemaPlugin.CountdownSeconds.Value} seconds", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(120f) });
				REPOCinemaPlugin.CountdownSeconds.Value = Mathf.RoundToInt(GUILayout.HorizontalSlider((float)REPOCinemaPlugin.CountdownSeconds.Value, 3f, 30f, Array.Empty<GUILayoutOption>()));
				GUILayout.EndHorizontal();
			}
			GUILayout.Space(8f);
			if (Switch(s, CinemaFeature.Intermission, "Intermission", "Pause for a break with a timer; the film resumes by itself."))
			{
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.Label($"{_breakMinutes} min", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) });
				_breakMinutes = Mathf.RoundToInt(GUILayout.HorizontalSlider((float)_breakMinutes, 1f, 20f, Array.Empty<GUILayoutOption>()));
				if (s.IntermissionUntil > now)
				{
					if (GUILayout.Button("End break now", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(130f) }))
					{
						_net.Publish(CinemaCommands.EndIntermission(_net.Current, now));
					}
				}
				else if (GUILayout.Button("Start break", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(130f) }))
				{
					_net.Publish(CinemaCommands.StartIntermission(_net.Current, now, _breakMinutes));
				}
				GUILayout.EndHorizontal();
			}
			GUILayout.Space(8f);
			if (Switch(s, CinemaFeature.Announcements, "Announcements", "A message in the middle of everyone's screen for 8 s."))
			{
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				_announce = GUILayout.TextField(_announce, 120, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(470f) });
				if (GUILayout.Button("Send", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) }) && _announce.Trim().Length > 0)
				{
					_net.Publish(CinemaCommands.Announce(_net.Current, _announce, now, 8.0));
				}
				GUILayout.EndHorizontal();
			}
			GUILayout.Space(8f);
			if (Switch(s, CinemaFeature.Stats, "Show stats", "After a show of 1+ min: viewers, reactions, top reactor.") && GUILayout.Button("Show stats now", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(160f) }))
			{
				Fun.PublishStats();
			}
		}

		private void DrawAudience(CinemaState s)
		{
			Switch(s, CinemaFeature.Reactions, "Reactions", "Viewers press 1-4 (or [ ] ; ') : LOL, <3, WOW, GG on screen.");
			Switch(s, CinemaFeature.EmojiRain, "Emoji rain", "3 matching reactions within 2.5 s make it rain.");
			GUILayout.Space(8f);
			bool flag = s.VoteTitles.Length != 0 || s.QuizQuestion.Length > 0;
			if (Switch(s, CinemaFeature.Vote, "Film vote", "2-3 films; viewers vote with 1-3; the winner plays."))
			{
				for (int i = 0; i < 3; i++)
				{
					GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
					GUILayout.Label($"{i + 1}.", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(18f) });
					_voteTitles[i] = GUILayout.TextField(_voteTitles[i], 32, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) });
					_voteUrls[i] = GUILayout.TextField(_voteUrls[i], 2048, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(320f) });
					if (GUILayout.Button("Paste", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(55f) }))
					{
						_voteUrls[i] = (GUIUtility.systemCopyBuffer ?? "").Trim();
					}
					GUILayout.EndHorizontal();
				}
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				if (s.VoteTitles.Length != 0)
				{
					if (GUILayout.Button("Cancel vote", Array.Empty<GUILayoutOption>()))
					{
						_net.Publish(CinemaCommands.EndVote(s));
					}
				}
				else if (!flag && GUILayout.Button($"Start vote ({REPOCinemaPlugin.VoteSeconds.Value} s)", Array.Empty<GUILayoutOption>()))
				{
					List<string> list = new List<string>();
					List<string> list2 = new List<string>();
					for (int j = 0; j < 3; j++)
					{
						if (_voteTitles[j].Trim().Length != 0 && _voteUrls[j].Trim().Length != 0)
						{
							UrlCheck urlCheck = _validator.ValidateSyntax(_voteUrls[j]);
							if (!urlCheck.Ok)
							{
								_localError = $"Vote link {j + 1}: {urlCheck.Error}";
								list.Clear();
								break;
							}
							list.Add(_voteTitles[j]);
							list2.Add(urlCheck.Uri.AbsoluteUri);
						}
					}
					if (list.Count >= 2)
					{
						_localError = "";
						Show.StartVote(list.ToArray(), list2.ToArray());
					}
					else if (_localError.Length == 0)
					{
						_localError = "Fill in at least 2 films (name + link).";
					}
				}
				GUILayout.EndHorizontal();
			}
			GUILayout.Space(8f);
			if (!Switch(s, CinemaFeature.Quiz, "Quiz", "A question with 2-3 answers; points for correct answers."))
			{
				return;
			}
			_quizQ = GUILayout.TextField(_quizQ, 120, Array.Empty<GUILayoutOption>());
			for (int k = 0; k < 3; k++)
			{
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				if (GUILayout.Toggle(_quizCorrect == k, (k == _quizCorrect) ? " correct" : "", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) }))
				{
					_quizCorrect = k;
				}
				_quizA[k] = GUILayout.TextField(_quizA[k], 32, Array.Empty<GUILayoutOption>());
				GUILayout.EndHorizontal();
			}
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label($"{_quizSeconds} s", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) });
			_quizSeconds = Mathf.RoundToInt(GUILayout.HorizontalSlider((float)_quizSeconds, 10f, 60f, Array.Empty<GUILayoutOption>()));
			if (s.QuizQuestion.Length > 0)
			{
				if (GUILayout.Button("Cancel quiz", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(120f) }))
				{
					_net.Publish(CinemaCommands.EndQuiz(s));
				}
			}
			else if (!flag && GUILayout.Button("Ask", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(120f) }))
			{
				string[] array = _quizA.Where((string a) => a.Trim().Length > 0).ToArray();
				if (_quizQ.Trim().Length == 0 || array.Length < 2 || _quizA[_quizCorrect].Trim().Length == 0)
				{
					_localError = "Quiz: a question, 2+ answers and the correct one marked.";
				}
				else
				{
					_localError = "";
					int correct = Array.IndexOf(array, _quizA[_quizCorrect]);
					Fun.StartQuiz(_quizQ, array, correct, _quizSeconds);
				}
			}
			if (GUILayout.Button("Reset scores", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(110f) }))
			{
				Fun.ResetScores();
			}
			GUILayout.EndHorizontal();
		}

		private void DrawPeople(CinemaState s)
		{
			GUILayout.Label("<b>Welcome</b>", _head, Array.Empty<GUILayoutOption>());
			REPOCinemaPlugin.WelcomeEnabled.Value = GUILayout.Toggle(REPOCinemaPlugin.WelcomeEnabled.Value, " Welcome line in chat (players without the mod, again after 1 h away)", Array.Empty<GUILayoutOption>());
			REPOCinemaPlugin.ChatInvite.Value = GUILayout.Toggle(REPOCinemaPlugin.ChatInvite.Value, " Cinema invite in chat during shows", Array.Empty<GUILayoutOption>());
			GUILayout.Space(10f);
			GUILayout.Label("<b>Host helpers</b>", _head, Array.Empty<GUILayoutOption>());
			GUILayout.Label("Ticked players can control playback (not streaming or settings).", _hint, Array.Empty<GUILayoutOption>());
			List<string> list = new List<string>(s.Helpers);
			foreach (PlayerAvatar item in SemiFunc.PlayerGetAll())
			{
				if ((Object)(object)item == (Object)null || (Object)(object)item.photonView == (Object)null || item.photonView.IsMine)
				{
					continue;
				}
				string text = CinemaIdentity.SteamIdOfActor(item.photonView.OwnerActorNr);
				if (text == null)
				{
					continue;
				}
				bool flag = list.Contains(text);
				Player owner = item.photonView.Owner;
				string text2 = ((owner != null) ? owner.NickName : null) ?? text;
				if (GUILayout.Toggle(flag, " " + text2, Array.Empty<GUILayoutOption>()) != flag)
				{
					if (flag)
					{
						list.Remove(text);
					}
					else
					{
						list.Add(text);
					}
					_net.Publish(CinemaCommands.SetHelpers(_net.Current, list.ToArray()));
					break;
				}
			}
		}

		private void DrawStreamSection(CinemaState s, double now)
		{
			//IL_0242: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			CinemaStream stream = _playback.Stream;
			if ((Object)(object)stream == (Object)null)
			{
				return;
			}
			DrawNowTitle(s);
			GUILayout.Label("Live screen stream (picture + the window's sound):", Array.Empty<GUILayoutOption>());
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Quality:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) });
			int[] array = new int[4] { 540, 720, 1080, 1440 };
			for (int i = 0; i < array.Length; i++)
			{
				int num = array[i];
				string text = ((num == 1440) ? "2K" : (num + "p"));
				bool flag = REPOCinemaPlugin.StreamHeight.Value == num;
				if (GUILayout.Toggle(flag, text, GUI.skin.button, Array.Empty<GUILayoutOption>()) && !flag)
				{
					REPOCinemaPlugin.StreamHeight.Value = num;
					if (stream.Hosting)
					{
						stream.RestartHost();
					}
				}
			}
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Frames:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) });
			array = new int[2] { 30, 60 };
			for (int i = 0; i < array.Length; i++)
			{
				int num2 = array[i];
				bool flag2 = REPOCinemaPlugin.StreamFps.Value == num2;
				if (GUILayout.Toggle(flag2, num2 + " fps", GUI.skin.button, Array.Empty<GUILayoutOption>()) && !flag2)
				{
					REPOCinemaPlugin.StreamFps.Value = num2;
					if (stream.Hosting)
					{
						stream.RestartHost();
					}
				}
			}
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (!stream.Hosting)
			{
				if (GUILayout.Button(_pickingWindow ? "Cancel" : "Stream a window...", Array.Empty<GUILayoutOption>()))
				{
					_pickingWindow = !_pickingWindow;
					if (_pickingWindow)
					{
						_windows = CinemaWindowCapture.ListWindows();
					}
				}
			}
			else if (GUILayout.Button("Stop stream", Array.Empty<GUILayoutOption>()))
			{
				_net.Publish(CinemaCommands.Stop(s, now));
				stream.StopAll();
			}
			GUILayout.Label(stream.Status, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(580f) });
			GUILayout.EndHorizontal();
			if (!_pickingWindow || _windows == null)
			{
				return;
			}
			_windowScroll = GUILayout.BeginScrollView(_windowScroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(140f) });
			foreach (KeyValuePair<IntPtr, string> window in _windows)
			{
				string text2 = ((window.Value.Length > 60) ? (window.Value.Substring(0, 60) + "...") : window.Value);
				if (GUILayout.Button(text2, Array.Empty<GUILayoutOption>()))
				{
					_pickingWindow = false;
					if (s.TvPose[0] == 0f && s.TvPose[1] == 0f && s.TvPose[2] == 0f)
					{
						PlaceTv();
						s = _net.Current;
					}
					if (stream.StartHost(window.Key, text2))
					{
						_net.Publish(CinemaCommands.StartStream(s, now, s.Has(CinemaFeature.Countdown) ? REPOCinemaPlugin.CountdownSeconds.Value : 0));
					}
					break;
				}
			}
			GUILayout.EndScrollView();
		}

		private static string Fmt(double t)
		{
			if (!(t <= 0.0))
			{
				return $"{(int)t / 60:00}:{(int)t % 60:00}";
			}
			return "--:--";
		}
	}
	internal sealed class CinemaDesktopDuplication : IDisposable
	{
		private struct D3D11_BOX
		{
			public uint left;

			public uint top;

			public uint front;

			public uint right;

			public uint bottom;

			public uint back;
		}

		private struct D3D11_MAPPED_SUBRESOURCE
		{
			public IntPtr pData;

			public uint RowPitch;

			public uint DepthPitch;
		}

		private struct D3D11_TEXTURE2D_DESC
		{
			public uint Width;

			public uint Height;

			public uint MipLevels;

			public uint ArraySize;

			public int Format;

			public uint SampleCount;

			public uint SampleQuality;

			public int Usage;

			public uint BindFlags;

			public uint CPUAccessFlags;

			public uint MiscFlags;
		}

		[UnmanagedFunctionPointer(CallingConvention.StdCall)]
		private delegate int QI(IntPtr self, ref Guid iid, out IntPtr obj);

		[UnmanagedFunctionPointer(CallingConvention.StdCall)]
		private delegate uint ReleaseFn(IntPtr self);

		[UnmanagedFunctionPointer(CallingConvention.StdCall)]
		private delegate int GetAdapterFn(IntPtr self, out IntPtr adapter);

		[UnmanagedFunctionPointer(CallingConvention.StdCall)]
		private delegate int EnumOutputsFn(IntPtr self, uint index, out IntPtr output);

		[UnmanagedFunctionPointer(CallingConvention.StdCall)]
		private delegate int GetDescFn(IntPtr self, IntPtr desc);

		[UnmanagedFunctionPointer(CallingConvention.StdCall)]
		private delegate int DuplicateOutputFn(IntPtr self, IntPtr device, out IntPtr dup);

		[UnmanagedFunctionPointer(CallingConvention.StdCall)]
		private delegate int AcquireNextFrameFn(IntPtr self, uint timeoutMs, IntPtr frameInfo, out IntPtr resource);

		[UnmanagedFunctionPointer(CallingConvention.StdCall)]
		private delegate int ReleaseFrameFn(IntPtr self);

		[UnmanagedFunctionPointer(CallingConvention.StdCall)]
		private delegate int CreateTexture2DFn(IntPtr self, ref D3D11_TEXTURE2D_DESC desc, IntPtr init, out IntPtr tex);

		[UnmanagedFunctionPointer(CallingConvention.StdCall)]
		private delegate void CopySubresourceRegionFn(IntPtr ctx, IntPtr dst, uint dstSub, uint x, uint y, uint z, IntPtr src, uint srcSub, ref D3D11_BOX box);

		[UnmanagedFunctionPointer(CallingConvention.StdCall)]
		private delegate int MapFn(IntPtr ctx, IntPtr res, uint sub, int mapType, uint flags, out D3D11_MAPPED_SUBRESOURCE mapped);

		[UnmanagedFunctionPointer(CallingConvention.StdCall)]
		private delegate void UnmapFn(IntPtr ctx, IntPtr res, uint sub);

		private IntPtr _device;

		private IntPtr _context;

		private IntPtr _output;

		private IntPtr _dup;

		private IntPtr _staging;

		private int _outLeft;

		private int _outTop;

		private int _outRight;

		private int _outBottom;

		private int _stagingW;

		private int _stagingH;

		private byte[] _last;

		private int _lastW;

		private int _lastH;

		private const int DXGI_ERROR_WAIT_TIMEOUT = -2005270489;

		public bool Covers(int x, int y)
		{
			if (_dup != IntPtr.Zero && x >= _outLeft && x < _outRight && y >= _outTop)
			{
				return y < _outBottom;
			}
			return false;
		}

		public void Open(int x, int y)
		{
			Close();
			Check(D3D11CreateDevice(IntPtr.Zero, 1, IntPtr.Zero, 32u, IntPtr.Zero, 0u, 7u, out _device, out var _, out _context), "D3D11CreateDevice");
			Guid iid = new Guid("54ec77fa-1377-44e6-8c32-88fd5f44c84c");
			Check(Fn<QI>(_device, 0)(_device, ref iid, out var obj), "QI IDXGIDevice");
			try
			{
				Check(Fn<GetAdapterFn>(obj, 7)(obj, out var adapter), "GetAdapter");
				try
				{
					IntPtr intPtr = Marshal.AllocHGlobal(128);
					try
					{
						IntPtr output;
						for (uint num = 0u; Fn<EnumOutputsFn>(adapter, 7)(adapter, num, out output) >= 0; num++)
						{
							Check(Fn<GetDescFn>(output, 7)(output, intPtr), "Output.GetDesc");
							int num2 = Marshal.ReadInt32(intPtr, 64);
							int num3 = Marshal.ReadInt32(intPtr, 68);
							int num4 = Marshal.ReadInt32(intPtr, 72);
							int num5 = Marshal.ReadInt32(intPtr, 76);
							if (x >= num2 && x < num4 && y >= num3 && y < num5)
							{
								_output = output;
								_outLeft = num2;
								_outTop = num3;
								_outRight = num4;
								_outBottom = num5;
								break;
							}
							Release(output);
						}
					}
					finally
					{
						Marshal.FreeHGlobal(intPtr);
					}
				}
				finally
				{
					Release(adapter);
				}
			}
			finally
			{
				Release(obj);
			}
			if (_output == IntPtr.Zero)
			{
				throw new InvalidOperationException("window is not on a monitor of the main GPU");
			}
			Guid iid2 = new Guid("00cddea8-939b-4b83-a340-a685226666cc");
			Check(Fn<QI>(_output, 0)(_output, ref iid2, out var obj2), "QI IDXGIOutput1");
			try
			{
				Check(Fn<DuplicateOutputFn>(obj2, 22)(obj2, _device, out _dup), "DuplicateOutput");
			}
			finally
			{
				Release(obj2);
			}
		}

		public bool Capture(int x, int y, int w, int h, out byte[] bgra, out int outW, out int outH)
		{
			int num = Math.Max(x, _outLeft);
			int num2 = Math.Max(y, _outTop);
			int num3 = Math.Min(x + w, _outRight);
			int num4 = Math.Min(y + h, _outBottom);
			outW = num3 - num;
			outH = num4 - num2;
			bgra = null;
			if (outW <= 0 || outH <= 0)
			{
				return false;
			}
			IntPtr intPtr = Marshal.AllocHGlobal(64);
			try
			{
				IntPtr resource;
				int num5 = Fn<AcquireNextFrameFn>(_dup, 8)(_dup, 0u, intPtr, out resource);
				if (num5 == -2005270489)
				{
					if (_last != null && _lastW == outW && _lastH == outH)
					{
						bgra = _last;
						return true;
					}
					return false;
				}
				Check(num5, "AcquireNextFrame");
				try
				{
					Guid iid = new Guid("6f15aaf2-d208-4e89-9ab4-489535d34f9c");
					Check(Fn<QI>(resource, 0)(resource, ref iid, out var obj), "QI ID3D11Texture2D");
					try
					{
						EnsureStaging(outW, outH);
						D3D11_BOX box = new D3D11_BOX
						{
							left = (uint)(num - _outLeft),
							top = (uint)(num2 - _outTop),
							front = 0u,
							right = (uint)(num3 - _outLeft),
							bottom = (uint)(num4 - _outTop),
							back = 1u
						};
						Fn<CopySubresourceRegionFn>(_context, 46)(_context, _staging, 0u, 0u, 0u, 0u, obj, 0u, ref box);
					}
					finally
					{
						Release(obj);
					}
				}
				finally
				{
					Release(resource);
					Fn<ReleaseFrameFn>(_dup, 14)(_dup);
				}
				Check(Fn<MapFn>(_context, 14)(_context, _staging, 0u, 1, 0u, out var mapped), "Map");
				try
				{
					int num6 = outW * 4;
					if (_last == null || _last.Length != num6 * outH)
					{
						_last = new byte[num6 * outH];
					}
					for (int i = 0; i < outH; i++)
					{
						Marshal.Copy(mapped.pData + (int)(i * mapped.RowPitch), _last, i * num6, num6);
					}
					_lastW = outW;
					_lastH = outH;
				}
				finally
				{
					Fn<UnmapFn>(_context, 15)(_context, _staging, 0u);
				}
				bgra = _last;
				return true;
			}
			finally
			{
				Marshal.FreeHGlobal(intPtr);
			}
		}

		private void EnsureStaging(int w, int h)
		{
			if (!(_staging != IntPtr.Zero) || _stagingW != w || _stagingH != h)
			{
				Release(ref _staging);
				D3D11_TEXTURE2D_DESC desc = new D3D11_TEXTURE2D_DESC
				{
					Width = (uint)w,
					Height = (uint)h,
					MipLevels = 1u,
					ArraySize = 1u,
					Format = 87,
					SampleCount = 1u,
					SampleQuality = 0u,
					Usage = 3,
					BindFlags = 0u,
					CPUAccessFlags = 131072u,
					MiscFlags = 0u
				};
				Check(Fn<CreateTexture2DFn>(_device, 5)(_device, ref desc, IntPtr.Zero, out _staging), "CreateTexture2D");
				_stagingW = w;
				_stagingH = h;
			}
		}

		public void Close()
		{
			Release(ref _staging);
			Release(ref _dup);
			Release(ref _output);
			Release(ref _context);
			Release(ref _device);
			_last = null;
		}

		public void Dispose()
		{
			Close();
		}

		private static T Fn<T>(IntPtr obj, int slot) where T : Delegate
		{
			return Marshal.GetDelegateForFunctionPointer<T>(Marshal.ReadIntPtr(Marshal.ReadIntPtr(obj), slot * IntPtr.Size));
		}

		private static void Release(IntPtr p)
		{
			if (p != IntPtr.Zero)
			{
				Fn<ReleaseFn>(p, 2)(p);
			}
		}

		private static void Release(ref IntPtr p)
		{
			Release(p);
			p = IntPtr.Zero;
		}

		private static void Check(int hr, string what)
		{
			if (hr < 0)
			{
				throw new COMException($"{what} failed (0x{hr:X8})", hr);
			}
		}

		[DllImport("d3d11.dll")]
		private static extern int D3D11CreateDevice(IntPtr adapter, int driverType, IntPtr software, uint flags, IntPtr featureLevels, uint numLevels, uint sdkVersion, out IntPtr device, out int featureLevel, out IntPtr context);
	}
	internal static class CinemaDiagnostics
	{
		public static void LogEnvironment()
		{
			ManualLogSource log = REPOCinemaPlugin.Log;
			log.LogInfo((object)("REPO Cinema 0.9.1 | Unity " + Application.unityVersion + " | game " + Application.version));
			log.LogInfo((object)string.Format("PUN {0} | protocol v{1}", "2.52", (byte)8));
			log.LogInfo((object)"NOTE: players without this mod cannot see or hear the cinema (the vanilla game has no URL video path).");
		}
	}
	public class CinemaFloat : MonoBehaviour
	{
		public CinemaPlayback Playback;

		private const float VerticalSpeed = 2.5f;

		private const float Acceleration = 6f;

		private const float CeilingAboveScreen = 1.5f;

		private const float FrontGap = 0.5f;

		private bool _floating;

		private bool _up;

		private bool _down;

		private bool _inZone;

		private LineRenderer _outline;

		private float _blockedFor;

		private void Update()
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			bool flag = REPOCinemaPlugin.FloatSeats.Value && (Object)(object)Playback != (Object)null && Playback.ContentShowing;
			UpdateOutline(flag);
			PlayerController instance = PlayerController.instance;
			_inZone = flag && (Object)(object)instance != (Object)null && InZone(instance.rb.position);
			bool flag2 = CinemaController.PanelOpen || CinemaIdentity.ChatActive;
			_up = _inZone && !flag2 && Input.GetKey((KeyCode)32);
			_down = _inZone && !flag2 && (Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305));
			if (!_inZone)
			{
				if (_floating)
				{
					Stop("left the float zone");
				}
				return;
			}
			if (!_floating && _up)
			{
				_floating = true;
				REPOCinemaPlugin.Log.LogInfo((object)"Cinema seats: floating.");
			}
			if (_floating)
			{
				instance.AntiGravity(0.2f);
			}
		}

		private void FixedUpdate()
		{
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: 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_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			PlayerController instance = PlayerController.instance;
			if (_floating && !((Object)(object)instance == (Object)null) && !instance.rb.isKinematic)
			{
				float num = (_up ? 2.5f : (_down ? (-2.5f) : 0f));
				Camera main = Camera.main;
				if (num > 0f && (Object)(object)main != (Object)null && ((Component)main).transform.position.y >= Playback.ScreenTopY + 1.5f)
				{
					num = 0f;
				}
				Vector3 velocity = instance.rb.velocity;
				float y = velocity.y;
				velocity.y = Mathf.MoveTowards(velocity.y, num, 6f * Time.fixedDeltaTime);
				instance.rb.velocity = velocity;
				_blockedFor = ((_down && y > -0.1f) ? (_blockedFor + Time.fixedDeltaTime) : 0f);
				if (_down && (instance.rb.position.y - Playback.TvFloorY < 0.15f || _blockedFor > 0.25f))
				{
					Stop("landed");
				}
			}
		}

		private void Stop(string why)
		{
			_floating = false;
			REPOCinemaPlugin.Log.LogInfo((object)("Cinema seats: " + why + "."));
		}

		private bool InZone(Vector3 worldPos)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			Transform tvTransform = Playback.TvTransform;
			if ((Object)(object)tvTransform == (Object)null)
			{
				return false;
			}
			Vector3 val = tvTransform.InverseTransformPoint(worldPos);
			float num = Playback.ZoneSize / 2f;
			float num2 = 0f - val.z;
			if (Mathf.Abs(val.x) <= num && num2 >= 0.5f)
			{
				return num2 <= 0.5f + Playback.ZoneSize;
			}
			return false;
		}

		private void UpdateOutline(bool show)
		{
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: 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_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: 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_0061: Expected O, but got Unknown
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Expected O, but got Unknown
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			Transform val = (((Object)(object)Playback != (Object)null) ? Playback.TvTransform : null);
			if (!show || (Object)(object)val == (Object)null)
			{
				if ((Object)(object)_outline != (Object)null)
				{
					((Renderer)_outline).enabled = false;
				}
				return;
			}
			if ((Object)(object)_outline == (Object)null)
			{
				GameObject val2 = new GameObject("REPOCinema_FloatZone");
				Object.DontDestroyOnLoad((Object)(object)val2);
				((Object)val2).hideFlags = (HideFlags)61;
				_outline = val2.AddComponent<LineRenderer>();
				_outline.loop = true;
				_outline.positionCount = 4;
				_outline.widthMultiplier = 0.04f;
				((Renderer)_outline).shadowCastingMode = (ShadowCastingMode)0;
				((Renderer)_outline).receiveShadows = false;
				((Renderer)_outline).material = new Material(Shader.Find("UI/Default") ?? Shader.Find("Standard"));
				LineRenderer outline = _outline;
				LineRenderer outline2 = _outline;
				Color val3 = default(Color);
				((Color)(ref val3))..ctor(0.4f, 0.8f, 1f, 0.35f);
				outline2.endColor = val3;
				outline.startColor = val3;
			}
			((Renderer)_outline).enabled = true;
			float num = Playback.ZoneSize / 2f;
			float num2 = 0.5f;
			float num3 = 0.5f + Playback.ZoneSize;
			float num4 = 0.03f;
			_outline.SetPosition(0, val.TransformPoint(new Vector3(0f - num, num4, 0f - num2)));
			_outline.SetPosition(1, val.TransformPoint(new Vector3(num, num4, 0f - num2)));
			_outline.SetPosition(2, val.TransformPoint(new Vector3(num, num4, 0f - num3)));
			_outline.SetPosition(3, val.TransformPoint(new Vector3(0f - num, num4, 0f - num3)));
		}

		private void OnDestroy()
		{
			if ((Object)(object)_outline != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)_outline).gameObject);
			}
		}
	}
	public class CinemaFun : MonoBehaviour
	{
		public CinemaNetwork Net;

		public CinemaPlayback Playback;

		public const byte QuizEvent = 182;

		private bool _wasShowing;

		private string _lastTitle = "";

		private double _lastShownAt;

		private float _bannerUntil;

		private float _showStart;

		private readonly HashSet<int> _viewersSeen = new HashSet<int>();

		private readonly int[] _reactionCounts = new int[4];

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

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

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

		private int _quizCorrect = -1;

		private int _myAnswer = -1;

		private double _revealedAt;

		private readonly List<float>[] _recent = new List<float>[4]
		{
			new List<float>(),
			new List<float>(),
			new List<float>(),
			new List<float>()
		};

		private int _rainType = -1;

		private float _rainUntil;

		private float _rainCooldown;

		private readonly List<(float x, float speed, float born)> _drops = new List<(float, float, float)>();

		private Light _spot;

		private GUIStyle _title;

		private GUIStyle _body;

		private GUIStyle _box;

		public static bool QuizActive { get; private set; }

		private double Now
		{
			get
			{
				if (!Net.Active)
				{
					return 0.0;
				}
				return CinemaNetwork.Now;
			}
		}

		public bool QuizOpen
		{
			get
			{
				CinemaState current = Net.Gate.Current;
				if (QuizActive && current.QuizReveal < 0)
				{
					return Now < current.QuizEnds;
				}
				return false;
			}
		}

		public int MyAnswer => _myAnswer;

		private void Start()
		{
			Net.ExtraEvent += OnExtra;
		}

		private void Update()
		{
			CinemaState current = Net.Gate.Current;
			bool contentShowing = Playback.ContentShowing;
			TrackShow(current, contentShowing);
			UpdateIntermissionHost(current);
			UpdateQuiz(current);
			UpdateRain();
			UpdateSpotlight(current, contentShowing);
		}

		private void OnExtra(byte code, int sender, object data)
		{
			try
			{
				if (code == 181 && data is byte r)
				{
					CountReaction(sender, r);
					FeedRain(r);
				}
				else if (code == 182 && Net.CanControl && data is byte value && !_answers.ContainsKey(sender))
				{
					_answers[sender] = value;
				}
			}
			catch (Exception ex)
			{
				REPOCinemaPlugin.Log.LogError((object)("Cinema fun event: " + ex));
			}
		}

		private void TrackShow(CinemaState s, bool showing)
		{
			if (s == null)
			{
				_wasShowing = false;
				return;
			}
			bool flag = s.NowPlayingShownAt > 0.0 && s.NowPlayingShownAt != _lastShownAt && Now - s.NowPlayingShownAt < 10.0;
			if (s.Has(CinemaFeature.NowPlaying) && s.NowPlaying.Length > 0 && (flag || (showing && (!_wasShowing || s.NowPlaying != _lastTitle))))
			{
				_bannerUntil = Time.unscaledTime + 5f;
			}
			_lastTitle = s.NowPlaying;
			_lastShownAt = s.NowPlayingShownAt;
			if (Net.CanControl)
			{
				if (showing && !_wasShowing)
				{
					_showStart = Time.unscaledTime;
					_viewersSeen.Clear();
					Array.Clear(_reactionCounts, 0, 4);
					_reactionsBy.Clear();
				}
				if (showing)
				{
					Player[] playerListOthers = PhotonNetwork.PlayerListOthers;
					foreach (Player val in playerListOthers)
					{
						_viewersSeen.Add(val.ActorNumber);
					}
				}
				if (!showing && _wasShowing && s.Has(CinemaFeature.Stats) && Time.unscaledTime - _showStart >= 60f)
				{
					PublishStats();
				}
			}
			_wasShowing = showing;
		}

		private void CountReaction(int sender, byte r)
		{
			if (Net.CanControl && r < 4)
			{
				_reactionCounts[r]++;