Decompiled source of PortableTerminal v0.1.9

PortableTerminal/portableterminal.dll

Decompiled 15 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.UI;

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

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

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

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace PortableTerminal
{
	[HarmonyPatch(typeof(GrabbableObject), "LateUpdate")]
	internal static class CarryPose
	{
		private static readonly Vector3 Handle = new Vector3(0f, 0.12f, -0.43f);

		[HarmonyPostfix]
		private static void AfterHeldPlacement(GrabbableObject __instance)
		{
			//IL_005b: 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_0084: 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_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			if (__instance.isHeld && !__instance.isPocketed && Object.op_Implicit((Object)(object)__instance.playerHeldBy) && Object.op_Implicit((Object)(object)__instance.parentObject))
			{
				PortableMarker component = ((Component)__instance).GetComponent<PortableMarker>();
				if (Object.op_Implicit((Object)(object)component) && !component.Deployed)
				{
					Transform transform = ((Component)__instance).transform;
					transform.rotation = Quaternion.Euler(0f, ((Component)__instance.playerHeldBy).transform.eulerAngles.y + 90f, 0f) * Quaternion.Euler(90f, 0f, 0f);
					transform.position = __instance.parentObject.position - transform.TransformVector(Handle);
				}
			}
		}
	}
	internal sealed class DisplayBinding : IDisposable
	{
		private readonly Canvas canvas;

		private readonly Terminal sourceTerminal;

		private GameObject? mount;

		private readonly TMP_InputField input;

		private readonly Transform screen;

		private readonly RectTransform rect;

		private readonly Transform parent;

		private readonly Vector3 position;

		private readonly Vector3 scale;

		private readonly Quaternion rotation;

		private readonly Vector2 anchorMin;

		private readonly Vector2 anchorMax;

		private readonly Vector2 pivot;

		private readonly Vector2 size;

		private readonly RenderMode mode;

		private readonly Camera camera;

		private readonly Camera view;

		private readonly bool active;

		private readonly bool canvasEnabled;

		private readonly bool interactable;

		private readonly bool readOnly;

		private readonly Animator? animator;

		private readonly bool animatorEnabled;

		private readonly CanvasGroup? group;

		private readonly float alpha;

		private readonly bool groupInteractable;

		private readonly bool groupBlocks;

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

		private readonly int originalLayer;

		private readonly GameObject? selected;

		private bool disposed;

		private int focusFrames = 2;

		internal DisplayBinding(Terminal terminal, Transform target, Camera view)
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Expected O, but got Unknown
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			sourceTerminal = terminal;
			canvas = terminal.terminalUIScreen;
			input = terminal.screenText;
			if (!Object.op_Implicit((Object)(object)canvas) || !Object.op_Implicit((Object)(object)input))
			{
				throw new InvalidOperationException("Ship terminal UI or input field is unavailable.");
			}
			screen = target;
			this.view = view;
			rect = (RectTransform)((Component)canvas).transform;
			parent = ((Transform)rect).parent;
			position = ((Transform)rect).localPosition;
			rotation = ((Transform)rect).localRotation;
			scale = ((Transform)rect).localScale;
			anchorMin = rect.anchorMin;
			anchorMax = rect.anchorMax;
			pivot = rect.pivot;
			size = rect.sizeDelta;
			mode = canvas.renderMode;
			camera = canvas.worldCamera;
			active = ((Component)canvas).gameObject.activeSelf;
			canvasEnabled = ((Behaviour)canvas).enabled;
			interactable = ((Selectable)input).interactable;
			readOnly = input.readOnly;
			animator = terminal.terminalUIAnimator;
			animatorEnabled = Object.op_Implicit((Object)(object)animator) && ((Behaviour)animator).enabled;
			group = ((Component)canvas).GetComponent<CanvasGroup>();
			if (Object.op_Implicit((Object)(object)group))
			{
				alpha = group.alpha;
				groupInteractable = group.interactable;
				groupBlocks = group.blocksRaycasts;
			}
			originalLayer = ((Component)canvas).gameObject.layer;
			selected = (Object.op_Implicit((Object)(object)EventSystem.current) ? EventSystem.current.currentSelectedGameObject : null);
			if ((Object)(object)selected == (Object)(object)((Component)input).gameObject)
			{
				selected = null;
			}
			Transform[] componentsInChildren = ((Component)canvas).GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				layers[val] = ((Component)val).gameObject.layer;
			}
		}

		internal void Attach()
		{
			//IL_003c: 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_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Expected O, but got Unknown
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			if (disposed)
			{
				throw new ObjectDisposedException("DisplayBinding");
			}
			try
			{
				((Component)canvas).gameObject.SetActive(true);
				((Behaviour)canvas).enabled = true;
				Canvas.ForceUpdateCanvases();
				Rect val = rect.rect;
				float num = Mathf.Max(((Rect)(ref val)).width, 640f);
				val = rect.rect;
				float num2 = Mathf.Max(((Rect)(ref val)).height, 480f);
				if (Object.op_Implicit((Object)(object)animator))
				{
					((Behaviour)animator).enabled = false;
				}
				mount = new GameObject("Portable terminal display mount");
				Object.DontDestroyOnLoad((Object)(object)mount);
				FollowScreen();
				((Transform)rect).SetParent(mount.transform, false);
				canvas.renderMode = (RenderMode)2;
				canvas.worldCamera = view;
				RectTransform obj = rect;
				RectTransform obj2 = rect;
				Vector2 val2 = (rect.pivot = new Vector2(0.5f, 0.5f));
				Vector2 val4 = (obj2.anchorMax = val2);
				obj.anchorMin = val4;
				rect.sizeDelta = new Vector2(num, num2);
				((Transform)rect).localScale = Vector3.one * DisplayLayout.Fit(num, num2);
				((Transform)rect).localPosition = Vector3.zero;
				((Transform)rect).localRotation = Quaternion.identity;
				if (Object.op_Implicit((Object)(object)group))
				{
					group.alpha = 1f;
					CanvasGroup? obj3 = group;
					bool flag = (group.blocksRaycasts = true);
					obj3.interactable = flag;
				}
				((Selectable)input).interactable = true;
				input.readOnly = false;
				MoveLayers();
				Focus();
			}
			catch
			{
				Dispose();
				throw;
			}
		}

		private void FollowScreen()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)mount) && Object.op_Implicit((Object)(object)screen))
			{
				mount.transform.position = screen.position;
				mount.transform.rotation = screen.rotation;
				mount.transform.localScale = screen.lossyScale;
			}
		}

		private void MoveLayers()
		{
			int layer = LayerMask.NameToLayer("Props");
			Transform[] componentsInChildren = ((Component)canvas).GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				if (!layers.ContainsKey(val))
				{
					layers[val] = originalLayer;
				}
				((Component)val).gameObject.layer = layer;
			}
		}

		private void Focus()
		{
			if (Object.op_Implicit((Object)(object)EventSystem.current))
			{
				EventSystem.current.SetSelectedGameObject(((Component)input).gameObject);
			}
			((Selectable)input).Select();
			input.ActivateInputField();
			input.caretPosition = input.text.Length;
		}

		internal void LateTick()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			if (!disposed && Object.op_Implicit((Object)(object)canvas) && Object.op_Implicit((Object)(object)screen))
			{
				FollowScreen();
				((Transform)rect).localPosition = Vector3.zero;
				((Transform)rect).localRotation = Quaternion.identity;
				MoveLayers();
				if (focusFrames-- > 0)
				{
					Focus();
				}
			}
		}

		public void Dispose()
		{
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			if (disposed)
			{
				return;
			}
			disposed = true;
			if (!Object.op_Implicit((Object)(object)canvas))
			{
				if (Object.op_Implicit((Object)(object)mount))
				{
					Object.Destroy((Object)(object)mount);
				}
				return;
			}
			if (!Object.op_Implicit((Object)(object)sourceTerminal))
			{
				Object.Destroy((Object)(object)((Component)canvas).gameObject);
				if (Object.op_Implicit((Object)(object)mount))
				{
					Object.Destroy((Object)(object)mount);
				}
				return;
			}
			input.DeactivateInputField(false);
			((Selectable)input).interactable = interactable;
			input.readOnly = readOnly;
			((Transform)rect).SetParent(parent, false);
			rect.anchorMin = anchorMin;
			rect.anchorMax = anchorMax;
			rect.pivot = pivot;
			rect.sizeDelta = size;
			((Transform)rect).localPosition = position;
			((Transform)rect).localRotation = rotation;
			((Transform)rect).localScale = scale;
			canvas.renderMode = mode;
			canvas.worldCamera = camera;
			((Behaviour)canvas).enabled = canvasEnabled;
			foreach (KeyValuePair<Transform, int> layer in layers)
			{
				if (Object.op_Implicit((Object)(object)layer.Key))
				{
					((Component)layer.Key).gameObject.layer = layer.Value;
				}
			}
			if (Object.op_Implicit((Object)(object)group))
			{
				group.alpha = alpha;
				group.interactable = groupInteractable;
				group.blocksRaycasts = groupBlocks;
			}
			if (Object.op_Implicit((Object)(object)animator))
			{
				((Behaviour)animator).enabled = animatorEnabled;
			}
			((Component)canvas).gameObject.SetActive(active);
			if (Object.op_Implicit((Object)(object)mount))
			{
				Object.Destroy((Object)(object)mount);
			}
			if (Object.op_Implicit((Object)(object)EventSystem.current))
			{
				EventSystem.current.SetSelectedGameObject((Object.op_Implicit((Object)(object)selected) && selected.activeInHierarchy) ? selected : null);
			}
		}
	}
	internal static class KeyboardModel
	{
		internal static void Build(Transform parent, Material sides)
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Expected O, but got Unknown
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_029b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a8: Expected O, but got Unknown
			//IL_02e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e9: 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_030b: Unknown result type (might be due to invalid IL or missing references)
			List<Vector3> vertices;
			List<Vector2> uv;
			List<int> triangles;
			float width;
			float height;
			float depth;
			using (Stream stream = typeof(Plugin).Assembly.GetManifestResourceStream("PortableTerminal.keyboard.png"))
			{
				byte[] array = new byte[stream.Length];
				int num;
				for (int i = 0; i < array.Length; i += num)
				{
					num = stream.Read(array, i, array.Length - i);
					if (num == 0)
					{
						throw new InvalidOperationException("Incomplete keyboard resource.");
					}
				}
				Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
				if (!ImageConversion.LoadImage(val, array))
				{
					throw new InvalidOperationException("Could not load keyboard texture.");
				}
				((Texture)val).wrapMode = (TextureWrapMode)1;
				((Texture)val).filterMode = (FilterMode)0;
				Material val2 = new Material(sides.shader);
				string[] array2 = new string[3] { "_BaseColor", "_UnlitColor", "_Color" };
				foreach (string text in array2)
				{
					if (val2.HasProperty(text))
					{
						val2.SetColor(text, Color.white);
					}
				}
				if (val2.HasProperty("_BaseColorMap"))
				{
					val2.SetTexture("_BaseColorMap", (Texture)(object)val);
				}
				else if (val2.HasProperty("_UnlitColorMap"))
				{
					val2.SetTexture("_UnlitColorMap", (Texture)(object)val);
				}
				else
				{
					val2.mainTexture = (Texture)(object)val;
				}
				if (val2.HasProperty("_Smoothness"))
				{
					val2.SetFloat("_Smoothness", 0.15f);
				}
				val2.renderQueue = 2000;
				vertices = new List<Vector3>();
				uv = new List<Vector2>();
				triangles = new List<int>();
				width = ((Texture)val).width;
				height = ((Texture)val).height;
				depth = 0.5f * height / width;
				Face(0f, 0f, width, height, 0.848f);
				Row(15f, 46f, new float[26]
				{
					16f, 46f, 62f, 89f, 105f, 131f, 148f, 175f, 191f, 217f,
					234f, 260f, 277f, 304f, 320f, 346f, 363f, 390f, 406f, 432f,
					449f, 476f, 492f, 518f, 534f, 602f
				});
				Row(60f, 90f, new float[26]
				{
					16f, 60f, 77f, 104f, 120f, 147f, 164f, 190f, 207f, 234f,
					251f, 278f, 294f, 321f, 338f, 365f, 381f, 408f, 425f, 452f,
					468f, 495f, 512f, 539f, 556f, 601f
				});
				Row(106f, 135f, new float[24]
				{
					16f, 85f, 102f, 129f, 146f, 173f, 190f, 217f, 234f, 261f,
					278f, 305f, 322f, 349f, 366f, 393f, 410f, 437f, 454f, 481f,
					498f, 525f, 542f, 600f
				});
				Row(151f, 180f, new float[20]
				{
					16f, 107f, 124f, 151f, 168f, 195f, 212f, 239f, 256f, 283f,
					300f, 327f, 344f, 371f, 388f, 415f, 432f, 459f, 476f, 600f
				});
				Row(196f, 225f, new float[18]
				{
					16f, 60f, 77f, 104f, 122f, 151f, 170f, 396f, 405f, 432f,
					449f, 479f, 496f, 523f, 540f, 564f, 582f, 602f
				});
				Mesh val3 = new Mesh
				{
					name = "Ship keyboard lettering and key tops"
				};
				val3.SetVertices(vertices);
				val3.SetUVs(0, uv);
				val3.SetTriangles(triangles, 0);
				val3.RecalculateNormals();
				val3.RecalculateBounds();
				GameObject val4 = new GameObject("Ship-style keyboard surface");
				val4.transform.SetParent(parent, false);
				val4.layer = LayerMask.NameToLayer("Props");
				val4.AddComponent<MeshFilter>().sharedMesh = val3;
				((Renderer)val4.AddComponent<MeshRenderer>()).sharedMaterial = val2;
			}
			void Face(float x0, float y0, float x1, float y1, float elevation)
			{
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0031: Unknown result type (might be due to invalid IL or missing references)
				//IL_0048: Unknown result type (might be due to invalid IL or missing references)
				//IL_005f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0088: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00da: Unknown result type (might be due to invalid IL or missing references)
				//IL_0103: Unknown result type (might be due to invalid IL or missing references)
				int count = vertices.Count;
				vertices.Add(Point(x0, y0, elevation));
				vertices.Add(Point(x1, y0, elevation));
				vertices.Add(Point(x0, y1, elevation));
				vertices.Add(Point(x1, y1, elevation));
				uv.Add(new Vector2(x0 / width, 1f - y0 / height));
				uv.Add(new Vector2(x1 / width, 1f - y0 / height));
				uv.Add(new Vector2(x0 / width, 1f - y1 / height));
				uv.Add(new Vector2(x1 / width, 1f - y1 / height));
				triangles.AddRange(new int[6]
				{
					count,
					count + 1,
					count + 2,
					count + 2,
					count + 1,
					count + 3
				});
			}
			Vector3 Point(float x, float y, float elevation)
			{
				//IL_0030: Unknown result type (might be due to invalid IL or missing references)
				return new Vector3((x / width - 0.5f) * 0.5f, elevation, -0.055f + (0.5f - y / height) * depth);
			}
			void Row(float y0, float y1, float[] edges)
			{
				//IL_0052: Unknown result type (might be due to invalid IL or missing references)
				//IL_0088: Unknown result type (might be due to invalid IL or missing references)
				for (int k = 0; k < edges.Length; k += 2)
				{
					float num2 = edges[k];
					float num3 = edges[k + 1];
					GameObject obj = GameObject.CreatePrimitive((PrimitiveType)3);
					((Object)obj).name = "Ship-style raised key";
					obj.transform.SetParent(parent, false);
					obj.transform.localPosition = Point((num2 + num3) * 0.5f, (y0 + y1) * 0.5f, 0.852f);
					obj.transform.localScale = new Vector3((num3 - num2) / width * 0.5f, 0.008f, (y1 - y0) / height * depth);
					obj.layer = LayerMask.NameToLayer("Props");
					Collider component = obj.GetComponent<Collider>();
					component.enabled = false;
					Object.Destroy((Object)(object)component);
					((Renderer)obj.GetComponent<MeshRenderer>()).sharedMaterial = sides;
					Face(num2, y0, num3, y1, 0.8561f);
				}
			}
		}
	}
	internal enum Request : byte
	{
		Deploy = 1,
		Pack,
		Use,
		Release,
		Ping
	}
	[BepInPlugin("achachala.portableterminal", "Portable Terminal", "0.1.9")]
	[BepInDependency("evaisa.lethallib", "1.2.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Id = "achachala.portableterminal";

		public const string Version = "0.1.9";

		private const string Hello = "achachala.portableterminal.hello.v1";

		private const string RequestName = "achachala.portableterminal.request.v1";

		private const string StateName = "achachala.portableterminal.state.v1";

		private const string LeaseName = "achachala.portableterminal.lease.v1";

		private const string PickupName = "achachala.portableterminal.pickup.v1";

		internal static Plugin Instance = null;

		internal readonly Dictionary<ulong, DeviceState> States = new Dictionary<ulong, DeviceState>();

		private readonly Dictionary<ulong, (ulong sender, float deadline)> pendingDeployment = new Dictionary<ulong, (ulong, float)>();

		private readonly RequestGate requests = new RequestGate();

		private readonly TapHold gesture = new TapHold();

		private readonly TerminalLease lease = new TerminalLease();

		internal TerminalBridge Bridge;

		private NetworkManager? network;

		private Harmony harmony;

		private float nextHello;

		private float nextHeartbeat;

		private float nextHostScan;

		private uint sequence;

		private ulong? hoverDevice;

		private float holdStarted;

		private bool holding;

		private GUIStyle? promptStyle;

		internal ulong? LeaseOwner;

		internal ulong? LeaseDevice;

		internal uint LeaseToken;

		internal bool AllowProxyInteraction;

		private static readonly MethodInfo EmptySlotMethod = AccessTools.Method(typeof(PlayerControllerB), "FirstEmptyItemSlot", (Type[])null, (Type[])null);

		private static readonly MethodInfo GrabMethod = AccessTools.Method(typeof(PlayerControllerB), "BeginGrabObject", (Type[])null, (Type[])null);

		private static readonly FieldInfo RayField = AccessTools.Field(typeof(PlayerControllerB), "interactRay");

		private const string SoundName = "achachala.portableterminal.sound.v2";

		internal bool Server
		{
			get
			{
				if (Object.op_Implicit((Object)(object)network))
				{
					return network.IsServer;
				}
				return false;
			}
		}

		internal PlayerControllerB? Local
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)GameNetworkManager.Instance))
				{
					return null;
				}
				return GameNetworkManager.Instance.localPlayerController;
			}
		}

		internal Terminal? ShipTerminal => Object.FindObjectOfType<Terminal>();

		private static int EmptySlot(PlayerControllerB player, GrabbableObject item)
		{
			return (int)EmptySlotMethod.Invoke(player, new object[1] { item });
		}

		private void Awake()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			Instance = this;
			Bridge = new TerminalBridge(this);
			TerminalAudio.Load();
			PortableItem.Register();
			harmony = new Harmony("achachala.portableterminal");
			harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Portable Terminal 0.1.9 loaded. Price: 250 credits. Host and all clients must install it.");
		}

		internal void Info(string text)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)text);
		}

		internal void Error(string text, Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)(text + ": " + ex));
		}

		private unsafe void Update()
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Expected O, but got Unknown
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Expected O, but got Unknown
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Expected O, but got Unknown
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Expected O, but got Unknown
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Expected O, but got Unknown
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Expected O, but got Unknown
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)network != (Object)(object)singleton || (Object.op_Implicit((Object)(object)network) && !network.IsListening))
			{
				Detach();
			}
			if (!Object.op_Implicit((Object)(object)singleton) || !singleton.IsListening || singleton.CustomMessagingManager == null)
			{
				return;
			}
			if (!Object.op_Implicit((Object)(object)network))
			{
				network = singleton;
				CustomMessagingManager customMessagingManager = singleton.CustomMessagingManager;
				customMessagingManager.RegisterNamedMessageHandler("achachala.portableterminal.sound.v2", new HandleNamedMessageDelegate(ReceiveSound));
				customMessagingManager.RegisterNamedMessageHandler("achachala.portableterminal.hello.v1", new HandleNamedMessageDelegate(ReceiveHello));
				customMessagingManager.RegisterNamedMessageHandler("achachala.portableterminal.request.v1", new HandleNamedMessageDelegate(ReceiveRequest));
				customMessagingManager.RegisterNamedMessageHandler("achachala.portableterminal.state.v1", new HandleNamedMessageDelegate(ReceiveState));
				customMessagingManager.RegisterNamedMessageHandler("achachala.portableterminal.lease.v1", new HandleNamedMessageDelegate(ReceiveLease));
				customMessagingManager.RegisterNamedMessageHandler("achachala.portableterminal.pickup.v1", new HandleNamedMessageDelegate(ReceivePickup));
				nextHello = (nextHostScan = 0f);
			}
			if (Server && Time.unscaledTime >= nextHostScan)
			{
				nextHostScan = Time.unscaledTime + 0.15f;
				HostTick();
			}
			else if (!Server && Time.unscaledTime >= nextHello)
			{
				nextHello = Time.unscaledTime + 2f;
				FastBufferWriter writer = default(FastBufferWriter);
				((FastBufferWriter)(ref writer))..ctor(1, (Allocator)2, -1);
				try
				{
					byte b = 1;
					((FastBufferWriter)(ref writer)).WriteValueSafe<byte>(ref b, default(ForPrimitives));
					Send("achachala.portableterminal.hello.v1", 0uL, writer);
				}
				finally
				{
					((IDisposable)(*(FastBufferWriter*)(&writer))/*cast due to .constrained prefix*/).Dispose();
				}
			}
			DeviceState[] array = States.Values.ToArray();
			foreach (DeviceState deviceState in array)
			{
				PortableMarker portableMarker = Find(deviceState.Id);
				if (Object.op_Implicit((Object)(object)portableMarker) && portableMarker.Revision != deviceState.Revision)
				{
					portableMarker.Apply(deviceState);
				}
			}
			Bridge.Tick();
			if (LeaseOwner == network.LocalClientId && Time.unscaledTime >= nextHeartbeat)
			{
				nextHeartbeat = Time.unscaledTime + 1f;
				Submit(Request.Ping, LeaseDevice.Value, LeaseToken);
			}
			InputTick();
		}

		internal PortableMarker? Find(ulong id)
		{
			if (!Object.op_Implicit((Object)(object)network) || network.SpawnManager == null || !network.SpawnManager.SpawnedObjects.TryGetValue(id, out var value))
			{
				return null;
			}
			if (!Object.op_Implicit((Object)(object)value))
			{
				return null;
			}
			return ((Component)value).GetComponent<PortableMarker>();
		}

		private IEnumerable<PortableMarker> Devices()
		{
			return from obj in network.SpawnManager.SpawnedObjects.Values
				where Object.op_Implicit((Object)(object)obj) && obj.IsSpawned
				select ((Component)obj).GetComponent<PortableMarker>() into marker
				where Object.op_Implicit((Object)(object)marker)
				select marker;
		}

		private PlayerControllerB? Player(ulong client)
		{
			if (!Object.op_Implicit((Object)(object)StartOfRound.Instance))
			{
				return null;
			}
			return ((IEnumerable<PlayerControllerB>)StartOfRound.Instance.allPlayerScripts).FirstOrDefault((Func<PlayerControllerB, bool>)((PlayerControllerB p) => Object.op_Implicit((Object)(object)p) && p.actualClientId == client && p.isPlayerControlled));
		}

		private void HostTick()
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)StartOfRound.Instance))
			{
				return;
			}
			PortableMarker[] array = Devices().ToArray();
			foreach (PortableMarker portableMarker in array)
			{
				GrabbableObject component = ((Component)portableMarker).GetComponent<GrabbableObject>();
				NetworkObject component2 = ((Component)portableMarker).GetComponent<NetworkObject>();
				if (!States.ContainsKey(component2.NetworkObjectId))
				{
					DeviceState deviceState = MakeState(portableMarker, deployed: false, ((Component)portableMarker).transform.position, ((Component)portableMarker).transform.eulerAngles);
					States[component2.NetworkObjectId] = deviceState;
					portableMarker.Apply(deviceState);
				}
				if (portableMarker.RestoreDeployed && !component.isHeld && Time.unscaledTime > portableMarker.Created + 0.75f)
				{
					portableMarker.RestoreDeployed = false;
					Change(portableMarker, deployed: true, ((Component)portableMarker).transform.position, ((Component)portableMarker).transform.eulerAngles, audible: false);
				}
			}
			KeyValuePair<ulong, (ulong, float)>[] array2 = pendingDeployment.ToArray();
			for (int i = 0; i < array2.Length; i++)
			{
				KeyValuePair<ulong, (ulong, float)> keyValuePair = array2[i];
				PortableMarker portableMarker2 = Find(keyValuePair.Key);
				PlayerControllerB val = Player(keyValuePair.Value.Item1);
				if (!Object.op_Implicit((Object)(object)portableMarker2) || !Object.op_Implicit((Object)(object)val) || val.isPlayerDead || Time.unscaledTime > keyValuePair.Value.Item2)
				{
					pendingDeployment.Remove(keyValuePair.Key);
				}
				else if (!((Component)portableMarker2).GetComponent<GrabbableObject>().isHeld && !InventoryContains(val, keyValuePair.Key))
				{
					Vector3 position = FloorPoint(val, 1.45f);
					Change(portableMarker2, deployed: true, position, new Vector3(0f, ((Component)val).transform.eulerAngles.y, 0f));
					pendingDeployment.Remove(keyValuePair.Key);
				}
			}
			ulong[] array3 = States.Keys.ToArray();
			foreach (ulong num in array3)
			{
				if (!Object.op_Implicit((Object)(object)Find(num)))
				{
					States.Remove(num);
				}
			}
			if (lease.Owner.HasValue)
			{
				PlayerControllerB val2 = Player(lease.Owner.Value);
				PortableMarker portableMarker3 = Find(lease.Device.Value);
				if (!Object.op_Implicit((Object)(object)val2) || val2.isPlayerDead || !Object.op_Implicit((Object)(object)portableMarker3) || !portableMarker3.Deployed || Vector3.Distance(((Component)val2).transform.position, ((Component)portableMarker3).transform.position) > 4f || lease.Expired(Time.unscaledTime))
				{
					EndLease();
				}
			}
		}

		private static bool InventoryContains(PlayerControllerB player, ulong id)
		{
			if (player.ItemSlots == null || !player.ItemSlots.Any((GrabbableObject item) => Object.op_Implicit((Object)(object)item) && ((NetworkBehaviour)item).NetworkObjectId == id))
			{
				if (Object.op_Implicit((Object)(object)player.ItemOnlySlot))
				{
					return ((NetworkBehaviour)player.ItemOnlySlot).NetworkObjectId == id;
				}
				return false;
			}
			return true;
		}

		private static Vector3 FloorPoint(PlayerControllerB player, float ahead)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: 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_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = ((Component)player).transform.position + ((Component)player).transform.forward * ahead + Vector3.up * 0.8f;
			RaycastHit val2 = default(RaycastHit);
			if (Physics.Linecast(((Component)player).transform.position + Vector3.up * 0.5f, val, ref val2, LayerMask.GetMask(new string[2] { "Room", "Colliders" }), (QueryTriggerInteraction)1))
			{
				val = ((RaycastHit)(ref val2)).point - ((Component)player).transform.forward * 0.4f + Vector3.up * 0.6f;
			}
			RaycastHit val3 = default(RaycastHit);
			if (Physics.Raycast(val, Vector3.down, ref val3, 3f, LayerMask.GetMask(new string[3] { "Room", "Colliders", "Railing" }), (QueryTriggerInteraction)1))
			{
				return ((RaycastHit)(ref val3)).point + Vector3.up * 0.08f;
			}
			return ((Component)player).transform.position + ((Component)player).transform.forward * 0.65f + Vector3.up * 0.08f;
		}

		private DeviceState MakeState(PortableMarker marker, bool deployed, Vector3 world, Vector3 rotation)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: 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_0028: 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_002d: 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_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			StartOfRound instance = StartOfRound.Instance;
			Bounds bounds = instance.shipInnerRoomBounds.bounds;
			bool flag = ((Bounds)(ref bounds)).Contains(world);
			Vector3 val = (flag ? instance.elevatorTransform.InverseTransformPoint(world) : world);
			if (flag)
			{
				rotation -= instance.elevatorTransform.eulerAngles;
			}
			return new DeviceState
			{
				Id = ((Component)marker).GetComponent<NetworkObject>().NetworkObjectId,
				Revision = marker.Revision + 1,
				Deployed = deployed,
				InShip = flag,
				X = val.x,
				Y = val.y,
				Z = val.z,
				Pitch = rotation.x,
				Yaw = rotation.y,
				Roll = rotation.z
			};
		}

		private void Change(PortableMarker marker, bool deployed, Vector3 position, Vector3 rotation, bool audible = true)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: 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_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			bool flag = TransitionSound.ShouldPlay(marker.Deployed, deployed, audible);
			DeviceState deviceState = MakeState(marker, deployed, position, rotation);
			States[deviceState.Id] = deviceState;
			marker.Apply(deviceState);
			foreach (ulong connectedClientsId in network.ConnectedClientsIds)
			{
				if (connectedClientsId != network.LocalClientId)
				{
					SendState(connectedClientsId, deviceState);
				}
			}
			if (flag)
			{
				PlayTransition(position + Vector3.up * 1.6f, deployed);
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("Portable terminal {0}: {1}.", deviceState.Id, deployed ? "deployed" : "packed"));
		}

		private unsafe void PlayTransition(Vector3 position, bool deploying)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			TerminalAudio.Play(position, deploying);
			FastBufferWriter writer = default(FastBufferWriter);
			foreach (ulong connectedClientsId in network.ConnectedClientsIds)
			{
				if (connectedClientsId != network.LocalClientId)
				{
					((FastBufferWriter)(ref writer))..ctor(13, (Allocator)2, -1);
					try
					{
						byte b = (deploying ? ((byte)1) : ((byte)0));
						((FastBufferWriter)(ref writer)).WriteValueSafe<byte>(ref b, default(ForPrimitives));
						((FastBufferWriter)(ref writer)).WriteValueSafe<float>(ref position.x, default(ForPrimitives));
						((FastBufferWriter)(ref writer)).WriteValueSafe<float>(ref position.y, default(ForPrimitives));
						((FastBufferWriter)(ref writer)).WriteValueSafe<float>(ref position.z, default(ForPrimitives));
						Send("achachala.portableterminal.sound.v2", connectedClientsId, writer);
					}
					finally
					{
						((IDisposable)(*(FastBufferWriter*)(&writer))/*cast due to .constrained prefix*/).Dispose();
					}
				}
			}
		}

		private void ReceiveSound(ulong sender, FastBufferReader reader)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			if (Server || sender != 0L || ((FastBufferReader)(ref reader)).Length - ((FastBufferReader)(ref reader)).Position != 13 || !((FastBufferReader)(ref reader)).TryBeginRead(13))
			{
				return;
			}
			byte b = default(byte);
			((FastBufferReader)(ref reader)).ReadValueSafe<byte>(ref b, default(ForPrimitives));
			if (b <= 1)
			{
				float num = default(float);
				((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref num, default(ForPrimitives));
				float num2 = default(float);
				((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref num2, default(ForPrimitives));
				float num3 = default(float);
				((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref num3, default(ForPrimitives));
				if (!float.IsNaN(num) && !float.IsInfinity(num) && !float.IsNaN(num2) && !float.IsInfinity(num2) && !float.IsNaN(num3) && !float.IsInfinity(num3))
				{
					TerminalAudio.Play(new Vector3(num, num2, num3), b == 1);
				}
			}
		}

		internal void DeployHeld(GrabbableObject grab)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			PlayerControllerB local = Local;
			if (Object.op_Implicit((Object)(object)network) && Object.op_Implicit((Object)(object)local) && ((NetworkBehaviour)local).IsOwner && !local.isPlayerDead && grab.isHeld && InventoryContains(local, ((NetworkBehaviour)grab).NetworkObjectId) && !local.inTerminalMenu)
			{
				ulong networkObjectId = ((NetworkBehaviour)grab).NetworkObjectId;
				Submit(Request.Deploy, networkObjectId);
				local.DiscardHeldObject(false, (NetworkObject)null, default(Vector3), true);
			}
		}

		private void InputTick()
		{
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			hoverDevice = null;
			holding = false;
			PlayerControllerB local = Local;
			if (!Object.op_Implicit((Object)(object)local) || local.isPlayerDead || !local.isPlayerControlled || local.inTerminalMenu || local.isTypingChat || local.quickMenuManager.isMenuOpen)
			{
				gesture.Cancel();
				return;
			}
			InputAction val = (Object.op_Implicit((Object)(object)IngamePlayerSettings.Instance) ? IngamePlayerSettings.Instance.playerInput.actions.FindAction("Interact", false) : null);
			if (val == null)
			{
				return;
			}
			PortableMarker portableMarker = null;
			RaycastHit val2 = default(RaycastHit);
			if (Physics.Raycast(((Component)local.gameplayCamera).transform.position, ((Component)local.gameplayCamera).transform.forward, ref val2, 3.5f, LayerMask.GetMask(new string[4] { "InteractableObject", "Props", "Room", "Colliders" }), (QueryTriggerInteraction)2))
			{
				portableMarker = ((Component)((RaycastHit)(ref val2)).collider).GetComponentInParent<PortableMarker>();
			}
			ulong? lookingAt = (hoverDevice = ((Object.op_Implicit((Object)(object)portableMarker) && portableMarker.Deployed) ? new ulong?(((Component)portableMarker).GetComponent<NetworkObject>().NetworkObjectId) : ((ulong?)null)));
			if (lookingAt.HasValue)
			{
				if (val.WasPressedThisFrame())
				{
					holdStarted = Time.unscaledTime;
				}
				holding = val.IsPressed();
			}
			GestureResult gestureResult = gesture.Tick(lookingAt, val.WasPressedThisFrame(), val.IsPressed(), val.WasReleasedThisFrame(), Time.unscaledTime);
			if (gestureResult != GestureResult.None && lookingAt.HasValue)
			{
				if (LeaseOwner.HasValue || (gestureResult == GestureResult.Tap && Object.op_Implicit((Object)(object)ShipTerminal) && ShipTerminal.terminalInUse))
				{
					HUDManager.Instance.DisplayTip("Terminal busy", "Someone is already using the shared ship terminal.", false, false, "LC_Tip1");
				}
				else if (gestureResult == GestureResult.Hold && Object.op_Implicit((Object)(object)portableMarker) && EmptySlot(local, ((Component)portableMarker).GetComponent<GrabbableObject>()) < 0)
				{
					HUDManager.Instance.DisplayTip("Inventory full", "Free an inventory slot before packing up the terminal.", false, false, "LC_Tip1");
				}
				else
				{
					Submit((gestureResult == GestureResult.Hold) ? Request.Pack : Request.Use, lookingAt.Value);
				}
			}
		}

		private void LateUpdate()
		{
			Bridge?.LateTick();
		}

		private void OnGUI()
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: 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)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Expected O, but got Unknown
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			if (hoverDevice.HasValue && Object.op_Implicit((Object)(object)network))
			{
				float num = Mathf.Clamp((float)Screen.height / 1080f, 0.7f, 2f);
				float num2 = Mathf.Min(440f * num, (float)Screen.width - 24f);
				Rect val = default(Rect);
				((Rect)(ref val))..ctor(((float)Screen.width - num2) * 0.5f, (float)Screen.height * 0.73f, num2, 96f * num);
				GUI.Box(val, "");
				if (promptStyle == null)
				{
					promptStyle = new GUIStyle(GUI.skin.label)
					{
						alignment = (TextAnchor)4,
						fontStyle = (FontStyle)1,
						wordWrap = true
					};
				}
				promptStyle.fontSize = Mathf.RoundToInt(17f * num);
				bool hasValue = LeaseOwner.HasValue;
				string text = (hasValue ? "PORTABLE TERMINAL\nTerminal in use" : "Tap interact to use the terminal. Hold to pick up");
				GUI.Label(val, text, promptStyle);
				if (holding && !hasValue)
				{
					Color color = GUI.color;
					GUI.color = new Color(0.45f, 0.95f, 0.65f);
					GUI.DrawTexture(new Rect(((Rect)(ref val)).x + 8f, ((Rect)(ref val)).yMax - 6f * num, (((Rect)(ref val)).width - 16f) * Mathf.Clamp01((Time.unscaledTime - holdStarted) / 0.8f), 3f * num), (Texture)(object)Texture2D.whiteTexture);
					GUI.color = color;
				}
			}
		}

		internal void ReleaseLocal()
		{
			if (Object.op_Implicit((Object)(object)network) && LeaseOwner == network.LocalClientId && LeaseDevice.HasValue)
			{
				Submit(Request.Release, LeaseDevice.Value, LeaseToken);
			}
		}

		private unsafe void Submit(Request action, ulong id, uint token = 0u)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)network))
			{
				return;
			}
			uint seq = ++sequence;
			if (Server)
			{
				Handle(network.LocalClientId, action, id, seq, token);
				return;
			}
			FastBufferWriter writer = default(FastBufferWriter);
			((FastBufferWriter)(ref writer))..ctor(17, (Allocator)2, -1);
			try
			{
				byte b = (byte)action;
				((FastBufferWriter)(ref writer)).WriteValueSafe<byte>(ref b, default(ForPrimitives));
				((FastBufferWriter)(ref writer)).WriteValueSafe<ulong>(ref id, default(ForPrimitives));
				((FastBufferWriter)(ref writer)).WriteValueSafe<uint>(ref seq, default(ForPrimitives));
				((FastBufferWriter)(ref writer)).WriteValueSafe<uint>(ref token, default(ForPrimitives));
				Send("achachala.portableterminal.request.v1", 0uL, writer);
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&writer))/*cast due to .constrained prefix*/).Dispose();
			}
		}

		private void ReceiveRequest(ulong sender, FastBufferReader reader)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			if (Server && ((FastBufferReader)(ref reader)).TryBeginRead(17))
			{
				byte action = default(byte);
				((FastBufferReader)(ref reader)).ReadValueSafe<byte>(ref action, default(ForPrimitives));
				ulong id = default(ulong);
				((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref id, default(ForPrimitives));
				uint seq = default(uint);
				((FastBufferReader)(ref reader)).ReadValueSafe<uint>(ref seq, default(ForPrimitives));
				uint token = default(uint);
				((FastBufferReader)(ref reader)).ReadValueSafe<uint>(ref token, default(ForPrimitives));
				Handle(sender, (Request)action, id, seq, token);
			}
		}

		private unsafe void Handle(ulong sender, Request action, ulong id, uint seq, uint token)
		{
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)network) || !Server || !network.ConnectedClients.ContainsKey(sender) || !requests.TryAccept(sender, seq, Time.unscaledTime, 0.05))
			{
				return;
			}
			switch (action)
			{
			case Request.Release:
				if (lease.Owner == sender && lease.Token == token)
				{
					EndLease();
				}
				return;
			case Request.Ping:
				lease.Touch(sender, token, Time.unscaledTime);
				return;
			}
			PlayerControllerB val = Player(sender);
			PortableMarker portableMarker = Find(id);
			if (!Object.op_Implicit((Object)(object)val) || val.isPlayerDead || !Object.op_Implicit((Object)(object)portableMarker) || !Object.op_Implicit((Object)(object)StartOfRound.Instance) || StartOfRound.Instance.shipIsLeaving || Vector3.Distance(((Component)val).transform.position, ((Component)portableMarker).transform.position) > 3.5f)
			{
				return;
			}
			GrabbableObject component = ((Component)portableMarker).GetComponent<GrabbableObject>();
			switch (action)
			{
			case Request.Deploy:
				if (!portableMarker.Deployed && (((NetworkBehaviour)component).NetworkObject.OwnerClientId == sender || InventoryContains(val, id)))
				{
					pendingDeployment[id] = (sender, Time.unscaledTime + 2f);
				}
				break;
			case Request.Pack:
			{
				if (!portableMarker.Deployed || LeaseDevice == id || EmptySlot(val, component) < 0)
				{
					break;
				}
				Change(portableMarker, deployed: false, FloorPoint(val, 0.7f), new Vector3(0f, ((Component)val).transform.eulerAngles.y, 0f));
				if (sender == network.LocalClientId)
				{
					((MonoBehaviour)this).StartCoroutine(AutoPickup(id, portableMarker.Revision));
					break;
				}
				FastBufferWriter writer = default(FastBufferWriter);
				((FastBufferWriter)(ref writer))..ctor(12, (Allocator)2, -1);
				try
				{
					((FastBufferWriter)(ref writer)).WriteValueSafe<ulong>(ref id, default(ForPrimitives));
					((FastBufferWriter)(ref writer)).WriteValueSafe<uint>(ref portableMarker.Revision, default(ForPrimitives));
					Send("achachala.portableterminal.pickup.v1", sender, writer);
					break;
				}
				finally
				{
					((IDisposable)(*(FastBufferWriter*)(&writer))/*cast due to .constrained prefix*/).Dispose();
				}
			}
			case Request.Use:
			{
				Terminal shipTerminal = ShipTerminal;
				if (portableMarker.Deployed && Object.op_Implicit((Object)(object)shipTerminal) && !shipTerminal.terminalInUse && !lease.Owner.HasValue && !Bridge.ShipTriggerBusy(shipTerminal) && lease.Acquire(sender, id, Time.unscaledTime))
				{
					BroadcastLease();
				}
				break;
			}
			}
		}

		private IEnumerator AutoPickup(ulong id, uint revision)
		{
			float timeout = Time.unscaledTime + 2f;
			PortableMarker marker;
			while (true)
			{
				PortableMarker portableMarker;
				marker = (portableMarker = Find(id));
				if (Object.op_Implicit((Object)(object)portableMarker) && !marker.Deployed && marker.Revision >= revision)
				{
					break;
				}
				if (Time.unscaledTime > timeout)
				{
					yield break;
				}
				yield return null;
			}
			yield return null;
			PlayerControllerB local = Local;
			if (!Object.op_Implicit((Object)(object)local) || local.isPlayerDead || EmptySlot(local, ((Component)marker).GetComponent<GrabbableObject>()) < 0)
			{
				yield break;
			}
			Transform transform = ((Component)local.gameplayCamera).transform;
			Quaternion rotation = transform.rotation;
			object value = RayField.GetValue(local);
			try
			{
				Physics.SyncTransforms();
				Bounds bounds = ((Collider)((Component)marker).GetComponent<BoxCollider>()).bounds;
				Vector3 center = ((Bounds)(ref bounds)).center;
				transform.LookAt(center);
				FieldInfo rayField = RayField;
				Vector3 position = transform.position;
				Vector3 val = center - transform.position;
				rayField.SetValue(local, (object)new Ray(position, ((Vector3)(ref val)).normalized));
				GrabMethod.Invoke(local, null);
			}
			finally
			{
				transform.rotation = rotation;
				RayField.SetValue(local, value);
			}
		}

		private void ReceivePickup(ulong sender, FastBufferReader reader)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			if (!Server && sender == 0L && ((FastBufferReader)(ref reader)).TryBeginRead(12))
			{
				ulong id = default(ulong);
				((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref id, default(ForPrimitives));
				uint revision = default(uint);
				((FastBufferReader)(ref reader)).ReadValueSafe<uint>(ref revision, default(ForPrimitives));
				((MonoBehaviour)this).StartCoroutine(AutoPickup(id, revision));
			}
		}

		private unsafe void SendState(ulong client, DeviceState state)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			byte[] array = state.Encode();
			FastBufferWriter writer = default(FastBufferWriter);
			((FastBufferWriter)(ref writer))..ctor(array.Length, (Allocator)2, -1);
			try
			{
				((FastBufferWriter)(ref writer)).WriteBytesSafe(array, array.Length, 0);
				Send("achachala.portableterminal.state.v1", client, writer);
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&writer))/*cast due to .constrained prefix*/).Dispose();
			}
		}

		private void ReceiveState(ulong sender, FastBufferReader reader)
		{
			if (!Server && sender == 0L && ((FastBufferReader)(ref reader)).Length - ((FastBufferReader)(ref reader)).Position == 38 && ((FastBufferReader)(ref reader)).TryBeginRead(38))
			{
				byte[] array = new byte[38];
				((FastBufferReader)(ref reader)).ReadBytesSafe(ref array, array.Length, 0);
				if (DeviceState.Decode(array, out DeviceState state))
				{
					States[state.Id] = state;
				}
			}
		}

		private void ReceiveHello(ulong sender, FastBufferReader reader)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			if (!Server || !network.ConnectedClients.ContainsKey(sender) || !((FastBufferReader)(ref reader)).TryBeginRead(1))
			{
				return;
			}
			byte b = default(byte);
			((FastBufferReader)(ref reader)).ReadValueSafe<byte>(ref b, default(ForPrimitives));
			if (b != 1)
			{
				return;
			}
			foreach (DeviceState value in States.Values)
			{
				SendState(sender, value);
			}
			SendLease(sender);
		}

		private void EndLease()
		{
			lease.Clear();
			BroadcastLease();
			Terminal shipTerminal = ShipTerminal;
			if (!Object.op_Implicit((Object)(object)shipTerminal))
			{
				return;
			}
			try
			{
				AccessTools.Method(typeof(Terminal), "SetTerminalInUseServerRpc", (Type[])null, (Type[])null).Invoke(shipTerminal, new object[1] { false });
			}
			catch (Exception ex)
			{
				Error("Clearing shared terminal busy state", ex);
			}
		}

		private void BroadcastLease()
		{
			ApplyLease(lease.Owner, lease.Device, lease.Token);
			foreach (ulong connectedClientsId in network.ConnectedClientsIds)
			{
				if (connectedClientsId != network.LocalClientId)
				{
					SendLease(connectedClientsId);
				}
			}
		}

		private unsafe void SendLease(ulong client)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: 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_0096: Unknown result type (might be due to invalid IL or missing references)
			FastBufferWriter writer = default(FastBufferWriter);
			((FastBufferWriter)(ref writer))..ctor(21, (Allocator)2, -1);
			try
			{
				bool hasValue = lease.Owner.HasValue;
				((FastBufferWriter)(ref writer)).WriteValueSafe<bool>(ref hasValue, default(ForPrimitives));
				ulong valueOrDefault = lease.Owner.GetValueOrDefault();
				((FastBufferWriter)(ref writer)).WriteValueSafe<ulong>(ref valueOrDefault, default(ForPrimitives));
				valueOrDefault = lease.Device.GetValueOrDefault();
				((FastBufferWriter)(ref writer)).WriteValueSafe<ulong>(ref valueOrDefault, default(ForPrimitives));
				((FastBufferWriter)(ref writer)).WriteValueSafe<uint>(ref lease.Token, default(ForPrimitives));
				Send("achachala.portableterminal.lease.v1", client, writer);
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&writer))/*cast due to .constrained prefix*/).Dispose();
			}
		}

		private void ReceiveLease(ulong sender, FastBufferReader reader)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			if (!Server && sender == 0L && ((FastBufferReader)(ref reader)).TryBeginRead(21))
			{
				bool flag = default(bool);
				((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag, default(ForPrimitives));
				ulong value = default(ulong);
				((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref value, default(ForPrimitives));
				ulong value2 = default(ulong);
				((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref value2, default(ForPrimitives));
				uint token = default(uint);
				((FastBufferReader)(ref reader)).ReadValueSafe<uint>(ref token, default(ForPrimitives));
				ApplyLease(flag ? new ulong?(value) : ((ulong?)null), flag ? new ulong?(value2) : ((ulong?)null), token);
			}
		}

		private void ApplyLease(ulong? owner, ulong? device, uint token)
		{
			if (LeaseOwner != owner || LeaseDevice != device || LeaseToken != token)
			{
				Bridge.Close();
				LeaseOwner = owner;
				LeaseDevice = device;
				LeaseToken = token;
			}
		}

		private void Send(string name, ulong target, FastBufferWriter writer)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			network.CustomMessagingManager.SendNamedMessage(name, target, writer, (NetworkDelivery)3);
		}

		private void Detach()
		{
			Bridge?.Close();
			if (Object.op_Implicit((Object)(object)network) && network.CustomMessagingManager != null)
			{
				string[] array = new string[6] { "achachala.portableterminal.hello.v1", "achachala.portableterminal.request.v1", "achachala.portableterminal.state.v1", "achachala.portableterminal.lease.v1", "achachala.portableterminal.pickup.v1", "achachala.portableterminal.sound.v2" };
				foreach (string text in array)
				{
					network.CustomMessagingManager.UnregisterNamedMessageHandler(text);
				}
			}
			network = null;
			LeaseOwner = (LeaseDevice = null);
			LeaseToken = 0u;
			States.Clear();
			pendingDeployment.Clear();
			requests.Clear();
			gesture.Cancel();
			hoverDevice = null;
			sequence = 0u;
			((MonoBehaviour)this).StopAllCoroutines();
		}
	}
	[HarmonyPatch(typeof(GrabbableObject), "ItemActivate")]
	internal static class DeployPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(GrabbableObject __instance, bool buttonDown)
		{
			if (!Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<PortableMarker>()))
			{
				return true;
			}
			if (buttonDown)
			{
				Plugin.Instance.DeployHeld(__instance);
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(GrabbableObject), "GetItemDataToSave")]
	internal static class SavePatch
	{
		[HarmonyPostfix]
		private static void Postfix(GrabbableObject __instance, ref int __result)
		{
			PortableMarker component = ((Component)__instance).GetComponent<PortableMarker>();
			if (Object.op_Implicit((Object)(object)component))
			{
				__result = (component.Deployed ? 1 : 0);
			}
		}
	}
	[HarmonyPatch(typeof(GrabbableObject), "LoadItemSaveData")]
	internal static class LoadPatch
	{
		[HarmonyPostfix]
		private static void Postfix(GrabbableObject __instance, int saveData)
		{
			PortableMarker component = ((Component)__instance).GetComponent<PortableMarker>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.RestoreDeployed = saveData == 1;
			}
		}
	}
	[HarmonyPatch(typeof(InteractTrigger), "Interact")]
	internal static class InteractionPatch
	{
		[HarmonyPrefix]
		[HarmonyPriority(800)]
		private static bool Prefix(InteractTrigger __instance)
		{
			Plugin instance = Plugin.Instance;
			if (Object.op_Implicit((Object)(object)((Component)__instance).GetComponentInParent<PortableMarker>()))
			{
				return instance.AllowProxyInteraction;
			}
			return !instance.Bridge.IsLockedShipTrigger(__instance);
		}
	}
	[HarmonyPatch(typeof(Terminal), "QuitTerminal")]
	internal static class QuitPatch
	{
		[HarmonyPostfix]
		private static void Postfix()
		{
			Plugin.Instance.Bridge.OnQuit();
		}
	}
	internal static class PortableItem
	{
		internal static Item Definition;

		internal static void Register()
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Expected O, but got Unknown
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_030b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0310: Unknown result type (might be due to invalid IL or missing references)
			//IL_031a: Unknown result type (might be due to invalid IL or missing references)
			//IL_031f: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c6: Unknown result type (might be due to invalid IL or missing references)
			Assembly assembly = ((object)Chainloader.PluginInfos["evaisa.lethallib"].Instance).GetType().Assembly;
			GameObject val = (GameObject)assembly.GetType("LethalLib.Modules.NetworkPrefabs").GetMethod("CreateNetworkPrefab", new Type[1] { typeof(string) }).Invoke(null, new object[1] { "achachala.portableterminal.Case.v1" });
			uint num = 2166136261u;
			string text = "achachala.portableterminal.Case.v1";
			foreach (char c in text)
			{
				num = (num ^ c) * 16777619;
			}
			typeof(NetworkObject).GetField("GlobalObjectIdHash", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).SetValue(val.GetComponent<NetworkObject>(), num);
			val.tag = "PhysicsProp";
			val.layer = LayerMask.NameToLayer("Props");
			Rigidbody val2 = val.AddComponent<Rigidbody>();
			val2.isKinematic = true;
			val2.useGravity = false;
			val2.mass = 0.4f;
			BoxCollider val3 = val.AddComponent<BoxCollider>();
			val3.center = new Vector3(0f, 0.13f, 0f);
			val3.size = new Vector3(1f, 0.3f, 0.68f);
			val.AddComponent<AudioSource>().playOnAwake = false;
			val.AddComponent<PortableMarker>();
			PortableMarker component = val.GetComponent<PortableMarker>();
			MeshRenderer mainObjectRenderer = PortableModel.Build(val.transform, component);
			Definition = ScriptableObject.CreateInstance<Item>();
			((Object)Definition).name = "RocketPortableItem";
			Definition.itemName = "Portable terminal";
			Definition.itemId = 847292;
			Definition.spawnPrefab = val;
			Definition.creditsWorth = 250;
			Definition.weight = 1.1f;
			Definition.isScrap = false;
			Definition.twoHanded = (Definition.twoHandedAnimation = false);
			Definition.canBeGrabbedBeforeGameStart = true;
			Definition.disallowUtilitySlot = false;
			Definition.saveItemVariable = true;
			Definition.requiresBattery = false;
			Definition.highestSalePercentage = 0;
			Definition.syncGrabFunction = (Definition.syncDiscardFunction = true);
			Definition.grabAnim = (Definition.useAnim = (Definition.pocketAnim = (Definition.throwAnim = "")));
			Definition.grabAnimationTime = 0f;
			Definition.toolTips = new string[1] { "Deploy terminal: [LMB]" };
			Definition.spawnPositionTypes = new List<ItemGroup>();
			Definition.meshVariants = Array.Empty<Mesh>();
			Definition.materialVariants = Array.Empty<Material>();
			Definition.clinkAudios = Array.Empty<AudioClip>();
			Definition.positionOffset = new Vector3(0.05f, -0.03f, -0.05f);
			Definition.rotationOffset = new Vector3(0f, 0f, -90f);
			Definition.restingRotation = Vector3.zero;
			Definition.verticalOffset = 0.015f;
			Definition.allowDroppingAheadOfPlayer = true;
			Definition.itemIcon = LoadIcon();
			component.Trigger.hoverIcon = (component.Trigger.disabledHoverIcon = Definition.itemIcon);
			PhysicsProp val4 = val.AddComponent<PhysicsProp>();
			((GrabbableObject)val4).itemProperties = Definition;
			((GrabbableObject)val4).grabbable = (((GrabbableObject)val4).grabbableToEnemies = true);
			((GrabbableObject)val4).mainObjectRenderer = mainObjectRenderer;
			((GrabbableObject)val4).propBody = val2;
			((GrabbableObject)val4).propColliders = (Collider[])(object)new Collider[1] { (Collider)val3 };
			((GrabbableObject)val4).originalScale = Vector3.one;
			((GrabbableObject)val4).useCooldown = 0.1f;
			assembly.GetType("LethalLib.Modules.Items").GetMethod("RegisterShopItem", new Type[2]
			{
				typeof(Item),
				typeof(int)
			}).Invoke(null, new object[2] { Definition, 250 });
		}

		private static Sprite LoadIcon()
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			using Stream stream = typeof(Plugin).Assembly.GetManifestResourceStream("PortableTerminal.icon.png");
			byte[] array = new byte[stream.Length];
			int num;
			for (int i = 0; i < array.Length; i += num)
			{
				num = stream.Read(array, i, array.Length - i);
				if (num == 0)
				{
					throw new InvalidOperationException("Incomplete portable terminal icon resource.");
				}
			}
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			if (!ImageConversion.LoadImage(val, array))
			{
				throw new InvalidOperationException("Could not load portable terminal icon.");
			}
			return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 256f);
		}
	}
	internal static class PortableModel
	{
		internal static MeshRenderer Build(Transform root, PortableMarker marker)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Expected O, but got Unknown
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: 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_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0300: Unknown result type (might be due to invalid IL or missing references)
			//IL_030a: Expected O, but got Unknown
			//IL_032b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0335: Unknown result type (might be due to invalid IL or missing references)
			//IL_0350: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_043a: Unknown result type (might be due to invalid IL or missing references)
			//IL_044e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0470: Unknown result type (might be due to invalid IL or missing references)
			//IL_0484: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0505: Unknown result type (might be due to invalid IL or missing references)
			//IL_0519: Unknown result type (might be due to invalid IL or missing references)
			//IL_0549: Unknown result type (might be due to invalid IL or missing references)
			//IL_055d: Unknown result type (might be due to invalid IL or missing references)
			//IL_057f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0593: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_05da: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e1: Expected O, but got Unknown
			//IL_0606: Unknown result type (might be due to invalid IL or missing references)
			//IL_0633: 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_0679: Unknown result type (might be due to invalid IL or missing references)
			//IL_068d: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0704: Unknown result type (might be due to invalid IL or missing references)
			//IL_0721: Unknown result type (might be due to invalid IL or missing references)
			//IL_0728: Expected O, but got Unknown
			//IL_073d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0742: Unknown result type (might be due to invalid IL or missing references)
			//IL_0761: Unknown result type (might be due to invalid IL or missing references)
			//IL_077d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0784: Expected O, but got Unknown
			//IL_07d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_07f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0851: Unknown result type (might be due to invalid IL or missing references)
			//IL_085b: Expected O, but got Unknown
			//IL_085d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0867: Expected O, but got Unknown
			//IL_0869: Unknown result type (might be due to invalid IL or missing references)
			//IL_0873: Expected O, but got Unknown
			//IL_0875: Unknown result type (might be due to invalid IL or missing references)
			//IL_087f: Expected O, but got Unknown
			//IL_0881: Unknown result type (might be due to invalid IL or missing references)
			//IL_088b: Expected O, but got Unknown
			//IL_088d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0897: Expected O, but got Unknown
			Shader shader = Shader.Find("HDRP/Lit") ?? Shader.Find("HDRP/Unlit");
			if (!Object.op_Implicit((Object)(object)shader))
			{
				throw new InvalidOperationException("Portable terminal shader unavailable.");
			}
			Material mat = Mat(new Color(0.18f, 0.21f, 0.17f), 0.4f);
			Material val = Mat(new Color(0.025f, 0.035f, 0.03f));
			Material mat2 = Mat(new Color(0.42f, 0.46f, 0.39f), 0.65f);
			Material mat3 = Mat(new Color(0.48f, 0.08f, 0.035f));
			Mat(new Color(0.65f, 0.37f, 0.055f));
			marker.Folded = new GameObject("Briefcase model");
			marker.Folded.transform.SetParent(root, false);
			Transform transform = marker.Folded.transform;
			transform.localScale = Vector3.one * 2f;
			MeshRenderer result = Box(transform, "Rugged briefcase", new Vector3(0f, 0.065f, 0f), new Vector3(0.49f, 0.13f, 0.33f), mat);
			Box(transform, "Lid seam", new Vector3(0f, 0.072f, 0f), new Vector3(0.497f, 0.009f, 0.337f), val);
			float[] array = new float[2] { -0.17f, 0.17f };
			foreach (float num in array)
			{
				Box(transform, "Latch", new Vector3(num, 0.075f, -0.172f), new Vector3(0.044f, 0.06f, 0.014f), mat2);
				Box(transform, "Handle mount", new Vector3(num * 0.45f, 0.06f, -0.19f), new Vector3(0.024f, 0.025f, 0.055f), val);
			}
			Box(transform, "Carry handle", new Vector3(0f, 0.06f, -0.215f), new Vector3(0.17f, 0.025f, 0.024f), val);
			array = new float[2] { -0.24f, 0.24f };
			foreach (float num2 in array)
			{
				float[] array2 = new float[2] { -0.16f, 0.16f };
				foreach (float num3 in array2)
				{
					Box(transform, "Corner guard", new Vector3(num2, 0.065f, num3), new Vector3(0.025f, 0.14f, 0.025f), mat2);
				}
			}
			marker.DeployedModel = new GameObject("Deployed field terminal");
			marker.DeployedModel.transform.SetParent(root, false);
			Transform transform2 = marker.DeployedModel.transform;
			transform2.localScale = Vector3.one * 2f;
			transform2.localPosition = new Vector3(0f, 0.07f, 0f);
			array = new float[2] { -0.23f, 0.23f };
			foreach (float num4 in array)
			{
				float[] array2 = new float[2] { -0.16f, 0.16f };
				foreach (float num5 in array2)
				{
					Box(transform2, "Folding leg", new Vector3(num4, 0.34f, num5), new Vector3(0.022f, 0.8f, 0.022f), mat2);
					Box(transform2, "Rubber foot", new Vector3(num4, -0.055f, num5), new Vector3(0.055f, 0.025f, 0.055f), val);
				}
			}
			Box(transform2, "Keyboard case", new Vector3(0f, 0.78f, 0f), new Vector3(0.57f, 0.11f, 0.42f), mat);
			Box(transform2, "Keyboard recess", new Vector3(0f, 0.841f, -0.055f), new Vector3(0.49f, 0.012f, 0.23f), val);
			KeyboardModel.Build(transform2, val);
			Box(transform2, "Screen casing", new Vector3(0f, 1.09f, 0.145f), new Vector3(0.57f, 0.49f, 0.1f), mat);
			array = new float[2] { -0.075f, 0.075f };
			foreach (float num6 in array)
			{
				Box(transform2, "Top carry handle mount", new Vector3(num6, 1.365f, 0.145f), new Vector3(0.025f, 0.06f, 0.025f), val);
			}
			Box(transform2, "Top carry handle", new Vector3(0f, 1.395f, 0.145f), new Vector3(0.175f, 0.025f, 0.025f), val);
			Box(transform2, "Screen bezel", new Vector3(-0.035f, 1.09f, 0.087f), new Vector3(0.44f, 0.37f, 0.018f), val);
			Box(transform2, "Monitor glass", new Vector3(-0.035f, 1.09f, 0.075f), new Vector3(0.39f, 0.32f, 0.008f), val);
			GameObject val2 = new GameObject("Live terminal canvas anchor");
			val2.transform.SetParent(transform2, false);
			val2.transform.localPosition = new Vector3(-0.035f, 1.09f, 0.064f);
			marker.Screen = val2.transform;
			Box(transform2, "Red power switch", new Vector3(0.237f, 1.22f, 0.08f), new Vector3(0.035f, 0.06f, 0.022f), mat3);
			for (int k = 0; k < 7; k++)
			{
				Box(transform2, "Vent", new Vector3(0.237f, 1.1f - (float)k * 0.023f, 0.083f), new Vector3(0.028f, 0.008f, 0.014f), val);
			}
			Box(transform2, "Antenna base", new Vector3(0.23f, 1.35f, 0.16f), new Vector3(0.035f, 0.05f, 0.035f), val);
			Box(transform2, "Antenna", new Vector3(0.23f, 1.5f, 0.16f), new Vector3(0.007f, 0.28f, 0.007f), mat2);
			marker.DeployedModel.SetActive(false);
			GameObject val3 = new GameObject("Terminal standing position");
			val3.transform.SetParent(root, false);
			float x = root.InverseTransformPoint(marker.Screen.position).x;
			val3.transform.localPosition = new Vector3(x, -0.075f, -1.35f);
			marker.Standing = val3.transform;
			GameObject val4 = new GameObject("Portable terminal interaction");
			val4.transform.SetParent(root, false);
			val4.layer = LayerMask.NameToLayer("InteractableObject");
			val4.tag = "InteractTrigger";
			marker.InteractionCollider = val4.AddComponent<BoxCollider>();
			marker.InteractionCollider.center = new Vector3(0f, 2.03f, 0f);
			marker.InteractionCollider.size = new Vector3(1.28f, 1.3f, 0.96f);
			((Collider)marker.InteractionCollider).enabled = false;
			InteractTrigger val5 = (marker.Trigger = val4.AddComponent<InteractTrigger>());
			val5.hoverTip = "Tap interact to use the terminal. Hold to pick up";
			val5.disabledHoverTip = "Terminal in use";
			val5.oneHandedItemAllowed = true;
			val5.twoHandedItemAllowed = false;
			val5.interactable = false;
			val5.holdInteraction = false;
			val5.onInteract = new InteractEvent();
			val5.onInteractEarly = new InteractEvent();
			val5.onInteractEarlyOtherClients = new InteractEvent();
			val5.onStopInteract = new InteractEvent();
			val5.onCancelAnimation = new InteractEvent();
			val5.holdingInteractEvent = new InteractEventFloat();
			return result;
			Material Mat(Color c, float metal = 0f)
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000c: Expected O, but got Unknown
				//IL_003e: Unknown result type (might be due to invalid IL or missing references)
				Material val6 = new Material(shader);
				string[] array3 = new string[3] { "_BaseColor", "_UnlitColor", "_Color" };
				foreach (string text in array3)
				{
					if (val6.HasProperty(text))
					{
						val6.SetColor(text, c);
					}
				}
				if (val6.HasProperty("_Metallic"))
				{
					val6.SetFloat("_Metallic", metal);
				}
				if (val6.HasProperty("_Smoothness"))
				{
					val6.SetFloat("_Smoothness", 0.25f);
				}
				return val6;
			}
		}

		private static MeshRenderer Box(Transform parent, string name, Vector3 position, Vector3 scale, Material mat)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = GameObject.CreatePrimitive((PrimitiveType)3);
			((Object)obj).name = name;
			obj.transform.SetParent(parent, false);
			obj.transform.localPosition = position;
			obj.transform.localScale = scale;
			obj.layer = LayerMask.NameToLayer("Props");
			Collider component = obj.GetComponent<Collider>();
			component.enabled = false;
			Object.Destroy((Object)(object)component);
			MeshRenderer component2 = obj.GetComponent<MeshRenderer>();
			((Renderer)component2).sharedMaterial = mat;
			return component2;
		}
	}
	public sealed class PortableMarker : MonoBehaviour
	{
		[SerializeField]
		internal GameObject Folded;

		[SerializeField]
		internal GameObject DeployedModel;

		[SerializeField]
		internal InteractTrigger Trigger;

		[SerializeField]
		internal BoxCollider InteractionCollider;

		[SerializeField]
		internal Transform Standing;

		[SerializeField]
		internal Transform Screen;

		internal uint Revision;

		internal bool Deployed;

		internal bool RestoreDeployed;

		internal float Created;

		internal Vector3 Anchor;

		internal Vector3 Rotation;

		private void Start()
		{
			Created = Time.unscaledTime;
		}

		internal void Apply(DeviceState state)
		{
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			if (state.Revision == Revision)
			{
				return;
			}
			bool deployed = Deployed;
			Revision = state.Revision;
			Deployed = state.Deployed;
			Folded.SetActive(!Deployed);
			DeployedModel.SetActive(Deployed);
			((Collider)InteractionCollider).enabled = Deployed;
			Trigger.interactable = Deployed;
			if (Deployed || deployed)
			{
				GrabbableObject component = ((Component)this).GetComponent<GrabbableObject>();
				StartOfRound instance = StartOfRound.Instance;
				((Component)this).transform.SetParent(state.InShip ? instance.elevatorTransform : instance.propsContainer, true);
				Anchor = new Vector3(state.X, state.Y, state.Z);
				Rotation = new Vector3(state.Pitch, state.Yaw, state.Roll);
				if (!state.InShip)
				{
					Anchor = ((Component)this).transform.parent.InverseTransformPoint(Anchor);
				}
				component.parentObject = null;
				if (Deployed || !component.isHeld)
				{
					((Component)this).transform.localPosition = Anchor;
					((Component)this).transform.localEulerAngles = Rotation;
				}
				component.isInElevator = (component.isInShipRoom = state.InShip);
				component.grabbable = (component.grabbableToEnemies = !Deployed);
				component.EnablePhysics(!Deployed);
				((Collider)((Component)this).GetComponent<BoxCollider>()).enabled = !Deployed;
				((Collider)InteractionCollider).enabled = Deployed;
				Trigger.interactable = Deployed;
				Folded.SetActive(!Deployed);
				DeployedModel.SetActive(Deployed);
				if (!Deployed && !component.isHeld)
				{
					component.FallToGround(false, true, default(Vector3));
				}
			}
		}

		private void LateUpdate()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: 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_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			if (Deployed)
			{
				GrabbableObject component = ((Component)this).GetComponent<GrabbableObject>();
				component.parentObject = null;
				component.fallTime = 1f;
				component.hasHitGround = (component.reachedFloorTarget = true);
				component.targetFloorPosition = (component.startFallingPosition = Anchor);
				((Component)this).transform.localPosition = Anchor;
				((Component)this).transform.localEulerAngles = Rotation;
			}
		}
	}
	internal sealed class RequestGate
	{
		private readonly Dictionary<ulong, (uint sequence, double time)> accepted = new Dictionary<ulong, (uint, double)>();

		internal bool TryAccept(ulong client, uint sequence, double now, double cooldown)
		{
			if (sequence == 0 || double.IsNaN(now) || double.IsInfinity(now))
			{
				return false;
			}
			if (accepted.TryGetValue(client, out (uint, double) value) && (sequence <= value.Item1 || now - value.Item2 < cooldown))
			{
				return false;
			}
			accepted[client] = (sequence, now);
			return true;
		}

		internal void Remove(ulong client)
		{
			accepted.Remove(client);
		}

		internal void Clear()
		{
			accepted.Clear();
		}
	}
	internal static class DisplayLayout
	{
		internal const float DeployedScale = 2f;

		internal static float Fit(float width, float height)
		{
			if (width <= 0f || height <= 0f || float.IsNaN(width) || float.IsNaN(height) || float.IsInfinity(width) || float.IsInfinity(height))
			{
				throw new ArgumentOutOfRangeException();
			}
			return Math.Min(0.39f / width, 0.32f / height);
		}
	}
	internal enum GestureResult
	{
		None,
		Tap,
		Hold
	}
	internal sealed class TapHold
	{
		private ulong? target;

		private double started;

		private bool fired;

		internal GestureResult Tick(ulong? lookingAt, bool pressed, bool held, bool released, double now)
		{
			if (pressed && lookingAt.HasValue)
			{
				target = lookingAt;
				started = now;
				fired = false;
			}
			if (!target.HasValue)
			{
				return GestureResult.None;
			}
			if (lookingAt != target || double.IsNaN(now))
			{
				Cancel();
				return GestureResult.None;
			}
			if (!fired && held && now - started >= 0.8)
			{
				fired = true;
				return GestureResult.Hold;
			}
			if (released)
			{
				int result = ((!fired) ? ((!(now - started >= 0.8)) ? 1 : 2) : 0);
				Cancel();
				return (GestureResult)result;
			}
			return GestureResult.None;
		}

		internal void Cancel()
		{
			target = null;
			fired = false;
		}
	}
	internal sealed class TerminalLease
	{
		internal ulong? Owner;

		internal ulong? Device;

		internal uint Token;

		private double touched;

		internal bool Acquire(ulong owner, ulong device, double now)
		{
			if (Owner.HasValue)
			{
				return false;
			}
			Owner = owner;
			Device = device;
			Token++;
			if (Token == 0)
			{
				Token++;
			}
			touched = now;
			return true;
		}

		internal bool Touch(ulong owner, uint token, double now)
		{
			if (Owner != owner || Token != token)
			{
				return false;
			}
			touched = now;
			return true;
		}

		internal bool Release(ulong owner, uint token)
		{
			if (Owner != owner || Token != token)
			{
				return false;
			}
			Clear();
			return true;
		}

		internal bool Expired(double now)
		{
			if (Owner.HasValue)
			{
				return now - touched > 6.0;
			}
			return false;
		}

		internal void Clear()
		{
			Owner = (Device = null);
		}
	}
	internal sealed class DeviceState
	{
		internal const int Size = 38;

		internal ulong Id;

		internal uint Revision;

		internal bool Deployed;

		internal bool InShip;

		internal float X;

		internal float Y;

		internal float Z;

		internal float Pitch;

		internal float Yaw;

		internal float Roll;

		internal byte[] Encode()
		{
			using MemoryStream memoryStream = new MemoryStream(38);
			using BinaryWriter binaryWriter = new BinaryWriter(memoryStream);
			binaryWriter.Write(Id);
			binaryWriter.Write(Revision);
			binaryWriter.Write(Deployed);
			binaryWriter.Write(InShip);
			binaryWriter.Write(X);
			binaryWriter.Write(Y);
			binaryWriter.Write(Z);
			binaryWriter.Write(Pitch);
			binaryWriter.Write(Yaw);
			binaryWriter.Write(Roll);
			return memoryStream.ToArray();
		}

		internal static bool Decode(byte[] bytes, out DeviceState state)
		{
			state = new DeviceState();
			if (bytes.Length != 38)
			{
				return false;
			}
			using BinaryReader binaryReader = new BinaryReader(new MemoryStream(bytes));
			state.Id = binaryReader.ReadUInt64();
			state.Revision = binaryReader.ReadUInt32();
			byte b = binaryReader.ReadByte();
			byte b2 = binaryReader.ReadByte();
			if (b > 1 || b2 > 1)
			{
				return false;
			}
			state.Deployed = b == 1;
			state.InShip = b2 == 1;
			state.X = binaryReader.ReadSingle();
			state.Y = binaryReader.ReadSingle();
			state.Z = binaryReader.ReadSingle();
			state.Pitch = binaryReader.ReadSingle();
			state.Yaw = binaryReader.ReadSingle();
			state.Roll = binaryReader.ReadSingle();
			float[] array = new float[6] { state.X, state.Y, state.Z, state.Pitch, state.Yaw, state.Roll };
			foreach (float f in array)
			{
				if (float.IsNaN(f) || float.IsInfinity(f))
				{
					return false;
				}
			}
			return state.Revision != 0;
		}
	}
	internal static class PcmSamples
	{
		internal static float[] Decode(byte[] pcm)
		{
			if (pcm == null || pcm.Length == 0 || pcm.Length % 2 != 0)
			{
				throw new ArgumentException("Expected nonempty 16-bit PCM audio.");
			}
			float[] array = new float[pcm.Length / 2];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = (float)(short)(pcm[i * 2] | (pcm[i * 2 + 1] << 8)) / 32768f;
			}
			return array;
		}
	}
	internal static class TransitionSound
	{
		internal static bool ShouldPlay(bool wasDeployed, bool deployed, bool audible)
		{
			if (audible)
			{
				return wasDeployed != deployed;
			}
			return false;
		}
	}
	internal static class TerminalAudio
	{
		private static AudioClip open;

		private static AudioClip close;

		internal static void Load()
		{
			open = LoadClip("open");
			close = LoadClip("close");
		}

		private static AudioClip LoadClip(string name)
		{
			using Stream stream = typeof(Plugin).Assembly.GetManifestResourceStream("PortableTerminal." + name + ".pcm");
			using MemoryStream memoryStream = new MemoryStream();
			stream.CopyTo(memoryStream);
			float[] array = PcmSamples.Decode(memoryStream.ToArray());
			AudioClip obj = AudioClip.Create("Portable terminal " + name, array.Length, 1, 24000, false);
			if (!obj.SetData(array, 0))
			{
				throw new InvalidOperationException("Could not initialize portable terminal " + name + " audio.");
			}
			return obj;
		}

		internal static void Play(Vector3 position, bool deploying)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: 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_0097: Expected O, but got Unknown
			AudioClip val = (deploying ? open : close);
			if (Object.op_Implicit((Object)(object)val))
			{
				GameObject val2 = new GameObject("Portable terminal transition sound");
				val2.transform.position = position;
				AudioSource obj = val2.AddComponent<AudioSource>();
				obj.playOnAwake = false;
				obj.spatialBlend = 1f;
				obj.rolloffMode = (AudioRolloffMode)1;
				obj.minDistance = 1f;
				obj.maxDistance = 10f;
				obj.dopplerLevel = 0f;
				obj.volume = 1f;
				obj.clip = val;
				obj.Play();
				Object.Destroy((Object)val2, val.length + 0.1f);
			}
		}
	}
	internal sealed class TerminalBridge
	{
		private readonly Plugin plugin;

		private static readonly FieldInfo TriggerField = AccessTools.Field(typeof(Terminal), "terminalTrigger");

		private Terminal? terminal;

		private InteractTrigger? original;

		private InteractTrigger? proxy;

		private bool originalInteractable;

		private bool started;

		private bool closing;

		private bool opened;

		private bool opening;

		private DisplayBinding? display;

		private PortableMarker? currentMarker;

		private float openAt;

		private Quaternion cameraRotation;

		private bool savedCamera;

		private float deadline;

		internal TerminalBridge(Plugin owner)
		{
			plugin = owner;
		}

		internal bool ShipTriggerBusy(Terminal ship)
		{
			InteractTrigger val = (InteractTrigger)(Object.op_Implicit((Object)(object)original) ? ((object)original) : ((object)/*isinst with value type is only supported in some contexts*/));
			if (Object.op_Implicit((Object)(object)val))
			{
				return val.isPlayingSpecialAnimation;
			}
			return false;
		}

		internal bool IsLockedShipTrigger(InteractTrigger trigger)
		{
			if (plugin.LeaseOwner.HasValue && Object.op_Implicit((Object)(object)original))
			{
				return (Object)(object)trigger == (Object)(object)original;
			}
			return false;
		}

		internal void Tick()
		{
			//IL_0160: 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_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			if (!plugin.LeaseOwner.HasValue || !plugin.LeaseDevice.HasValue)
			{
				return;
			}
			PortableMarker portableMarker = plugin.Find(plugin.LeaseDevice.Value);
			if (!Object.op_Implicit((Object)(object)portableMarker) || !portableMarker.Deployed)
			{
				return;
			}
			if (!Object.op_Implicit((Object)(object)terminal))
			{
				terminal = plugin.ShipTerminal;
				if (!Object.op_Implicit((Object)(object)terminal))
				{
					return;
				}
				ref InteractTrigger? reference = re