Decompiled source of The Relay from Deep Space v1.8.0

TRFDS.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.WebSockets;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using TRFDS.DataStructures;
using TRFDS.Helpers;
using TRFDS.MonoBehaviours;
using TRFDS.UI;
using UnityEngine;
using UnityEngine.Events;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("TRFDS")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.8.0.0")]
[assembly: AssemblyInformationalVersion("1.8.0+334d0ed44845c052916bb4c139956f01d8097d49")]
[assembly: AssemblyProduct("The Relay from Deep Space")]
[assembly: AssemblyTitle("TRFDS")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.8.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
[CompilerGenerated]
internal sealed class <>z__ReadOnlySingleElementList<T> : IEnumerable, ICollection, IList, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T>
{
	private sealed class Enumerator : IDisposable, IEnumerator, IEnumerator<T>
	{
		object IEnumerator.Current => _item;

		T IEnumerator<T>.Current => _item;

		public Enumerator(T item)
		{
			_item = item;
		}

		bool IEnumerator.MoveNext()
		{
			if (!_moveNextCalled)
			{
				return _moveNextCalled = true;
			}
			return false;
		}

		void IEnumerator.Reset()
		{
			_moveNextCalled = false;
		}

		void IDisposable.Dispose()
		{
		}
	}

	int ICollection.Count => 1;

	bool ICollection.IsSynchronized => false;

	object ICollection.SyncRoot => this;

	object IList.this[int index]
	{
		get
		{
			if (index != 0)
			{
				throw new IndexOutOfRangeException();
			}
			return _item;
		}
		set
		{
			throw new NotSupportedException();
		}
	}

	bool IList.IsFixedSize => true;

	bool IList.IsReadOnly => true;

	int IReadOnlyCollection<T>.Count => 1;

	T IReadOnlyList<T>.this[int index]
	{
		get
		{
			if (index != 0)
			{
				throw new IndexOutOfRangeException();
			}
			return _item;
		}
	}

	int ICollection<T>.Count => 1;

	bool ICollection<T>.IsReadOnly => true;

	T IList<T>.this[int index]
	{
		get
		{
			if (index != 0)
			{
				throw new IndexOutOfRangeException();
			}
			return _item;
		}
		set
		{
			throw new NotSupportedException();
		}
	}

	public <>z__ReadOnlySingleElementList(T item)
	{
		_item = item;
	}

	IEnumerator IEnumerable.GetEnumerator()
	{
		return new Enumerator(_item);
	}

	void ICollection.CopyTo(Array array, int index)
	{
		array.SetValue(_item, index);
	}

	int IList.Add(object value)
	{
		throw new NotSupportedException();
	}

	void IList.Clear()
	{
		throw new NotSupportedException();
	}

	bool IList.Contains(object value)
	{
		return EqualityComparer<T>.Default.Equals(_item, (T)value);
	}

	int IList.IndexOf(object value)
	{
		if (!EqualityComparer<T>.Default.Equals(_item, (T)value))
		{
			return -1;
		}
		return 0;
	}

	void IList.Insert(int index, object value)
	{
		throw new NotSupportedException();
	}

	void IList.Remove(object value)
	{
		throw new NotSupportedException();
	}

	void IList.RemoveAt(int index)
	{
		throw new NotSupportedException();
	}

	IEnumerator<T> IEnumerable<T>.GetEnumerator()
	{
		return new Enumerator(_item);
	}

	void ICollection<T>.Add(T item)
	{
		throw new NotSupportedException();
	}

	void ICollection<T>.Clear()
	{
		throw new NotSupportedException();
	}

	bool ICollection<T>.Contains(T item)
	{
		return EqualityComparer<T>.Default.Equals(_item, item);
	}

	void ICollection<T>.CopyTo(T[] array, int arrayIndex)
	{
		array[arrayIndex] = _item;
	}

	bool ICollection<T>.Remove(T item)
	{
		throw new NotSupportedException();
	}

	int IList<T>.IndexOf(T item)
	{
		if (!EqualityComparer<T>.Default.Equals(_item, item))
		{
			return -1;
		}
		return 0;
	}

	void IList<T>.Insert(int index, T item)
	{
		throw new NotSupportedException();
	}

	void IList<T>.RemoveAt(int index)
	{
		throw new NotSupportedException();
	}
}
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
public class CallsignInputValidator : TMP_InputValidator
{
	public override char Validate(ref string text, ref int pos, char ch)
	{
		if (CharacterIsValid(ch) && WithinLengthLimit(text))
		{
			text = text.Insert(pos, ch.ToString());
			pos++;
			return ch;
		}
		return '\0';
	}

	private bool WithinLengthLimit(string text)
	{
		return text.Length < 4;
	}

	private bool CharacterIsValid(char ch)
	{
		if (ch - 48 <= 7)
		{
			return ch - 48 >= 0;
		}
		return false;
	}
}
namespace TRFDS
{
	[BepInPlugin("TRFDS", "The Relay from Deep Space", "1.8.0")]
	public class TRFDSPlugin : BaseUnityPlugin
	{
		public static ConfigEntry<bool> Oscilloscopes;

		public static ConfigEntry<bool> DictionaryDynamicBudge;

		public static ConfigEntry<bool> PlayConfetti;

		public static ConfigEntry<float> RelayTypingDelay;

		public static ConfigEntry<int> RelayTypeCharByCharCutoff;

		public static ConfigEntry<int> RelayTypeLineByLineCutoff;

		public static ConfigEntry<bool> ShowInitialMessagesInstantly;

		public static ConfigEntry<bool> ShortenVisuals;

		public static ConfigEntry<string> RelaySource;

		public static ConfigEntry<bool> ForceEnableRelay;

		internal static ManualLogSource Logger;

		private readonly Harmony harmony = new Harmony("TRFDS");

		private void Awake()
		{
			Logger = ((BaseUnityPlugin)this).Logger;
			Logger.LogInfo((object)"Plugin TRFDS is loaded!");
			harmony.PatchAll();
			LoadConfig();
		}

		private void LoadConfig()
		{
			string text = "";
			string text2 = "";
			string text3 = "";
			text = "General";
			text2 = "Oscilloscopes";
			text3 = "Whether or not to display incoming and outgoing Relay messages on the oscilloscopes";
			Oscilloscopes = ((BaseUnityPlugin)this).Config.Bind<bool>(text, text2, true, text3);
			text2 = "DictionaryLayoutDynamicWidth";
			text3 = "Whether to budge dictionary labels over by a dynamic amount or a fixed amount.\nTrue for dynamic amount, depends on signal length\nFalse for fixed amount of 2";
			DictionaryDynamicBudge = ((BaseUnityPlugin)this).Config.Bind<bool>(text, text2, true, text3);
			text = "Confetti";
			text2 = "Confetti";
			text3 = "Whether the confetti cannon should be allowed to play when a specific frequency is sent. The frequency must also be defined in your dictionary";
			PlayConfetti = ((BaseUnityPlugin)this).Config.Bind<bool>(text, text2, true, text3);
			text = "Typing";
			text2 = "RelayTypingDelay";
			text3 = "The time to wait between printing new lines or characters, in human seconds. Set to 0 to remove line-by-line and character-by-character printing";
			RelayTypingDelay = ((BaseUnityPlugin)this).Config.Bind<float>(text, text2, 0.04f, text3);
			text2 = "RelayTypeCharByCharCutoff";
			text3 = "The amount of characters a message must be under to be typed character-by-character. Messages with a length longer than this are typed either line-by-line or instantly. Does nothing if you set RelayTypingDelay to 0";
			RelayTypeCharByCharCutoff = ((BaseUnityPlugin)this).Config.Bind<int>(text, text2, 32, text3);
			text2 = "RelayTypeLineByLineCutoff";
			text3 = "The amount of characters a message must be under to be typed line-by-line. Messages with a length longer than this are typed instantly. Does nothing if you set RelayTypingDelay to 0";
			RelayTypeLineByLineCutoff = ((BaseUnityPlugin)this).Config.Bind<int>(text, text2, 128, text3);
			text = "Relay";
			text2 = "ShowInitialMessagesInstantly";
			text3 = "Whether to skip typing out the 10 messages that get sent when you initially connect to the Relay. If this is set to false, they are typed out line-by-line, regardless of cutoff settings";
			ShowInitialMessagesInstantly = ((BaseUnityPlugin)this).Config.Bind<bool>(text, text2, true, text3);
			text2 = "ShortenVisuals";
			text3 = "Whether to shorten Relay messages that have visuals in them so they are easier to scroll past";
			ShortenVisuals = ((BaseUnityPlugin)this).Config.Bind<bool>(text, text2, true, text3);
			text2 = "RelaySource";
			text3 = "The web socket source to pull Relay messages from";
			RelaySource = ((BaseUnityPlugin)this).Config.Bind<string>(text, text2, "wss://dscr-relay.dixonary.co.uk", text3);
			text = "Debug";
			text2 = "ForceEnableRelay";
			text3 = "Forces access to the Relay to be enabled, regardless of if you've finished the game or not. WARNING: This is an option provided for debugging, please do not enable this if you haven't finished the game";
			ForceEnableRelay = ((BaseUnityPlugin)this).Config.Bind<bool>(text, text2, false, text3);
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "TRFDS";

		public const string PLUGIN_NAME = "The Relay from Deep Space";

		public const string PLUGIN_VERSION = "1.8.0";
	}
}
namespace TRFDS.UI
{
	[HarmonyPatch]
	public static class CompilerPatch
	{
		[HarmonyPatch(typeof(SignalCompiler), "CompileStringToStringLines")]
		[HarmonyPostfix]
		public static void CollateSignalRepresentations(ref List<string> __result)
		{
			List<string> list = new List<string>();
			for (int i = 0; i < __result.Count; i++)
			{
				string text = __result[i];
				string text2 = __result.ElementAtOrDefault(i + 1);
				string s = __result.ElementAtOrDefault(i + 2);
				if (text == "|" && text2 == "-" && int.TryParse(s, out var result))
				{
					list.Add("-" + result);
					i += 2;
				}
				else
				{
					list.Add(text);
				}
			}
			__result = list;
		}

		[HarmonyPatch(typeof(C_WordCatcher), "CompileLine")]
		[HarmonyPrefix]
		public static bool AllowSignalRepresentations(string lineInput, ref List<int> __result)
		{
			if (lineInput.StartsWith('-') && int.TryParse(lineInput, out var result))
			{
				__result = new List<int> { result };
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch]
	public static class DictionaryPatch
	{
		[HarmonyPatch(typeof(DictionaryEntry), "Configure")]
		[HarmonyPostfix]
		public static void FixOverlappingDictDefinitions(DictionaryEntry __instance)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			num = ((!TRFDSPlugin.DictionaryDynamicBudge.Value) ? 3 : (__instance.idLabel.text.Length - 4));
			Vector3 position = __instance.wordLabel.transform.position;
			__instance.wordLabel.transform.position = new Vector3(position.x + (float)num * 0.0539f, position.y, position.z);
		}

		[HarmonyPatch(typeof(TermNameInputValidator), "WithinLengthLimit")]
		[HarmonyPostfix]
		public static void AllowSlightlyLongerTermNames(ref bool __result, string text)
		{
			__result = text.Length < 18;
		}

		[HarmonyPatch(typeof(DictionaryEntry), "TrashName")]
		[HarmonyPrefix]
		public static bool FullyDeleteCustomSignals(DictionaryEntry __instance)
		{
			if ((__instance.id < -245 || __instance.id > -1) && (Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305)))
			{
				UserDictionary.Instance.RemoveEntry(__instance.id);
				DictionaryWindow obj = UnityHelpers.FindSingleInstanceObject<DictionaryWindow>();
				obj.entries.Remove(__instance);
				obj.entriesDict.Remove(__instance.id);
				obj.totalEntries--;
				Object.DestroyImmediate((Object)(object)((Component)__instance).gameObject);
				obj.dataEntryLayout.LayoutElements(true);
				UnityHelpers.FindSingleInstanceObject<Autosaver>().Autosave(PuzzleManager.Instance);
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(UserDictionary), "LoadPopulate")]
		[HarmonyPrefix]
		public static void SortDictionaryKeys(ref Dictionary<int, string> lWordDict)
		{
			int[] array = lWordDict.Keys.ToArray();
			string[] array2 = lWordDict.Values.ToArray();
			Array.Sort(array, array2, new ReverseComparer());
			lWordDict = array.Zip(array2, (int k, string v) => new { k, v }).ToDictionary(x => x.k, x => x.v);
		}
	}
	internal class ReverseComparer : IComparer
	{
		int IComparer.Compare(object x, object y)
		{
			return Comparer.Default.Compare(y, x);
		}
	}
	[HarmonyPatch]
	public class RelayManagerWindow : InfoWindow
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__SwitchToInput;

			public static UnityAction <1>__CreateNewDictEntry;

			public static UnityAction <2>__SendMessage;

			public static UnityAction <3>__SwitchToManager;
		}

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

			public static UnityAction <>9__32_0;

			public static UnityAction<bool> <>9__34_0;

			public static UnityAction <>9__34_1;

			public static Func<Transform, bool> <>9__35_0;

			public static Func<SimpleWriter, bool> <>9__35_1;

			public static UnityAction <>9__35_2;

			public static UnityAction <>9__35_3;

			public static Func<char, bool> <>9__42_0;

			public static Func<char, bool> <>9__47_0;

			public static Func<(int id, string name), int> <>9__55_0;

			public static Func<int, bool> <>9__55_1;

			public static Func<string, int> <>9__56_0;

			internal void <MakeRelayButton>b__32_0()
			{
				infoDisplay.SwitchWindow(relayManagerWindow);
			}

			internal void <Start>b__34_0(bool goodCallsign)
			{
				if (goodCallsign)
				{
					GoodCallsign();
				}
				else
				{
					BadCallsign();
				}
			}

			internal void <Start>b__34_1()
			{
				((TMP_Text)playMessageSongText).text = "Play";
				((TMP_Text)messageTimeText).text = "";
			}

			internal bool <InitManagerViewport>b__35_0(Transform x)
			{
				return ((Object)x).name == "Round";
			}

			internal bool <InitManagerViewport>b__35_1(SimpleWriter x)
			{
				return ((Object)x).name == "Name Input";
			}

			internal void <InitManagerViewport>b__35_2()
			{
				CycleChannel(-1);
			}

			internal void <InitManagerViewport>b__35_3()
			{
				CycleChannel(1);
			}

			internal bool <SetCallsign>b__42_0(char c)
			{
				if (c - 48 <= 9)
				{
					return c - 48 >= 0;
				}
				return false;
			}

			internal bool <CreateNewDictEntry>b__47_0(char c)
			{
				return char.IsDigit(c);
			}

			internal int <SaveEnabledChannels>b__55_0((int id, string name) x)
			{
				return x.id;
			}

			internal bool <SaveEnabledChannels>b__55_1(int x)
			{
				return x != 0;
			}

			internal int <LoadEnabledChannels>b__56_0(string x)
			{
				return int.Parse(x);
			}
		}

		public static InfoDisplay infoDisplay;

		public static RelaySocket relaySocket;

		public static SongPlayer songPlayer;

		private static bool initRelayButton = false;

		private static bool initInfoDisplay = false;

		private static bool loadEnabledChannels = false;

		private static bool reinitDict = false;

		private static int currCallsignBase8;

		private static int currChannelIndex = 0;

		private static List<(int id, string name)> enabledChannels = new List<(int, string)> { (0, "Default channel") };

		private static GameObject relayManagerViewport;

		private static GameObject relayInputViewport;

		private static InfoWindow relayManagerWindow;

		private static ScrollBar3D relayInputScrollBar;

		private static SimpleWriter callsignInput;

		private static TextMeshPro relayInput;

		private static GameObject switchToInputButton;

		private static TextMeshPro newSignalIdInput;

		private static TextMeshPro newSignalNameInput;

		private static TextMeshPro messageSelectorInput;

		private static GameObject playMessageSongButton;

		private static TextMeshPro playMessageSongText;

		private static TextMeshPro messageTimeText;

		private static TextMeshPro currentChannelLabel;

		private static List<GameObject> hiddenUntilLoggedIn = new List<GameObject>();

		private static CalculatorWindow calculatorWindow;

		private static PopupBox popupBox;

		private static Autosaver autosaver;

		private static DictionaryWindow dictionaryWindow;

		private static PuzzleCounter puzzleCounter;

		private static Oscilloscope playerInputOscilloscope;

		private static VisualWindow visualWindow;

		[HarmonyPatch(typeof(TabsWindow), "Open")]
		[HarmonyPostfix]
		public static void MakeRelayButton(TabsWindow __instance)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Expected O, but got Unknown
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Expected O, but got Unknown
			//IL_014f: 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_015a: Expected O, but got Unknown
			if (initRelayButton)
			{
				return;
			}
			if (!TRFDSPlugin.ForceEnableRelay.Value && PuzzleManager.Instance.CurrPuzzle.uniqueID != 922)
			{
				TRFDSPlugin.Logger.LogWarning((object)"Relay unavailable, please finish the game before chatting.");
				return;
			}
			GameObject val = new GameObject("Song Player");
			val.AddComponent<SongPlayer>();
			songPlayer = val.GetComponent<SongPlayer>();
			initRelayButton = true;
			Transform val2 = __instance.tabsList.transform.Find("Ideas Tab");
			Vector3 position = ((Component)val2).transform.position;
			position.y = 4.46f;
			Transform val3 = Object.Instantiate<Transform>(val2, position, Quaternion.identity);
			((Object)val3).name = "Relay Tab";
			((Component)val3).transform.SetParent(((Component)val2).transform.parent);
			((TMP_Text)((Component)val3).GetComponentInChildren<TextMeshPro>()).text = "Relay";
			using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("TRFDS.Assets.relay.png");
			byte[] array = new byte[stream.Length];
			stream.Read(array, 0, array.Length);
			Texture2D val4 = new Texture2D(2, 2);
			ImageConversion.LoadImage(val4, array);
			((Renderer)((Component)((Component)val3).transform.Find("Icon")).GetComponent<MeshRenderer>()).material.mainTexture = (Texture)(object)val4;
			Button3D component = ((Component)val3).GetComponent<Button3D>();
			component.OnUseButton = new UnityEvent();
			UnityEvent onUseButton = component.OnUseButton;
			object obj = <>c.<>9__32_0;
			if (obj == null)
			{
				UnityAction val5 = delegate
				{
					infoDisplay.SwitchWindow(relayManagerWindow);
				};
				<>c.<>9__32_0 = val5;
				obj = (object)val5;
			}
			onUseButton.AddListener((UnityAction)obj);
		}

		[HarmonyPatch(typeof(InfoDisplay), "Start")]
		[HarmonyPostfix]
		public static void MakeRelayManagerScreen(InfoDisplay __instance)
		{
			if (initInfoDisplay)
			{
				return;
			}
			initInfoDisplay = true;
			infoDisplay = __instance;
			GameObject gameObject = ((Component)Object.Instantiate<CalendarWindow>(UnityHelpers.FindSingleInstanceObject<CalendarWindow>())).gameObject;
			((Object)gameObject).name = "Relay Manager Window";
			Object.DestroyImmediate((Object)(object)gameObject.GetComponent<CalendarWindow>());
			gameObject.SetActive(true);
			Transform[] componentsInChildren = gameObject.GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				if (((Object)val).name == "Mission Time" || ((Object)val).name == "Running Time")
				{
					Object.DestroyImmediate((Object)(object)((Component)val).gameObject);
				}
				else
				{
					((Component)val).gameObject.SetActive(true);
				}
			}
			relayManagerWindow = (InfoWindow)(object)gameObject.AddComponent<RelayManagerWindow>();
		}

		private void Start()
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Expected O, but got Unknown
			relayManagerViewport = ((Component)((Component)this).transform.GetChild(0)).gameObject;
			((Object)relayManagerViewport).name = "Relay Manager Viewport";
			relayManagerViewport.SetActive(false);
			relayInputViewport = Object.Instantiate<GameObject>(relayManagerViewport.gameObject);
			relayInputViewport.transform.SetParent(((Component)this).transform);
			relayInputViewport.transform.position = relayManagerViewport.transform.position;
			((Object)relayInputViewport).name = "Relay Input Viewport";
			relayInputViewport.SetActive(false);
			InitManagerViewport();
			InitInputViewport();
			autosaver = UnityHelpers.FindSingleInstanceObject<Autosaver>();
			dictionaryWindow = UnityHelpers.FindSingleInstanceObject<DictionaryWindow>();
			puzzleCounter = UnityHelpers.FindSingleInstanceObject<PuzzleCounter>();
			playerInputOscilloscope = GameObject.Find("Input Oscilloscope").GetComponent<Oscilloscope>();
			foreach (GameObject item in hiddenUntilLoggedIn)
			{
				item.SetActive(false);
			}
			HotkeyManager.Instance.SetButtonHotkeyDictionary();
			RelaySocket.CallsignProcessed.AddListener((UnityAction<bool>)delegate(bool goodCallsign)
			{
				if (goodCallsign)
				{
					GoodCallsign();
				}
				else
				{
					BadCallsign();
				}
			});
			UnityEvent onSongFinished = SongPlayer.OnSongFinished;
			object obj = <>c.<>9__34_1;
			if (obj == null)
			{
				UnityAction val = delegate
				{
					((TMP_Text)playMessageSongText).text = "Play";
					((TMP_Text)messageTimeText).text = "";
				};
				<>c.<>9__34_1 = val;
				obj = (object)val;
			}
			onSongFinished.AddListener((UnityAction)obj);
		}

		private void InitManagerViewport()
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Expected O, but got Unknown
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Expected O, but got Unknown
			//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d7: Expected O, but got Unknown
			//IL_0366: Unknown result type (might be due to invalid IL or missing references)
			//IL_036b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0375: Unknown result type (might be due to invalid IL or missing references)
			//IL_037a: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03da: Unknown result type (might be due to invalid IL or missing references)
			//IL_03df: Unknown result type (might be due to invalid IL or missing references)
			//IL_0430: Unknown result type (might be due to invalid IL or missing references)
			//IL_0449: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0540: Unknown result type (might be due to invalid IL or missing references)
			//IL_0559: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0301: Expected O, but got Unknown
			//IL_0610: Unknown result type (might be due to invalid IL or missing references)
			//IL_0642: Unknown result type (might be due to invalid IL or missing references)
			//IL_0647: Unknown result type (might be due to invalid IL or missing references)
			//IL_0651: Unknown result type (might be due to invalid IL or missing references)
			//IL_0656: Unknown result type (might be due to invalid IL or missing references)
			//IL_0694: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_072a: Unknown result type (might be due to invalid IL or missing references)
			//IL_072f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0739: Unknown result type (might be due to invalid IL or missing references)
			//IL_073e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0755: 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_07e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_07fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0804: Expected O, but got Unknown
			//IL_088d: Unknown result type (might be due to invalid IL or missing references)
			//IL_08a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0929: Unknown result type (might be due to invalid IL or missing references)
			//IL_095b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0960: Unknown result type (might be due to invalid IL or missing references)
			//IL_096a: Unknown result type (might be due to invalid IL or missing references)
			//IL_096f: Unknown result type (might be due to invalid IL or missing references)
			//IL_09ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a08: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a19: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a23: Expected O, but got Unknown
			//IL_0a36: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a40: Expected O, but got Unknown
			//IL_0aa2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ab3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0abd: Expected O, but got Unknown
			//IL_0ad0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ada: Expected O, but got Unknown
			//IL_0b4b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b5f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b69: Expected O, but got Unknown
			//IL_0b7f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b89: Expected O, but got Unknown
			//IL_0be2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bfb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c80: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c99: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d13: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d24: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d2e: Expected O, but got Unknown
			//IL_0820: Unknown result type (might be due to invalid IL or missing references)
			//IL_0825: Unknown result type (might be due to invalid IL or missing references)
			//IL_082b: Expected O, but got Unknown
			//IL_0d97: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d9c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0da6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0dab: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e05: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e16: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e20: Expected O, but got Unknown
			//IL_0d4e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d53: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d59: Expected O, but got Unknown
			//IL_0e89: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e8e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e98: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e9d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ef3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f0c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f93: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f98: Unknown result type (might be due to invalid IL or missing references)
			//IL_0fa6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0fa8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e40: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e45: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e4b: Expected O, but got Unknown
			((TMP_Text)relayManagerViewport.GetComponentInChildren<TextMeshPro>()).text = "Relay Manager";
			calculatorWindow = GameObject.Find("Calculator Window").GetComponent<CalculatorWindow>();
			visualWindow = UnityHelpers.FindSingleInstanceObject<VisualWindow>();
			GameObject obj = Object.Instantiate<GameObject>(((Component)calculatorWindow.outputLabel).gameObject);
			((Object)obj).name = "Callsign Label";
			obj.transform.SetParent(relayManagerViewport.transform);
			RectTransform component = obj.GetComponent<RectTransform>();
			component.anchoredPosition = Vector2.zero;
			((Transform)component).position = new Vector3(-30.3f, 5.45f, 0f);
			TextMeshPro component2 = obj.GetComponent<TextMeshPro>();
			((TMP_Text)component2).text = "Callsign (base 8):";
			((TMP_Text)component2).textWrappingMode = (TextWrappingModes)0;
			((TMP_Text)component2).overflowMode = (TextOverflowModes)0;
			GameObject obj2 = Object.Instantiate<GameObject>(((Component)calculatorWindow.operand1).gameObject);
			((Object)obj2).name = "Callsign Input";
			obj2.transform.SetParent(relayManagerViewport.transform);
			obj2.transform.position = new Vector3(-29.7f, 5.5f, 0.22f);
			UnityHelpers.ScaleMeshVertices(obj2.GetComponent<MeshFilter>().mesh, 0.2f, 0.6f);
			callsignInput = obj2.GetComponent<SimpleWriter>();
			callsignInput.label.transform.position = new Vector3(-29.1f, 5.46f, 0.2141f);
			string text = "";
			for (int i = 0; i < 4; i++)
			{
				text += Random.RandomRangeInt(0, 8);
			}
			callsignInput.label.text = text;
			Transform? obj3 = ((IEnumerable<Transform>)calculatorWindow.viewport.GetComponentsInChildren<Transform>()).FirstOrDefault((Func<Transform, bool>)((Transform x) => ((Object)x).name == "Round"));
			Transform obj4 = Object.Instantiate<Transform>(obj3);
			((Object)obj4).name = "Confirm Callsign Button";
			((Component)obj4).transform.SetParent(relayManagerViewport.transform);
			((Component)obj4).transform.position = new Vector3(-29.3f, 5.5f, 0.216f);
			((Component)obj4).GetComponent<Button3D>().OnUseButton = new UnityEvent();
			((Component)obj4).GetComponent<Button3D>().OnUseButton.AddListener(new UnityAction(SetCallsign));
			((TMP_Text)((Component)obj4).GetComponentInChildren<TextMeshPro>()).text = "Set";
			switchToInputButton = ((Component)Object.Instantiate<Transform>(ConsoleDisplay.Instance.readMessageGroup.transform.Find("Respond Button"))).gameObject;
			hiddenUntilLoggedIn.Add(switchToInputButton);
			((Object)switchToInputButton).name = "Relay Input Button";
			switchToInputButton.transform.SetParent(relayManagerViewport.transform);
			switchToInputButton.transform.position = new Vector3(-29.38f, 5.675f, 0.25f);
			switchToInputButton.GetComponent<Button3D>().OnUseButton = new UnityEvent();
			UnityEvent onUseButton = switchToInputButton.GetComponent<Button3D>().OnUseButton;
			object obj5 = <>O.<0>__SwitchToInput;
			if (obj5 == null)
			{
				UnityAction val = SwitchToInput;
				<>O.<0>__SwitchToInput = val;
				obj5 = (object)val;
			}
			onUseButton.AddListener((UnityAction)obj5);
			((TMP_Text)switchToInputButton.GetComponentInChildren<TextMeshPro>()).text = "Input";
			Object.Destroy((Object)(object)((Component)switchToInputButton.transform.Find("Icon")).gameObject);
			UnityHelpers.ScaleMeshVertices(switchToInputButton.GetComponent<MeshFilter>().mesh, 0.6f);
			BoxCollider component3 = switchToInputButton.GetComponent<BoxCollider>();
			component3.size -= Vector3.right * 0.4f;
			switchToInputButton.gameObject.SetActive(false);
			RelayHelpers.AddHotkey(switchToInputButton, (KeyCode)306, (KeyCode)114);
			RelayHelpers.AddHotkey(switchToInputButton, (KeyCode)305, (KeyCode)114);
			Transform obj6 = switchToInputButton.transform.Find("Text");
			obj6.position += Vector3.right * 0.0325f;
			GameObject val2 = Object.Instantiate<GameObject>(((Component)calculatorWindow.outputLabel).gameObject);
			hiddenUntilLoggedIn.Add(val2);
			((Object)val2).name = "New Signals Label";
			val2.transform.SetParent(relayManagerViewport.transform);
			RectTransform component4 = val2.GetComponent<RectTransform>();
			component4.anchoredPosition = Vector2.zero;
			((Transform)component4).position = new Vector3(-30.3f, 5.25f, 0f);
			TextMeshPro component5 = val2.GetComponent<TextMeshPro>();
			((TMP_Text)component5).text = "Add new signals:";
			((TMP_Text)component5).textWrappingMode = (TextWrappingModes)0;
			((TMP_Text)component5).overflowMode = (TextOverflowModes)0;
			GameObject val3 = Object.Instantiate<GameObject>(((Component)calculatorWindow.outputLabel).gameObject);
			hiddenUntilLoggedIn.Add(val3);
			((Object)val3).name = "Signal ID Label";
			val3.transform.SetParent(relayManagerViewport.transform);
			RectTransform component6 = val3.GetComponent<RectTransform>();
			component6.anchoredPosition = Vector2.zero;
			((Transform)component6).position = new Vector3(-30.3f, 5.15f, 0f);
			TextMeshPro component7 = val3.GetComponent<TextMeshPro>();
			((TMP_Text)component7).text = "ID";
			((TMP_Text)component7).textWrappingMode = (TextWrappingModes)0;
			((TMP_Text)component7).overflowMode = (TextOverflowModes)0;
			GameObject val4 = Object.Instantiate<GameObject>(((Component)calculatorWindow.outputLabel).gameObject);
			hiddenUntilLoggedIn.Add(val4);
			((Object)val4).name = "Signal Name Label";
			val4.transform.SetParent(relayManagerViewport.transform);
			RectTransform component8 = val4.GetComponent<RectTransform>();
			component8.anchoredPosition = Vector2.zero;
			((Transform)component8).position = new Vector3(-29.63f, 5.15f, 0f);
			TextMeshPro component9 = val4.GetComponent<TextMeshPro>();
			((TMP_Text)component9).text = "Name";
			((TMP_Text)component9).textWrappingMode = (TextWrappingModes)0;
			((TMP_Text)component9).overflowMode = (TextOverflowModes)0;
			calculatorWindow.viewport.GetComponentsInChildren<SimpleWriter>(true).First((SimpleWriter x) => ((Object)x).name == "Name Input");
			GameObject val5 = Object.Instantiate<GameObject>(((Component)calculatorWindow.operand1).gameObject);
			hiddenUntilLoggedIn.Add(val5);
			((Object)val5).name = "New Signal ID Input";
			val5.transform.SetParent(relayManagerViewport.transform);
			val5.transform.position = new Vector3(-30.755f, 5.1f, 0.22f);
			UnityHelpers.ScaleMeshVertices(val5.GetComponent<MeshFilter>().mesh, 0.3f, 0.6f);
			BoxCollider component10 = val5.GetComponent<BoxCollider>();
			component10.size -= Vector3.right * 0.4f;
			newSignalIdInput = val5.GetComponentInChildren<TextMeshPro>();
			((TMP_Text)newSignalIdInput).text = "-";
			newSignalIdInput.transform.localPosition = new Vector3(0.3503f, -0.2237f, -0.59f);
			GameObject val6 = Object.Instantiate<GameObject>(((Component)calculatorWindow.operand1).gameObject);
			hiddenUntilLoggedIn.Add(val6);
			((Object)val6).name = "New Signal Name Input";
			val6.transform.SetParent(relayManagerViewport.transform);
			val6.transform.position = new Vector3(-29.95f, 5.1f, 0.22f);
			UnityHelpers.ScaleMeshVertices(val6.GetComponent<MeshFilter>().mesh, 0.5f, 0.6f);
			BoxCollider component11 = val6.GetComponent<BoxCollider>();
			component11.size -= Vector3.right * 0.4f;
			((Component)val6.transform).GetComponent<SimpleWriter>().dummyType = (InputDummyType)0;
			newSignalNameInput = val6.GetComponentInChildren<TextMeshPro>();
			((TMP_Text)newSignalNameInput).text = "";
			newSignalNameInput.transform.localPosition = new Vector3(0.25f, -0.2237f, -0.59f);
			GameObject gameObject = ((Component)Object.Instantiate<Transform>(obj3)).gameObject;
			hiddenUntilLoggedIn.Add(gameObject);
			((Object)gameObject).name = "Make New Dict Entry Button";
			gameObject.transform.SetParent(relayManagerViewport.transform);
			gameObject.transform.position = new Vector3(-29.3f, 5.1f, 0.216f);
			gameObject.GetComponent<Button3D>().OnUseButton = new UnityEvent();
			UnityEvent onUseButton2 = gameObject.GetComponent<Button3D>().OnUseButton;
			object obj7 = <>O.<1>__CreateNewDictEntry;
			if (obj7 == null)
			{
				UnityAction val7 = CreateNewDictEntry;
				<>O.<1>__CreateNewDictEntry = val7;
				obj7 = (object)val7;
			}
			onUseButton2.AddListener((UnityAction)obj7);
			((TMP_Text)gameObject.GetComponentInChildren<TextMeshPro>()).text = "Make";
			GameObject val8 = Object.Instantiate<GameObject>(((Component)calculatorWindow.outputLabel).gameObject);
			hiddenUntilLoggedIn.Add(val8);
			((Object)val8).name = "Message Select Label";
			val8.transform.SetParent(relayManagerViewport.transform);
			RectTransform component12 = val8.GetComponent<RectTransform>();
			component12.anchoredPosition = Vector2.zero;
			((Transform)component12).position = new Vector3(-30.3f, 4.83f, 0f);
			TextMeshPro component13 = val8.GetComponent<TextMeshPro>();
			((TMP_Text)component13).text = "Message Actions:";
			((TMP_Text)component13).textWrappingMode = (TextWrappingModes)0;
			((TMP_Text)component13).overflowMode = (TextOverflowModes)0;
			GameObject val9 = Object.Instantiate<GameObject>(((Component)calculatorWindow.operand1).gameObject);
			hiddenUntilLoggedIn.Add(val9);
			((Object)val9).name = "Relay Message Selector Input";
			val9.transform.SetParent(relayManagerViewport.transform);
			val9.transform.position = new Vector3(-30.83f, 4.77f, 0.22f);
			UnityHelpers.ScaleMeshVertices(val9.GetComponent<MeshFilter>().mesh, 0.2f, 0.6f);
			BoxCollider component14 = val9.GetComponent<BoxCollider>();
			component14.size -= Vector3.right * 0.8f;
			messageSelectorInput = val9.GetComponentInChildren<TextMeshPro>();
			((TMP_Text)messageSelectorInput).text = "";
			messageSelectorInput.transform.position = new Vector3(-30.2f, 4.73f, 0.2141f);
			GameObject gameObject2 = ((Component)Object.Instantiate<Transform>(obj3)).gameObject;
			hiddenUntilLoggedIn.Add(gameObject2);
			((Object)gameObject2).name = "Copy Relay Message Signals Button";
			gameObject2.transform.SetParent(relayManagerViewport.transform);
			gameObject2.transform.position = new Vector3(-30.5f, 4.77f, 0.216f);
			gameObject2.GetComponent<Button3D>().OnUseButton = new UnityEvent();
			gameObject2.GetComponent<Button3D>().OnUseButton.AddListener(new UnityAction(CopySignals));
			((TMP_Text)gameObject2.GetComponentInChildren<TextMeshPro>()).text = "Copy";
			GameObject gameObject3 = ((Component)Object.Instantiate<Transform>(obj3)).gameObject;
			hiddenUntilLoggedIn.Add(gameObject3);
			((Object)gameObject3).name = "View Relay Message Visual Button";
			gameObject3.transform.SetParent(relayManagerViewport.transform);
			gameObject3.transform.position = new Vector3(-30.16f, 4.77f, 0.216f);
			gameObject3.GetComponent<Button3D>().OnUseButton = new UnityEvent();
			gameObject3.GetComponent<Button3D>().OnUseButton.AddListener(new UnityAction(ViewVisual));
			((TMP_Text)gameObject3.GetComponentInChildren<TextMeshPro>()).text = "View";
			playMessageSongButton = ((Component)Object.Instantiate<Transform>(obj3)).gameObject;
			hiddenUntilLoggedIn.Add(playMessageSongButton);
			((Object)playMessageSongButton).name = "Play Relay Message Song Button";
			playMessageSongButton.transform.SetParent(relayManagerViewport.transform);
			playMessageSongButton.transform.position = new Vector3(-29.822f, 4.77f, 0.216f);
			playMessageSongButton.GetComponent<Button3D>().OnUseButton = new UnityEvent();
			playMessageSongButton.GetComponent<Button3D>().OnUseButton.AddListener(new UnityAction(PlayStopSong));
			playMessageSongText = playMessageSongButton.GetComponentInChildren<TextMeshPro>();
			((TMP_Text)playMessageSongText).text = "Play";
			GameObject obj8 = Object.Instantiate<GameObject>(((Component)calculatorWindow.outputLabel).gameObject);
			((Object)obj8).name = "Song Duration Label";
			obj8.transform.SetParent(relayManagerViewport.transform);
			RectTransform component15 = obj8.GetComponent<RectTransform>();
			component15.anchoredPosition = Vector2.zero;
			((Transform)component15).position = new Vector3(-28.95f, 4.71f, 0f);
			messageTimeText = obj8.GetComponent<TextMeshPro>();
			((TMP_Text)messageTimeText).text = "";
			((TMP_Text)messageTimeText).textWrappingMode = (TextWrappingModes)0;
			((TMP_Text)messageTimeText).overflowMode = (TextOverflowModes)0;
			GameObject val10 = Object.Instantiate<GameObject>(((Component)calculatorWindow.outputLabel).gameObject);
			hiddenUntilLoggedIn.Add(val10);
			((Object)val10).name = "Change Channel Label";
			val10.transform.SetParent(relayManagerViewport.transform);
			RectTransform component16 = val10.GetComponent<RectTransform>();
			component16.anchoredPosition = Vector2.zero;
			((Transform)component16).position = new Vector3(-30.3f, 4.52f, 0f);
			TextMeshPro component17 = val10.GetComponent<TextMeshPro>();
			((TMP_Text)component17).text = "Select channel:";
			((TMP_Text)component17).textWrappingMode = (TextWrappingModes)0;
			((TMP_Text)component17).overflowMode = (TextOverflowModes)0;
			GameObject gameObject4 = ((Component)Object.Instantiate<Transform>(obj3)).gameObject;
			hiddenUntilLoggedIn.Add(gameObject4);
			((Object)gameObject4).name = "Cycle Channel Left Button";
			gameObject4.transform.SetParent(relayManagerViewport.transform);
			gameObject4.transform.position = new Vector3(-30.89f, 4.45f, 0.216f);
			gameObject4.GetComponent<Button3D>().OnUseButton = new UnityEvent();
			UnityEvent onUseButton3 = gameObject4.GetComponent<Button3D>().OnUseButton;
			object obj9 = <>c.<>9__35_2;
			if (obj9 == null)
			{
				UnityAction val11 = delegate
				{
					CycleChannel(-1);
				};
				<>c.<>9__35_2 = val11;
				obj9 = (object)val11;
			}
			onUseButton3.AddListener((UnityAction)obj9);
			((TMP_Text)gameObject4.GetComponentInChildren<TextMeshPro>()).text = "<";
			UnityHelpers.ScaleMeshVertices(gameObject4.GetComponent<MeshFilter>().mesh, 0.5f);
			BoxCollider component18 = gameObject4.GetComponent<BoxCollider>();
			component18.size -= Vector3.right * 0.5f;
			GameObject gameObject5 = ((Component)Object.Instantiate<Transform>(obj3)).gameObject;
			hiddenUntilLoggedIn.Add(gameObject5);
			((Object)gameObject5).name = "Cycle Channel Right Button";
			gameObject5.transform.SetParent(relayManagerViewport.transform);
			gameObject5.transform.position = new Vector3(-29.58f, 4.45f, 0.216f);
			gameObject5.GetComponent<Button3D>().OnUseButton = new UnityEvent();
			UnityEvent onUseButton4 = gameObject5.GetComponent<Button3D>().OnUseButton;
			object obj10 = <>c.<>9__35_3;
			if (obj10 == null)
			{
				UnityAction val12 = delegate
				{
					CycleChannel(1);
				};
				<>c.<>9__35_3 = val12;
				obj10 = (object)val12;
			}
			onUseButton4.AddListener((UnityAction)obj10);
			((TMP_Text)gameObject5.GetComponentInChildren<TextMeshPro>()).text = ">";
			UnityHelpers.ScaleMeshVertices(gameObject5.GetComponent<MeshFilter>().mesh, 0.5f);
			BoxCollider component19 = gameObject5.GetComponent<BoxCollider>();
			component19.size -= Vector3.right * 0.5f;
			GameObject val13 = Object.Instantiate<GameObject>(((Component)calculatorWindow.outputLabel).gameObject);
			hiddenUntilLoggedIn.Add(val13);
			((Object)val13).name = "Current Channel Label";
			val13.transform.SetParent(relayManagerViewport.transform);
			RectTransform component20 = val13.GetComponent<RectTransform>();
			component20.anchoredPosition = Vector2.zero;
			((Transform)component20).position = new Vector3(-30.235f, 4.445f, 0f);
			currentChannelLabel = val13.GetComponent<TextMeshPro>();
			((TMP_Text)currentChannelLabel).text = enabledChannels[currChannelIndex].name;
			((TMP_Text)currentChannelLabel).textWrappingMode = (TextWrappingModes)0;
			((TMP_Text)currentChannelLabel).overflowMode = (TextOverflowModes)0;
			((TMP_Text)currentChannelLabel).alignment = (TextAlignmentOptions)514;
			PopupBox obj11 = Object.Instantiate<PopupBox>(UnityHelpers.FindSingleInstanceObject<PopupBox>("Idea Popup"));
			((Object)obj11).name = "Relay Popup";
			popupBox = ((Component)obj11).GetComponent<PopupBox>();
			PopupBox obj12 = popupBox;
			Vector3 rootPos = popupBox.rootPos;
			rootPos.y = 4f;
			obj12.rootPos = rootPos;
		}

		private void InitInputViewport()
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Expected O, but got Unknown
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_025e: 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_02b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0309: Unknown result type (might be due to invalid IL or missing references)
			//IL_0329: Unknown result type (might be due to invalid IL or missing references)
			//IL_0333: Expected O, but got Unknown
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Expected O, but got Unknown
			//IL_039e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_034e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0353: Unknown result type (might be due to invalid IL or missing references)
			//IL_0359: Expected O, but got Unknown
			((TMP_Text)relayInputViewport.GetComponentInChildren<TextMeshPro>()).text = "Relay Input";
			InputDisplaySelector val = Object.Instantiate<InputDisplaySelector>(UnityHelpers.FindSingleInstanceObject<InputDisplaySelector>());
			((Component)val).transform.SetParent(relayInputViewport.transform);
			((Component)val).transform.position = new Vector3(-30.1f, 5.55f, 0.22f);
			((Object)val).name = "Relay Input";
			relayInput = ((Component)val).GetComponent<TextMeshPro>();
			((TMP_Text)relayInput).fontSize = 0.9f;
			((Component)val).GetComponent<InputDisplaySelector>().tInput = (TMP_Text)(object)relayInput;
			((SimpleWriter)((Component)val).GetComponent<InputDisplaySelector>()).charsLength = 9999;
			GameObject obj = Object.Instantiate<GameObject>(((Component)ConsoleDisplay.Instance.responseGroup.transform.Find("Scroll Bar")).gameObject);
			obj.transform.SetParent(relayInputViewport.transform);
			((Object)obj).name = "Relay Input Scrollbar";
			relayInputScrollBar = obj.GetComponentInChildren<ScrollBar3D>();
			((Object)relayInputScrollBar).name = "Relay Input Scroll Handle";
			relayInputScrollBar.visuals = ((Component)((Component)relayInputScrollBar).transform.Find("Scroll Visuals")).gameObject;
			relayInputScrollBar.col = (Collider)(object)((Component)relayInputScrollBar).GetComponent<BoxCollider>();
			relayInputScrollBar.meshRenderer = ((Component)relayInputScrollBar).GetComponentInChildren<MeshRenderer>();
			relayInputScrollBar.scrollArea = ((Component)val).gameObject;
			val.scrollArea = ((Component)val).GetComponent<ScrollArea>();
			val.scrollBar = relayInputScrollBar;
			Transform obj2 = ConsoleDisplay.Instance.readMessageGroup.transform.Find("Respond Button");
			Transform obj3 = Object.Instantiate<Transform>(obj2);
			((Object)obj3).name = "Relay Send Message Button";
			((Component)obj3).transform.SetParent(relayInputViewport.transform);
			((Component)obj3).transform.position = new Vector3(-29.34f, 5.675f, 0.25f);
			((TMP_Text)((Component)obj3).GetComponentInChildren<TextMeshPro>()).text = "Send";
			((Component)obj3).GetComponentInChildren<Button3D>().OnUseButton = new UnityEvent();
			UnityEvent onUseButton = ((Component)obj3).GetComponentInChildren<Button3D>().OnUseButton;
			object obj4 = <>O.<2>__SendMessage;
			if (obj4 == null)
			{
				UnityAction val2 = SendMessage;
				<>O.<2>__SendMessage = val2;
				obj4 = (object)val2;
			}
			onUseButton.AddListener((UnityAction)obj4);
			Object.Destroy((Object)(object)((Component)((Component)obj3).transform.Find("Icon")).gameObject);
			UnityHelpers.ScaleMeshVertices(((Component)obj3).GetComponent<MeshFilter>().mesh, 0.5f);
			BoxCollider component = ((Component)obj3).GetComponent<BoxCollider>();
			component.size -= Vector3.right * 0.5f;
			RelayHelpers.AddHotkey(obj3, (KeyCode)306, (KeyCode)101);
			RelayHelpers.AddHotkey(obj3, (KeyCode)305, (KeyCode)101);
			RelayHelpers.AddHotkey(obj3, (KeyCode)306, (KeyCode)13);
			RelayHelpers.AddHotkey(obj3, (KeyCode)305, (KeyCode)13);
			Transform obj5 = ((Component)obj3).transform.Find("Text");
			obj5.position += Vector3.right * 0.0325f;
			Transform obj6 = Object.Instantiate<Transform>(obj2);
			((Object)obj6).name = "Relay Manager Button";
			((Component)obj6).transform.SetParent(relayInputViewport.transform);
			((Component)obj6).transform.position = new Vector3(-29.73f, 5.675f, 0.25f);
			((TMP_Text)((Component)obj6).GetComponentInChildren<TextMeshPro>()).text = "Manager";
			((Component)obj6).GetComponentInChildren<Button3D>().OnUseButton = new UnityEvent();
			UnityEvent onUseButton2 = ((Component)obj6).GetComponentInChildren<Button3D>().OnUseButton;
			object obj7 = <>O.<3>__SwitchToManager;
			if (obj7 == null)
			{
				UnityAction val3 = SwitchToManager;
				<>O.<3>__SwitchToManager = val3;
				obj7 = (object)val3;
			}
			onUseButton2.AddListener((UnityAction)obj7);
			Object.Destroy((Object)(object)((Component)((Component)obj6).transform.Find("Icon")).gameObject);
			UnityHelpers.ScaleMeshVertices(((Component)obj6).GetComponent<MeshFilter>().mesh, 0.8f);
			BoxCollider component2 = ((Component)obj6).GetComponent<BoxCollider>();
			component2.size -= Vector3.right * 0.2f;
			RelayHelpers.AddHotkey(obj6, (KeyCode)306, (KeyCode)114);
			RelayHelpers.AddHotkey(obj6, (KeyCode)305, (KeyCode)114);
			Transform obj8 = ((Component)obj6).transform.Find("Text");
			obj8.position += Vector3.right * 0.0355f;
		}

		[HarmonyPatch(typeof(WorldSpaceClicker), "ScanForHitbox")]
		[HarmonyPostfix]
		public static void HandleInput(WorldSpaceClicker __instance)
		{
			if (__instance.mainClickDown && relayInputViewport.gameObject.activeSelf && !__instance.InRightSide)
			{
				((SimpleWriter)((Component)relayInput).GetComponent<InputDisplaySelector>()).OnRelease(__instance);
			}
		}

		[HarmonyPatch(typeof(SimpleWriter), "BecomeWritingTarget")]
		[HarmonyPrefix]
		public static void FuckUnfuckFloatTextDummy(SimpleWriter __instance)
		{
			if ((Object)(object)__instance == (Object)(object)callsignInput)
			{
				TextDummyManager.Instance_Float.InputField.inputValidator = (TMP_InputValidator)(object)ScriptableObject.CreateInstance<CallsignInputValidator>();
			}
			else if (!(TextDummyManager.Instance_Float.InputField.inputValidator is FloatInputValidator))
			{
				TextDummyManager.Instance_Float.InputField.inputValidator = (TMP_InputValidator)(object)ScriptableObject.CreateInstance<FloatInputValidator>();
			}
		}

		[HarmonyPatch(typeof(WorldSpaceClicker), "ObjectIsRightSide")]
		[HarmonyPostfix]
		public static void ForceInputScrollbarToLeftMonitor(GameObject go, ref bool __result)
		{
			ScrollBar3D obj = relayInputScrollBar;
			if ((Object)(object)go == (Object)(object)((obj != null) ? ((Component)obj).gameObject : null))
			{
				__result = false;
			}
		}

		public override void Open()
		{
			if (!loadEnabledChannels)
			{
				LoadEnabledChannels();
				loadEnabledChannels = true;
			}
			if (RelaySocket.Callsign == null)
			{
				relayManagerViewport.SetActive(true);
			}
			else
			{
				relayInputViewport.SetActive(true);
			}
			RelayWindow.TryShow();
		}

		public override void Close()
		{
			relayManagerViewport.SetActive(false);
			relayInputViewport.SetActive(false);
		}

		private void SetCallsign()
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			string text = GeneralExtensions.Join<char>(callsignInput.label.text.Where((char c) => c - 48 <= 9 && c - 48 >= 0), (Func<char, string>)null, "");
			if (text.Length != 4)
			{
				popupBox.PopupWithLabel("Callsign length must be 4");
				return;
			}
			int num = int.Parse(text);
			string callsign = calculatorWindow.EuclideanBaseChange((double)num, 8, 10);
			if ((Object)(object)relaySocket == (Object)null)
			{
				RelaySocket.Callsign = callsign;
				currCallsignBase8 = num;
				GameObject val = new GameObject("Relay Socket");
				val.AddComponent<RelaySocket>();
				relaySocket = val.GetComponent<RelaySocket>();
			}
			else
			{
				RelaySocket.Callsign = callsign;
				RelaySocket.UpdateCallsign = true;
			}
		}

		public static void GoodCallsign()
		{
			SwitchToInput();
			switchToInputButton.SetActive(true);
			popupBox.PopupWithLabel("Callsign set to " + callsignInput.label.text);
			((MonoBehaviour)puzzleCounter).StartCoroutine(puzzleCounter.UpdateCounterRoutine(currCallsignBase8, 0f));
			foreach (GameObject item in hiddenUntilLoggedIn)
			{
				item.SetActive(true);
			}
			if (UserDictionary.Instance.terms.ContainsKey(-577))
			{
				ShowSongStuff();
			}
			else
			{
				HideSongStuff();
			}
		}

		public static void BadCallsign()
		{
			popupBox.PopupWithLabel("Callsign already in use");
		}

		public static void Disconnect()
		{
			infoDisplay.SwitchWindow(infoDisplay.tabsWindow);
			if ((Object)(object)relaySocket == (Object)null)
			{
				return;
			}
			HideSongStuff();
			foreach (GameObject item in hiddenUntilLoggedIn)
			{
				item.SetActive(false);
			}
			((MonoBehaviour)puzzleCounter).StartCoroutine(puzzleCounter.UpdateCounterRoutine(PuzzleManager.Instance.TotalPuzzleID + 1, 0f));
			puzzleCounter.digitWheels[0].ScrollTo(0);
			switchToInputButton.SetActive(false);
			relaySocket.Disconnect();
			Object.Destroy((Object)(object)relaySocket);
			relaySocket = null;
			RelaySocket.Callsign = null;
		}

		private static void SendMessage()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			//IL_002a: 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_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Invalid comparison between Unknown and I4
			//IL_0435: Unknown result type (might be due to invalid IL or missing references)
			string text = TextDummyManager.Instance_PuzzleInput.currText.ToUpper();
			CompilerResult val = new CompilerResult();
			SignalMessage signalMessage = ConsoleDisplay.Instance.compiler.CompileStringToSignal(text, ref val);
			if ((int)val.compilerResultTag == 1)
			{
				string[] array = val.errorMsg.Split(Environment.NewLine);
				string text2 = array[1];
				if (text2 == "Null Input")
				{
					popupBox.PopupWithLabel("Err: null input");
				}
				else if (text2.Contains("Entry not found"))
				{
					string text3 = array[2];
					popupBox.PopupWithLabel("Err: " + text3 + " not found");
				}
				else
				{
					popupBox.PopupWithLabel("Err: Unknown error type");
				}
				return;
			}
			if (signalMessage.signals[0] == -65534)
			{
				if (signalMessage.signals.Length > 2 || signalMessage.signals.ElementAtOrDefault(1) >= 0)
				{
					popupBox.PopupWithLabel("Usage: " + UserDictionary.Instance.GetWordFromInt(-65534) + " <signal>");
					return;
				}
				if (enabledChannels.Any(((int id, string name) x) => x.id == signalMessage.signals[1]))
				{
					popupBox.PopupWithLabel("Already in channel: " + UserDictionary.Instance.GetWordFromInt(signalMessage.signals[1]));
					return;
				}
				enabledChannels.Add((signalMessage.signals[1], UserDictionary.Instance.GetWordFromInt(signalMessage.signals[1])));
				currChannelIndex = enabledChannels.Count - 1;
				((TMP_Text)currentChannelLabel).text = enabledChannels[currChannelIndex].name;
				RelayWindow.SetActiveChannel(enabledChannels[currChannelIndex].id);
				popupBox.PopupWithLabel("Joined channel: " + enabledChannels[currChannelIndex].name);
				SaveEnabledChannels();
				TextDummyManager.Instance_PuzzleInput.Clear();
				return;
			}
			if (signalMessage.signals[0] == -65533)
			{
				if (signalMessage.signals.Length > 2 || signalMessage.signals.ElementAtOrDefault(1) >= 0)
				{
					popupBox.PopupWithLabel("Usage: " + UserDictionary.Instance.GetWordFromInt(-65533) + " <signal>");
					return;
				}
				int num = enabledChannels.FindIndex(0, ((int id, string name) x) => x.id == signalMessage.signals[1]);
				if (num < 0)
				{
					popupBox.PopupWithLabel("Not in channel: " + UserDictionary.Instance.GetWordFromInt(signalMessage.signals[1]));
					return;
				}
				string item = enabledChannels[num].name;
				enabledChannels.RemoveAt(num);
				currChannelIndex = 0;
				((TMP_Text)currentChannelLabel).text = enabledChannels[currChannelIndex].name;
				RelayWindow.SetActiveChannel(enabledChannels[currChannelIndex].id);
				popupBox.PopupWithLabel("Left channel: " + item);
				SaveEnabledChannels();
				TextDummyManager.Instance_PuzzleInput.Clear();
				return;
			}
			int item2 = enabledChannels[currChannelIndex].id;
			if (item2 != 0 && item2 != -65536)
			{
				signalMessage.signals = new int[2] { -65535, item2 }.Concat(signalMessage.signals).ToArray();
			}
			string text4 = "M,";
			for (int num2 = 0; num2 < signalMessage.signals.Length; num2++)
			{
				int num3 = signalMessage.signals[num2];
				text4 = ((num3 >= 0 && signalMessage.signals.ElementAtOrDefault(num2 + 1) >= 0) ? (text4 + num3) : (text4 + num3 + ","));
			}
			text4 = text4.TrimEnd(',');
			RelaySocket.QueueSend(text4);
			TextDummyManager.Instance_PuzzleInput.Clear();
			if (TRFDSPlugin.Oscilloscopes.Value)
			{
				playerInputOscilloscope.PlaySignal(signalMessage, false);
			}
		}

		private static void CreateNewDictEntry()
		{
			if (((TMP_Text)newSignalIdInput).text.Contains('.'))
			{
				popupBox.PopupWithLabel("Signal must be an integer");
				return;
			}
			if (((TMP_Text)newSignalIdInput).text[0] != '-')
			{
				popupBox.PopupWithLabel("Signal must be negative");
				return;
			}
			int num = Convert.ToInt32(GeneralExtensions.Join<char>(((TMP_Text)newSignalIdInput).text.Where((char c) => char.IsDigit(c)), (Func<char, string>)null, "")) * -1;
			if (UserDictionary.Instance.terms.ContainsKey(num))
			{
				popupBox.PopupWithLabel("Duplicate signal: " + num);
				return;
			}
			string text = ((TMP_Text)newSignalNameInput).text.Trim(' ').Trim('\u200b');
			if (UserDictionary.Instance.keys.ContainsKey(text))
			{
				popupBox.PopupWithLabel("Duplicate name: " + text);
			}
			else if (UserDictionary.Instance.AddEntry(text, num))
			{
				dictionaryWindow.UpdateToAddEntry(num, text, "?");
				popupBox.PopupWithLabel("Added signal");
				((TMP_Text)newSignalIdInput).text = "-";
				((TMP_Text)newSignalNameInput).text = "";
				autosaver.Autosave(PuzzleManager.Instance);
				if (num == -577)
				{
					ShowSongStuff();
				}
			}
			else
			{
				popupBox.PopupWithLabel("Failed to add signal");
			}
		}

		private void CopySignals()
		{
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Expected O, but got Unknown
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			if (RelayWindow.receivedMessages.Count <= 0)
			{
				popupBox.PopupWithLabel("No msg to try select");
				return;
			}
			if (!short.TryParse(((TMP_Text)messageSelectorInput).text.Trim(' ').Trim('\u200b'), out var selectedMessageId))
			{
				popupBox.PopupWithLabel("Msg ID must be an integer");
				return;
			}
			int num = RelayWindow.activeChannel.FindIndex(0, (RelayMessage x) => x.TransmissionId == selectedMessageId);
			if (num < 0)
			{
				popupBox.PopupWithLabel("Msg " + selectedMessageId + " not in active channel");
				return;
			}
			RelayMessage relayMessage = RelayWindow.activeChannel[num];
			if (Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305))
			{
				GUIUtility.systemCopyBuffer = string.Join(' ', relayMessage.Signals.signals);
				popupBox.PopupWithLabel("Copied signals");
				return;
			}
			CompilerResult val = new CompilerResult();
			List<string> list = ConsoleDisplay.Instance.compiler.CompileSignalToString(relayMessage.Signals, ref val);
			string text = "";
			for (int num2 = 0; num2 < list.Count; num2++)
			{
				text = ((num2 != list.Count - 1) ? (text + list[num2] + "\n") : (text + list[num2]));
			}
			GUIUtility.systemCopyBuffer = text.ToUpper();
			popupBox.PopupWithLabel("Copied msg text");
		}

		private void ViewVisual()
		{
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			if (RelayWindow.receivedMessages.Count <= 0)
			{
				popupBox.PopupWithLabel("No msg to try select");
				return;
			}
			if (!short.TryParse(((TMP_Text)messageSelectorInput).text.Trim(' ').Trim('\u200b'), out var selectedMessageId))
			{
				popupBox.PopupWithLabel("Msg ID must be an integer");
				return;
			}
			int num = RelayWindow.activeChannel.FindIndex(0, (RelayMessage x) => x.TransmissionId == selectedMessageId);
			if (num < 0)
			{
				popupBox.PopupWithLabel("Msg " + selectedMessageId + " not in active channel");
				return;
			}
			RelayMessage relayMessage = RelayWindow.activeChannel[num];
			Puzzle val = ScriptableObject.CreateInstance<Puzzle>();
			val.rockOutput = relayMessage.Signals;
			bool flag = false;
			int[] signals = val.rockOutput.signals;
			for (int num2 = 0; num2 < signals.Length; num2++)
			{
				if (signals[num2] == -53 && num2 < signals.Length - 1 && signals[num2 + 1] == -14)
				{
					flag = true;
					visualWindow.validVisuals = new List<int>();
					visualWindow.validVisuals.Add(num2);
					break;
				}
			}
			if (!flag)
			{
				popupBox.PopupWithLabel("Msg " + selectedMessageId + " has no visual data");
				return;
			}
			visualWindow.QueueDraw(val);
			visualWindow.currDrawPuzzle = val;
			visualWindow.visualDetectedPopup.Popup();
			infoDisplay.SwitchWindow(infoDisplay.visualWindow);
		}

		private void PlayStopSong()
		{
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			if (SongPlayer.IsPlaying)
			{
				songPlayer.StopSong();
				((TMP_Text)playMessageSongText).text = "Play";
				((TMP_Text)messageTimeText).text = "";
				return;
			}
			if (RelayWindow.receivedMessages.Count <= 0)
			{
				popupBox.PopupWithLabel("No msg to try select");
				return;
			}
			if (!short.TryParse(((TMP_Text)messageSelectorInput).text.Trim(' ').Trim('\u200b'), out var selectedMessageId))
			{
				popupBox.PopupWithLabel("Msg ID must be an integer");
				return;
			}
			int num = RelayWindow.activeChannel.FindIndex(0, (RelayMessage x) => x.TransmissionId == selectedMessageId);
			if (num < 0)
			{
				popupBox.PopupWithLabel("Msg " + selectedMessageId + " not in active channel");
				return;
			}
			RelayMessage relayMessage = RelayWindow.activeChannel[num];
			if (!songPlayer.TryPlaySong(relayMessage.Signals))
			{
				popupBox.PopupWithLabel("Failed to parse song");
			}
			else
			{
				((TMP_Text)playMessageSongText).text = "Stop";
			}
		}

		public static void SetSongDurationLabel(string durationLabel)
		{
			((TMP_Text)messageTimeText).text = durationLabel;
		}

		private static void HideSongStuff()
		{
			playMessageSongButton.SetActive(false);
		}

		private static void ShowSongStuff()
		{
			playMessageSongButton.SetActive(true);
		}

		private static void CycleChannel(int dir)
		{
			currChannelIndex += dir;
			if (currChannelIndex >= enabledChannels.Count)
			{
				currChannelIndex = 0;
			}
			if (currChannelIndex < 0)
			{
				currChannelIndex = enabledChannels.Count - 1;
			}
			((TMP_Text)currentChannelLabel).text = enabledChannels[currChannelIndex].name;
			RelayWindow.SetActiveChannel(enabledChannels[currChannelIndex].id);
		}

		private static void SaveEnabledChannels()
		{
			string text = Path.Join(Application.persistentDataPath.AsSpan(), "/TRFDS".AsSpan());
			if (!Directory.Exists(text))
			{
				Directory.CreateDirectory(text);
			}
			string path = Path.Join(text.AsSpan(), "enabledChannels.save".AsSpan());
			string contents = GeneralExtensions.Join<int>(from x in enabledChannels
				select x.id into x
				where x != 0
				select x, (Func<int, string>)null, ",");
			File.WriteAllText(path, contents);
		}

		private static void LoadEnabledChannels()
		{
			string path = Path.Join(Application.persistentDataPath.AsSpan(), "/TRFDS/enabledChannels.save".AsSpan());
			if (File.Exists(path))
			{
				int[] array = (from x in File.ReadAllText(path).Split(',')
					select int.Parse(x)).ToArray();
				foreach (int num2 in array)
				{
					enabledChannels.Add((num2, UserDictionary.Instance.GetWordFromInt(num2)));
				}
			}
		}

		private static void SwitchToManager()
		{
			relayManagerViewport.SetActive(true);
			relayInputViewport.SetActive(false);
		}

		private static void SwitchToInput()
		{
			relayManagerViewport.SetActive(false);
			relayInputViewport.SetActive(true);
		}
	}
	[HarmonyPatch]
	public class RelayWindow
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__LogOut;

			public static UnityAction <1>__Recompile;
		}

		private const float LinesPerPage = 12.315f;

		public static Dictionary<int, List<RelayMessage>> receivedMessages;

		public static List<RelayMessage> activeChannel;

		private static GameObject relayRoot;

		private static GameObject recompileButton;

		private static TextMeshPro relayOutput;

		private static ScrollBar3D scrollbar;

		private static ScrollArea scrollArea;

		private static float lineHeight;

		private static float totalDisplayHeight;

		private static CalculatorWindow calculatorWindow;

		private static Oscilloscope relayOutputOscilloscope;

		private static OverheadLight overheadLight;

		[HarmonyPatch(typeof(ConsoleDisplay), "Awake")]
		[HarmonyPostfix]
		public static void Init(ConsoleDisplay __instance)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Expected O, but got Unknown
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Expected O, but got Unknown
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: 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_0170: 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_018b: 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_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: Expected O, but got Unknown
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Expected O, but got Unknown
			//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_043e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Expected O, but got Unknown
			relayRoot = new GameObject("Relay Output");
			calculatorWindow = GameObject.Find("Calculator Window").GetComponent<CalculatorWindow>();
			GameObject obj = Object.Instantiate<GameObject>(__instance.readMessageGroup);
			((Object)obj).name = "Relay Top Bar";
			obj.transform.SetParent(relayRoot.transform);
			obj.transform.position = new Vector3(-27.75f, 5f, -0.005f);
			((TMP_Text)obj.GetComponentInChildren<TextMeshPro>()).text = "Relay";
			Object.Destroy((Object)(object)((Component)obj.transform.Find("Line Numbers")).gameObject);
			Transform obj2 = obj.transform.Find("Respond Button");
			((Object)obj2).name = "Logout Button";
			((Component)obj2).transform.position = new Vector3(-27.05f, 5.675f, 0.257f);
			((TMP_Text)((Component)obj2).GetComponentInChildren<TextMeshPro>()).text = "Logout";
			((Component)obj2).GetComponentInChildren<Button3D>().OnUseButton = new UnityEvent();
			UnityEvent onUseButton = ((Component)obj2).GetComponentInChildren<Button3D>().OnUseButton;
			object obj3 = <>O.<0>__LogOut;
			if (obj3 == null)
			{
				UnityAction val = LogOut;
				<>O.<0>__LogOut = val;
				obj3 = (object)val;
			}
			onUseButton.AddListener((UnityAction)obj3);
			Object.Destroy((Object)(object)((Component)((Component)obj2).transform.Find("Icon")).gameObject);
			UnityHelpers.ScaleMeshVertices(((Component)obj2).GetComponent<MeshFilter>().mesh, 0.7f);
			BoxCollider component = ((Component)obj2).GetComponent<BoxCollider>();
			component.size -= Vector3.right * 0.3f;
			Transform transform = ((Component)obj2).GetComponentInChildren<TextMeshPro>().transform;
			transform.position += Vector3.right * 0.0365f;
			RelayHelpers.AddHotkey(((Component)obj2).GetComponentInChildren<Button3D>(), (KeyCode)306, (KeyCode)108);
			RelayHelpers.AddHotkey(((Component)obj2).GetComponentInChildren<Button3D>(), (KeyCode)305, (KeyCode)108);
			recompileButton = ((Component)obj.transform.GetChild(2)).gameObject;
			((Object)recompileButton).name = "Recompile Button";
			recompileButton.transform.position = new Vector3(-27.95f, 5.675f, 0.257f);
			((TMP_Text)recompileButton.GetComponentInChildren<TextMeshPro>()).text = "Recompile";
			recompileButton.GetComponentInChildren<Button3D>().OnUseButton = new UnityEvent();
			UnityEvent onUseButton2 = recompileButton.GetComponentInChildren<Button3D>().OnUseButton;
			object obj4 = <>O.<1>__Recompile;
			if (obj4 == null)
			{
				UnityAction val2 = Recompile;
				<>O.<1>__Recompile = val2;
				obj4 = (object)val2;
			}
			onUseButton2.AddListener((UnityAction)obj4);
			Object.Destroy((Object)(object)((Component)recompileButton.transform.Find("Icon")).gameObject);
			UnityHelpers.ScaleMeshVertices(recompileButton.GetComponent<MeshFilter>().mesh, 0.85f);
			BoxCollider component2 = recompileButton.GetComponent<BoxCollider>();
			component2.size -= Vector3.right * 0.15f;
			Transform transform2 = recompileButton.GetComponentInChildren<TextMeshPro>().transform;
			transform2.position += Vector3.right * 0.0439f;
			recompileButton.gameObject.SetActive(false);
			RelayHelpers.AddHotkey(recompileButton, (KeyCode)306, (KeyCode)116);
			RelayHelpers.AddHotkey(recompileButton, (KeyCode)305, (KeyCode)116);
			HotkeyManager.Instance.SetButtonHotkeyDictionary();
			Transform obj5 = obj.transform.Find("Output Display");
			((Object)obj5).name = "Relay Output Signals";
			relayOutput = ((Component)obj5).GetComponent<TextMeshPro>();
			((TMP_Text)relayOutput).fontSize = 0.9f;
			((TMP_Text)relayOutput).maxVisibleLines = 0;
			((TMP_Text)relayOutput).maxVisibleCharacters = 0;
			scrollbar = obj.GetComponentInChildren<ScrollBar3D>();
			((Object)scrollbar).name = "Scroll Handle Fucked";
			Transform transform3 = ((Component)scrollbar).transform;
			transform3.position += Vector3.right * 0.5f;
			scrollbar.visuals = ((Component)((Component)scrollbar).transform.Find("Scroll Visuals")).gameObject;
			scrollbar.col = (Collider)(object)((Component)scrollbar).GetComponent<BoxCollider>();
			scrollbar.meshRenderer = ((Component)scrollbar).GetComponentInChildren<MeshRenderer>();
			scrollArea = ((Component)relayOutput).GetComponent<ScrollArea>();
			scrollbar.scrollArea = ((Component)scrollArea).gameObject;
			totalDisplayHeight = ((TMP_Text)relayOutput).rectTransform.sizeDelta.y;
			lineHeight = totalDisplayHeight / 12.315f;
			relayOutputOscilloscope = GameObject.Find("Output Oscilloscope").GetComponent<Oscilloscope>();
			overheadLight = GameObject.Find("Overhead Light").GetComponent<OverheadLight>();
			RelaySocket.CallsignProcessed.AddListener((UnityAction<bool>)delegate(bool goodCallsign)
			{
				if (goodCallsign)
				{
					recompileButton.SetActive(true);
					receivedMessages = new Dictionary<int, List<RelayMessage>>();
					activeChannel = new List<RelayMessage>();
					receivedMessages.Add(0, activeChannel);
					receivedMessages.Add(-65536, new List<RelayMessage>());
				}
			});
			relayRoot.SetActive(false);
		}

		public static void TryShow()
		{
			if (!relayRoot.activeSelf)
			{
				relayRoot.SetActive(true);
				ConsoleDisplay instance = ConsoleDisplay.Instance;
				((Component)instance.display).gameObject.SetActive(false);
				instance.readMessageGroup.gameObject.SetActive(false);
				((Component)instance.inputDisplay).gameObject.SetActive(false);
				instance.responseGroup.gameObject.SetActive(false);
				instance.monitorVisual.OnWipe();
			}
		}

		public static void LogOut()
		{
			relayRoot.SetActive(false);
			recompileButton.SetActive(false);
			((TMP_Text)relayOutput).text = "";
			((TMP_Text)relayOutput).maxVisibleLines = 0;
			((TMP_Text)relayOutput).maxVisibleCharacters = 0;
			receivedMessages = null;
			activeChannel = null;
			RelayManagerWindow.Disconnect();
			ConsoleDisplay instance = ConsoleDisplay.Instance;
			((Component)instance.display).gameObject.SetActive(true);
			instance.readMessageGroup.gameObject.SetActive(true);
			instance.monitorVisual.OnWipe();
		}

		private static string CompileSignalsToString(SignalMessage signalMessage, out CompilerResult compileResult)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			compileResult = new CompilerResult();
			SignalCompiler compiler = ConsoleDisplay.Instance.compiler;
			if (TRFDSPlugin.ShortenVisuals.Value)
			{
				for (int i = 0; i < signalMessage.signals.Length; i++)
				{
					bool num = signalMessage.signals[i] == -53 && signalMessage.signals.ElementAtOrDefault(i + 1) == -14;
					bool flag = signalMessage.signals[i] == -577 && signalMessage.signals.ElementAtOrDefault(i + 1) == -14;
					if (num || flag)
					{
						int num2 = RelayHelpers.FindClosingBraceIndex(signalMessage.signals, i + 1);
						if (num2 >= 0)
						{
							IEnumerable<int> source = signalMessage.signals.Take(i + 2).Concat(new <>z__ReadOnlySingleElementList<int>(-25)).Concat(signalMessage.signals.Skip(num2));
							signalMessage.signals = source.ToArray();
						}
					}
				}
			}
			List<string> list = compiler.CompileSignalToString(signalMessage, ref compileResult);
			string text = "";
			for (int j = 0; j < list.Count; j++)
			{
				text = ((j != list.Count - 1) ? (text + list[j] + "\n") : (text + list[j]));
			}
			return text;
		}

		public static void SetActiveChannel(int channel)
		{
			if (!receivedMessages.ContainsKey(channel))
			{
				receivedMessages.Add(channel, new List<RelayMessage>());
			}
			activeChannel = receivedMessages[channel];
			Recompile();
		}

		private static float HueToRgb(float p, float q, float t)
		{
			if (t < 0f)
			{
				t += 1f;
			}
			else if (t > 1f)
			{
				t -= 1f;
			}
			if (t < 0.166f)
			{
				return (q - p) * 6f * t + p;
			}
			if (t < 0.5f)
			{
				return q;
			}
			if (t < 0.666f)
			{
				return (q - p) * (0.666f - t) * 6f + p;
			}
			return p;
		}

		private static Color GetCallsignColor(int callsign)
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			float num = 137.5f * (float)callsign % 360f / 360f;
			float num2 = 1f;
			float num3 = 0.7f;
			float num4 = num3 + num2 - num3 * num2;
			float p = 2f * num3 - num4;
			float num5 = HueToRgb(p, num4, num + 0.33f);
			float num6 = HueToRgb(p, num4, num);
			float num7 = HueToRgb(p, num4, num - 0.33f);
			return new Color(num5, num6, num7);
		}

		private static string GetPlaintextMessage(short sender, short transmissionId, string text, bool forceNoStartNewline = false)
		{
			//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_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			string text2 = ((activeChannel.Count <= 1 || forceNoStartNewline) ? "" : "\n\n");
			Color callsignColor = GetCallsignColor(int.Parse(calculatorWindow.EuclideanBaseChange((double)sender, 8, 10)));
			string text3 = sender.ToString().PadLeft(4, '0');
			string text4 = transmissionId.ToString().PadLeft(3, '0');
			return text2 + "<color=#" + ColorUtility.ToHtmlStringRGB(callsignColor) + ">" + text3 + "</color> <color=#" + ColorUtility.ToHtmlStringRGB(Color.grey) + ">" + text4 + "</color>\n" + text;
		}

		private static void Recompile()
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			((TMP_Text)relayOutput).text = "";
			((TMP_Text)relayOutput).maxVisibleLines = 0;
			((TMP_Text)relayOutput).maxVisibleCharacters = 0;
			string text = "";
			for (int i = 0; i < activeChannel.Count; i++)
			{
				RelayMessage relayMessage = activeChannel[i];
				CompilerResult compileResult;
				string text2 = CompileSignalsToString(relayMessage.Signals, out compileResult);
				text += GetPlaintextMessage(relayMessage.Sender, relayMessage.TransmissionId, text2, i == 0);
			}
			((MonoBehaviour)relayOutput).StartCoroutine(PrintTextRoutine(text, byChar: false, instant: true));
		}

		public static void PrintText(string text, bool byChar, bool instant)
		{
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: 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)
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f6: 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_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_036d: Unknown result type (might be due to invalid IL or missing references)
			if (text[0] != 'R')
			{
				return;
			}
			if (TRFDSPlugin.RelayTypingDelay.Value <= 0f)
			{
				instant = true;
			}
			bool flag = receivedMessages.Where((KeyValuePair<int, List<RelayMessage>> x) => x.Key != -65536).SelectMany((KeyValuePair<int, List<RelayMessage>> x) => x.Value).Count() < 10;
			if (flag)
			{
				byChar = false;
				if (TRFDSPlugin.ShowInitialMessagesInstantly.Value)
				{
					instant = true;
				}
			}
			Match match = new Regex("^R,([\\d]+),([\\d]+),(.*)$").Match(text);
			string value = match.Groups[1].Value;
			string value2 = match.Groups[2].Value;
			long[] array = (from x in match.Groups[3].Value.Split(',')
				select long.Parse(x)).ToArray();
			List<int> list = new List<int>();
			for (int num = 0; num < array.Length; num++)
			{
				long num2 = array[num];
				if (num2 < int.MinValue)
				{
					TRFDSPlugin.Logger.LogError((object)"Failed to parse message. Someone sent a signal less than int.MaxValue, why ;-;");
					return;
				}
				if (num2 >= 0)
				{
					string text2 = num2.ToString();
					foreach (char c in text2)
					{
						list.Add(c - 48);
					}
				}
				else
				{
					list.Add((int)num2);
				}
			}
			int[] array2 = list.ToArray();
			SignalMessage val = new SignalMessage
			{
				signals = array2
			};
			if (!flag && TRFDSPlugin.PlayConfetti.Value && array.Contains(-702L) && UserDictionary.Instance.terms.ContainsKey(-702))
			{
				GameObject.Find("Confetti L (Controller)").GetComponent<ConfettiCannon>().Fire();
			}
			int num4 = int.Parse(value);
			string s = calculatorWindow.EuclideanBaseChange((double)num4, 10, 8);
			RelayMessage relayMessage = new RelayMessage
			{
				Sender = short.Parse(s),
				TransmissionId = short.Parse(value2),
				Signals = val
			};
			RelayMessage item = relayMessage;
			int key = 0;
			if (val.signals[0] == -65535 && val.signals.Length >= 2)
			{
				key = val.signals[1];
				if (!receivedMessages.ContainsKey(key))
				{
					receivedMessages.Add(key, new List<RelayMessage>());
				}
				RelayMessage relayMessage2 = relayMessage;
				relayMessage2.Signals = new SignalMessage
				{
					signals = array2.Skip(2).ToArray()
				};
				item = relayMessage2;
			}
			receivedMessages[key].Add(item);
			receivedMessages[-65536].Add(relayMessage);
			CompilerResult compileResult;
			string text3 = CompileSignalsToString((activeChannel == receivedMessages[-65536]) ? relayMessage.Signals : item.Signals, out compileResult);
			if (activeChannel == receivedMessages[-65536] || activeChannel == receivedMessages[key])
			{
				string plaintextMessage = GetPlaintextMessage(relayMessage.Sender, relayMessage.TransmissionId, text3);
				((MonoBehaviour)relayOutput).StartCoroutine(PrintTextRoutine(plaintextMessage, byChar, instant));
				if (TRFDSPlugin.Oscilloscopes.Value)
				{
					relayOutputOscilloscope.PlaySignal(val, true);
				}
				if (!flag && num4.ToString() != RelaySocket.Callsign)
				{
					overheadLight.winLoseAS.clip = overheadLight.winClip;
					overheadLight.winLoseAS.Play();
				}
			}
		}

		private static IEnumerator PrintTextRoutine(string text, bool byChar, bool instant)
		{
			TextMeshPro obj = relayOutput;
			((TMP_Text)obj).text = ((TMP_Text)obj).text + text;
			yield return ((MonoBehaviour)relayOutput).StartCoroutine(SetupScrollbar());
			int fullLineCount = ((TMP_Text)relayOutput).textInfo.lineCount;
			int fullCharCount = ((TMP_Text)relayOutput).textInfo.characterCount;
			if (byChar)
			{
				((TMP_Text)relayOutput).maxVisibleLines = fullLineCount;
				for (int i = ((TMP_Text)relayOutput).maxVisibleCharacters; i < fullCharCount; i++)
				{
					((TMP_Text)relayOutput).maxVisibleCharacters = i;
					SFXPlayer.instance.PlayMonitorTypeBlip();
					if (!instant)
					{
						yield return (object)new WaitForSeconds(TRFDSPlugin.RelayTypingDelay.Value);
					}
				}
			}
			else
			{
				((TMP_Text)relayOutput).maxVisibleCharacters = fullCharCount;
				for (int i = ((TMP_Text)relayOutput).maxVisibleLines; i < fullLineCount; i++)
				{
					((TMP_Text)relayOutput).maxVisibleLines = i;
					SFXPlayer.instance.PlayMonitorTypeBlip();
					if (!instant)
					{
						yield return (object)new WaitForSeconds(TRFDSPlugin.RelayTypingDelay.Value);
					}
				}
			}
			((TMP_Text)relayOutput).maxVisibleLines = fullLineCount;
			((TMP_Text)relayOutput).maxVisibleCharacters = fullCharCount;
			yield return ((MonoBehaviour)relayOutput).StartCoroutine(SetupScrollbar());
		}

		private static IEnumerator SetupScrollbar()
		{
			yield return null;
			float num = (float)(((TMP_Text)relayOutput).textInfo.lineCount + 1) * lineHeight;
			float num2 = num / totalDisplayHeight;
			bool num3 = scrollbar.NormalizedScroll <= 0.01f;
			scrollbar.ConfigureHeight(num2, false);
			scrollArea.Configure(scrollbar, lineHeight + num, totalDisplayHeight);
			if (num3)
			{
				scrollbar.ForceScrollTo(0f);
			}
		}
	}
}
namespace TRFDS.MonoBehaviours
{
	public class RelaySocket : MonoBehaviour
	{
		public static UnityEvent<bool> CallsignProcessed = new UnityEvent<bool>();

		public static string? Callsign = null;

		public static bool UpdateCallsign = false;

		public static Queue<string> EnqueuedMessages = new Queue<string>();

		private static ClientWebSocket socket;

		private static CancellationTokenSource cancellationToken;

		private static Queue<string> receivedMessages = new Queue<string>();

		private static Coroutine showMessages;

		private static Encoding ASCII => Encoding.ASCII;

		private async void Start()
		{
			cancellationToken = new CancellationTokenSource();
			socket = new ClientWebSocket();
			try
			{
				if (!(await TryConnect(socket, new Uri(TRFDSPlugin.RelaySource.Value), cancellationToken.Token)))
				{
					CallsignProcessed.Invoke(false);
					Disconnect();
					return;
				}
				CallsignProcessed.Invoke(true);
				Task.Run(() => Receive(socket, cancellationToken.Token));
				Task.Run(() => Send(socket, cancellationToken.Token));
				Task.Run(() => TryUpdateCallsign(socket, cancellationToken.Token));
			}
			catch (OperationCanceledException)
			{
			}
			catch (Exception ex2)
			{
				TRFDSPlugin.Logger.LogError((object)ex2);
			}
		}

		private void Update()
		{
			if (receivedMessages.Count > 0)
			{
				string text = receivedMessages.Dequeue();
				RelayWindow.PrintText(text, text.Length < TRFDSPlugin.RelayTypeCharByCharCutoff.Value, text.Length >= TRFDSPlugin.RelayTypeLineByLineCutoff.Value);
			}
		}

		private IEnumerator ShowMessages()
		{
			yield return (object)new WaitForSeconds(0.1f);
		}

		public void Disconnect()
		{
			cancellationToken?.Cancel();
			socket?.Dispose();
			socket = null;
			cancellationToken?.Dispose();
			cancellationToken = null;
			Object.Destroy((Object)(object)((Component)this).gameObject);
		}

		public static void QueueSend(string compiledMessage)
		{
			EnqueuedMessages.Enqueue(compiledMessage);
		}

		public static async Task Receive(ClientWebSocket socket, CancellationToken token)
		{
			byte[] buffer = new byte[32767];
			Memory<byte> view = new Memory<byte>(buffer);
			while (socket.State == WebSocketState.Open)
			{
				ValueWebSocketReceiveResult valueWebSocketReceiveResult = await socket.ReceiveAsync(view, token);
				if (valueWebSocketReceiveResult.MessageType == WebSocketMessageType.Close)
				{
					await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, token);
					break;
				}
				string text = ASCII.GetString(buffer[0..valueWebSocketReceiveResult.Count]);
				if (text[0] == 'K')
				{
					CallsignProcessed.Invoke(true);
				}
				else if (text[0] == 'U')
				{
					CallsignProcessed.Invoke(true);
				}
				else
				{
					receivedMessages.Enqueue(text);
				}
				Array.Fill(buffer, (byte)0, 0, valueWebSocketReceiveResult.Count);
			}
		}

		public static async Task Send(ClientWebSocket socket, CancellationToken token)
		{
			while (socket.State == WebSocketState.Open)
			{
				if (EnqueuedMessages.Count > 0)
				{
					await socket.SendAsync(ASCII.GetBytes(EnqueuedMessages.Dequeue()).AsMemory(), WebSocketMessageType.Text, endOfMessage: true, token);
				}
			}
		}

		public static async Task TryUpdateCallsign(ClientWebSocket socket, CancellationToken token)
		{
			while (socket.State == WebSocketState.Open)
			{
				if (UpdateCallsign)
				{
					string s = "S," + Callsign + ",0";
					await socket.SendAsync(new Memory<byte>(ASCII.GetBytes(s)), WebSocketMessageType.Text, endOfMessage: true, default(CancellationToken));
					UpdateCallsign = false;
				}
			}
		}

		public static async Task<bool> TryConnect(ClientWebSocket socket, Uri uri, CancellationToken token)
		{
			byte[] confirmationBuffer = new byte[8];
			new Memory<byte>(confirmationBuffer);
			await socket.ConnectAsync(uri, token);
			string s = "S," + Callsign;
			await socket.SendAsync(new Memory<byte>(ASCII.GetBytes(s)), WebSocketMessageType.Text, endOfMessage: true, default(CancellationToken));
			await socket.ReceiveAsync(confirmationBuffer, token);
			return confirmationBuffer[0] == 75;
		}
	}
	public class SongPlayer : MonoBehaviour
	{
		public static UnityEvent OnSongFinished = new UnityEvent();

		private const double FadeTime = 0.01;

		public static SongPlayer Instance;

		public static bool IsPlaying;

		private AudioSource audioSource;

		private MusicNote[] currentSong;

		private double volume;

		private int samplePosition;

		private double[] phases;

		private int outputSampleRate;

		private double songStartTime;

		private double songEndTime;

		private VolumeManager volumeManager;

		private void Awake()
		{
			Instance = this;
			audioSource = ((Component)this).gameObject.AddComponent<AudioSource>();
			volumeManager = UnityHelpers.FindSingleInstanceObject<VolumeManager>();
		}

		public bool TryPlaySong(SignalMessage message)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (Song.TryParse(message.signals, out var song))
			{
				PlaySong(song.Notes.ToArray());
				return true;
			}
			return false;
		}

		private void PlaySong(MusicNote[] notes)
		{
			currentSong = notes;
			volume = (float)volumeManager.sfxUI.level / 100f;
			samplePosition = 0;
			phases = new double[notes.Length];
			outputSampleRate = AudioSettings.outputSampleRate;
			songStartTime = AudioSettings.dspTime;
			double num = 0.0;
			for (int i = 0; i < notes.Length; i++)
			{
				MusicNote musicNote = notes[i];
				if (musicNote.Duration + musicNote.StartTime > num)
				{
					num = musicNote.Duration + musicNote.StartTime;
				}
			}
			songEndTime = songStartTime + num;
			IsPlaying = true;
			MusicManager.Instance.PauseNormalMusic();
			audioSource.Play();
		}

		public void StopSong()
		{
			IsPlaying = false;
			audioSource.Stop();
			MusicManager.Instance.ResumeNormalMusic();
		}

		private void Update()
		{
			if (IsPlaying && AudioSettings.dspTime >= songEndTime)
			{
				audioSource.Stop();
				IsPlaying = false;
				OnSongFinished.Invoke();
				MusicManager.Instance.ResumeNormalMusic();
			}
			if (IsPlaying)
			{
				double value = songEndTime - songStartTime;
				double value2 = AudioSettings.dspTime - songStartTime;
				TimeSpan timeSpan = TimeSpan.FromSeconds(value);
				RelayManagerWindow.SetSongDurationLabel(TimeSpan.FromSeconds(value2).ToString("m\\:ss") + "|" + timeSpan.ToString("m\\:ss"));
			}
		}

		private void OnAudioFilterRead(float[] data, int channels)
		{
			if (!IsPlaying)
			{
				return;
			}
			for (int i = 0; i < data.Length; i += channels)
			{
				double num = (double)samplePosition / (double)outputSampleRate;
				double num2 = 0.0;
				for (int j = 0; j < currentSong.Length; j++)
				{
					MusicNote musicNote = currentSong[j];
					double num3 = num - musicNote.StartTime;
					if (num3 >= 0.0 && num3 < musicNote.Duration)
					{
						double num4 = 0.5;
						double num5 = Math.Min(num3 / 0.01, 1.0);
						double num6 = Math.Min((musicNote.Duration - num3) / 0.01, 1.0);
						num4 *= num5 * num5;
						num4 *= num6 * num6;
						num2 += Math.Sin(phases[j]) * num4;
						phases[j] += musicNote.Frequency * Math.PI * 2.0 / (double)outputSampleRate;
						if (phases[j] >= Math.PI * 2.0)
						{
							phases[j] -= Math.PI * 2.0;
						}
					}
				}
				num2 *= 0.2 * volume;
				for (int k = 0; k < channels; k++)
				{
					data[i + k] += (float)num2;
				}
				samplePosition++;
			}
		}
	}
}
namespace TRFDS.Helpers
{
	public static class RelayHelpers
	{
		public static int FindClosingBraceIndex(int[] signals, int startIndex)
		{
			int num = 0;
			for (int i = startIndex; i < signals.Length; i++)
			{
				switch (signals[i])
				{
				case -14:
					num++;
					break;
				case -15:
					num--;
					break;
				}
				if (num == 0)
				{
					return i;
				}
			}
			return -1;
		}

		public static void AddHotkey(GameObject obj, KeyCode modifier, KeyCode activator)
		{
			//IL_0006: 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)
			AddHotkey(obj.GetComponent<Button3D>(), modifier, activator);
		}

		public static void AddHotkey(Transform obj, KeyCode modifier, KeyCode activator)
		{
			//IL_0006: 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)
			AddHotkey(((Component)obj).GetComponent<Button3D>(), modifier, activator);
		}

		public static void AddHotkey(Button3D button, KeyCode modifier, KeyCode activator)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			HotkeyManager.Instance.recipients = HotkeyManager.Instance.recipients.Append(new HotkeyRecipient
			{
				button = ((Component)button).GetComponent<Button3D>(),
				modifierKey = modifier,
				activatorKey = activator
			}).ToArray();
		}
	}
	public static class UnityHelpers
	{
		public static T FindSingleInstanceObject<T>() where T : MonoBehaviour
		{
			return (from t in Resources.FindObjectsOfTypeAll<Transform>()
				select ((Component)t).GetComponent<T>()).Single((T c) => (Object)(object)c != (Object)null);
		}

		public static T FindSingleInstanceObject<T>(string name) where T : MonoBehaviour
		{
			return (from t in Resources.FindObjectsOfTypeAll<Transform>()
				select ((Component)t).GetComponent<T>()).Single(delegate(T c)
			{
				object obj = c;
				return ((obj != null) ? ((Object)obj).name : null) == name;
			});
		}

		public static T FindFirstInstanceObject<T>() where T : MonoBehaviour
		{
			return (from t in Resources.FindObjectsOfTypeAll<Transform>()
				select ((Component)t).GetComponent<T>()).First((T c) => (Object)(object)c != (Object)null);
		}

		public static void ScaleMeshVertices(Mesh mesh, float xScale = 1f, float yScale = 1f, float zScale = 1f)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			Vector3[] array = (Vector3[])(object)new Vector3[mesh.vertices.Length];
			for (int i = 0; i < mesh.vertices.Length; i++)
			{
				Vector3 val = mesh.vertices[i];
				val.x *= xScale;
				val.y *= yScale;
				val.z *= zScale;
				array[i] = val;
			}
			mesh.vertices = array;
		}
	}
}
namespace TRFDS.DataStructures
{
	public struct RelayMessage
	{
		public short Sender;

		public short TransmissionId;

		public SignalMessage Signals;
	}
	public record struct MusicNote(double StartTime, double Duration, double Frequency);
	public class Song
	{
		private const double ASecondsToSeconds = 0.8069224;

		public List<MusicNote> Notes;

		public double TotalLength
		{
			get
			{
				if (Notes.Count == 0)
				{
					return 0.0;
				}
				return Notes.Max((MusicNote x) => x.StartTime + x.Duration);
			}
		}

		private Song(List<MusicNote> notes)
		{
			Notes = notes;
		}

		private static Song Combine(Song a, Song b)
		{
			List<MusicNote> list = new List<MusicNote>(a.Notes.Count + b.Notes.Count);
			list.AddRange(a.Notes);
			list.AddRange(b.Notes);
			return new Song(list);
		}

		private Song Append(Song other)
		{
			List<MusicNote> list = new List<MusicNote>(Notes.Count + other.Notes.Count);
			list.AddRange(Notes);
			foreach (MusicNote note in other.Notes)
			{
				list.Add(note with
				{
					StartTime = note.StartTime + TotalLength
				});
			}
			return new Song(list);
		}

		private Song ConvertUnits()
		{
			List<MusicNote> list = new List<MusicNote>(Notes.Count);
			foreach (MusicNo