Decompiled source of LastWords v0.5.5

BepInEx/plugins/LastWords/LastWords.dll

Decompiled 13 hours ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Events;
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("青金石")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright © 2026 青金石. All rights reserved.")]
[assembly: AssemblyDescription("Give every employee one last message after death in Lethal Company.")]
[assembly: AssemblyFileVersion("0.5.5.0")]
[assembly: AssemblyInformationalVersion("0.5.5+1db928a26e492fe5084493b0cdc29b0ca4a4579c")]
[assembly: AssemblyProduct("LastWords")]
[assembly: AssemblyTitle("LastWords")]
[assembly: AssemblyVersion("0.5.5.0")]
[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 LastWords
{
	internal enum BroadcastMode
	{
		Auto,
		SignalTranslator,
		Chat
	}
	public sealed class LastWordsRuntime : MonoBehaviour
	{
		private static readonly Color PanelColor = new Color(0.055f, 0.012f, 0.015f, 0.98f);

		private static readonly Color InputColor = new Color(0.095f, 0.025f, 0.03f, 1f);

		private static readonly Color PrimaryButtonColor = new Color(0.48f, 0.055f, 0.07f, 1f);

		private static readonly Color SecondaryButtonColor = new Color(0.2f, 0.16f, 0.16f, 1f);

		private static readonly Color BloodRed = new Color(0.95f, 0.12f, 0.15f, 1f);

		private static readonly Color MessageRed = new Color(1f, 0.34f, 0.36f, 1f);

		private Plugin? _owner;

		private GameObject? _overlay;

		private InputField? _input;

		private Text? _instruction;

		private Text? _counter;

		private Text? _status;

		private GameObject? _sentConfirmation;

		private Text? _sentConfirmationTitle;

		private Text? _sentConfirmationMessage;

		private Button? _sendButton;

		private Button? _skipButton;

		private Font? _font;

		internal void Initialize(Plugin owner)
		{
			_owner = owner;
			owner.LogRuntimeMessage($"Dedicated runtime initialized; enabled: {((Behaviour)this).enabled}; active and enabled: {((Behaviour)this).isActiveAndEnabled}.");
			BuildCanvas();
		}

		internal void ShowWindow(int maximumLength, bool signalOnly)
		{
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_overlay == (Object)null || (Object)(object)_input == (Object)null || (Object)(object)_instruction == (Object)null || (Object)(object)_counter == (Object)null || (Object)(object)_status == (Object)null)
			{
				_owner?.LogRuntimeMessage("Cannot show last-words window because its Canvas was not initialized.");
				return;
			}
			_input.characterLimit = maximumLength;
			_input.text = string.Empty;
			((Selectable)_input).interactable = true;
			HideSentConfirmation();
			if ((Object)(object)_sendButton != (Object)null)
			{
				((Selectable)_sendButton).interactable = true;
			}
			if ((Object)(object)_skipButton != (Object)null)
			{
				((Selectable)_skipButton).interactable = true;
			}
			_instruction.text = (signalOnly ? $"Type up to {maximumLength} characters. The ship broadcasts only the first 10." : "Signal Translator broadcasts the first 10 characters when available; otherwise LastWords sends the full message.");
			_counter.text = $"0 / {maximumLength}";
			_status.text = string.Empty;
			((Graphic)_status).color = new Color(1f, 0.42f, 0.32f, 1f);
			_overlay.SetActive(true);
			((Selectable)_input).Select();
			_input.ActivateInputField();
			_owner?.LogRuntimeMessage("Last-words Canvas activated and input focused.");
		}

		internal void HideWindow()
		{
			if ((Object)(object)_overlay != (Object)null)
			{
				_overlay.SetActive(false);
			}
		}

		internal void SetStatus(string message)
		{
			if ((Object)(object)_status != (Object)null)
			{
				_status.text = message;
			}
		}

		internal void ShowSentConfirmation(string message, string? deliveryNote = null)
		{
			//IL_009a: 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)
			if ((Object)(object)_overlay == (Object)null || (Object)(object)_input == (Object)null || (Object)(object)_instruction == (Object)null || (Object)(object)_counter == (Object)null || (Object)(object)_status == (Object)null)
			{
				return;
			}
			_input.text = message;
			((Selectable)_input).interactable = false;
			_instruction.text = "SENT TO ALL PLAYERS";
			_counter.text = string.Empty;
			_status.text = deliveryNote ?? "Your last words were submitted. This window will close shortly.";
			((Graphic)_status).color = MessageRed;
			if ((Object)(object)_sentConfirmation != (Object)null && (Object)(object)_sentConfirmationMessage != (Object)null)
			{
				if ((Object)(object)_sentConfirmationTitle != (Object)null)
				{
					_sentConfirmationTitle.text = "— FINAL WORDS TRANSMITTED —";
				}
				_sentConfirmationMessage.text = message;
				((Graphic)_sentConfirmationMessage).color = MessageRed;
				_sentConfirmation.SetActive(true);
				_sentConfirmation.transform.SetAsLastSibling();
			}
			if ((Object)(object)_sendButton != (Object)null)
			{
				((Selectable)_sendButton).interactable = false;
			}
			if ((Object)(object)_skipButton != (Object)null)
			{
				((Selectable)_skipButton).interactable = false;
			}
		}

		internal void HideSentConfirmation()
		{
			if ((Object)(object)_sentConfirmation != (Object)null)
			{
				_sentConfirmation.SetActive(false);
			}
		}

		internal void ShowReceivedMessage(string message)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_sentConfirmation == (Object)null) && !((Object)(object)_sentConfirmationMessage == (Object)null))
			{
				if ((Object)(object)_sentConfirmationTitle != (Object)null)
				{
					_sentConfirmationTitle.text = "— MESSAGE FROM THE DEAD —";
				}
				_sentConfirmationMessage.text = message;
				((Graphic)_sentConfirmationMessage).color = MessageRed;
				_sentConfirmation.SetActive(true);
				_sentConfirmation.transform.SetAsLastSibling();
			}
		}

		private void BuildCanvas()
		{
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Expected O, but got Unknown
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_027b: 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_02bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0309: Unknown result type (might be due to invalid IL or missing references)
			//IL_0318: Unknown result type (might be due to invalid IL or missing references)
			//IL_0349: Unknown result type (might be due to invalid IL or missing references)
			//IL_0358: Unknown result type (might be due to invalid IL or missing references)
			//IL_0367: 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_03d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03df: Unknown result type (might be due to invalid IL or missing references)
			//IL_0422: Unknown result type (might be due to invalid IL or missing references)
			//IL_0441: Unknown result type (might be due to invalid IL or missing references)
			//IL_0450: Unknown result type (might be due to invalid IL or missing references)
			//IL_045f: Unknown result type (might be due to invalid IL or missing references)
			//IL_047b: Unknown result type (might be due to invalid IL or missing references)
			//IL_049f: 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_04bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e3: Expected O, but got Unknown
			//IL_04f5: 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_0528: Unknown result type (might be due to invalid IL or missing references)
			//IL_0537: Unknown result type (might be due to invalid IL or missing references)
			//IL_0553: Unknown result type (might be due to invalid IL or missing references)
			//IL_055d: Expected O, but got Unknown
			//IL_059b: Unknown result type (might be due to invalid IL or missing references)
			//IL_05aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0616: Unknown result type (might be due to invalid IL or missing references)
			//IL_0635: Unknown result type (might be due to invalid IL or missing references)
			//IL_0644: Unknown result type (might be due to invalid IL or missing references)
			//IL_0653: Unknown result type (might be due to invalid IL or missing references)
			//IL_0687: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_06b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_06c4: Unknown result type (might be due to invalid IL or missing references)
			_font = Font.CreateDynamicFontFromOSFont(new string[3] { "Microsoft YaHei UI", "Microsoft YaHei", "Arial" }, 24);
			if ((Object)(object)_font == (Object)null)
			{
				_font = Resources.GetBuiltinResource<Font>("Arial.ttf");
			}
			if ((Object)(object)_font == (Object)null)
			{
				_font = Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf");
			}
			GameObject val = new GameObject("LastWords.Canvas", new Type[4]
			{
				typeof(RectTransform),
				typeof(Canvas),
				typeof(CanvasScaler),
				typeof(GraphicRaycaster)
			});
			val.transform.SetParent(((Component)this).transform, false);
			Canvas component = val.GetComponent<Canvas>();
			component.renderMode = (RenderMode)0;
			component.sortingOrder = 32767;
			CanvasScaler component2 = val.GetComponent<CanvasScaler>();
			component2.uiScaleMode = (ScaleMode)1;
			component2.referenceResolution = new Vector2(1920f, 1080f);
			component2.matchWidthOrHeight = 0.5f;
			_overlay = CreateUiObject("Overlay", val.transform, typeof(Image));
			StretchToParent(_overlay.GetComponent<RectTransform>());
			((Graphic)_overlay.GetComponent<Image>()).color = new Color(0f, 0f, 0f, 0.72f);
			GameObject val2 = CreateUiObject("Panel", _overlay.transform, typeof(Image));
			SetRect(val2.GetComponent<RectTransform>(), new Vector2(0.5f, 0.5f), new Vector2(620f, 300f), Vector2.zero);
			((Graphic)val2.GetComponent<Image>()).color = PanelColor;
			Text obj = CreateText("Title", val2.transform, "FINAL TRANSMISSION", 30, (TextAnchor)4);
			((Graphic)obj).color = BloodRed;
			SetRect(((Graphic)obj).rectTransform, new Vector2(0.5f, 0.5f), new Vector2(580f, 42f), new Vector2(0f, 112f));
			GameObject obj2 = CreateUiObject("TitleRule", val2.transform, typeof(Image));
			SetRect(obj2.GetComponent<RectTransform>(), new Vector2(0.5f, 0.5f), new Vector2(570f, 2f), new Vector2(0f, 90f));
			((Graphic)obj2.GetComponent<Image>()).color = new Color(BloodRed.r, BloodRed.g, BloodRed.b, 0.72f);
			_instruction = CreateText("Instruction", val2.transform, string.Empty, 17, (TextAnchor)4);
			SetRect(((Graphic)_instruction).rectTransform, new Vector2(0.5f, 0.5f), new Vector2(570f, 38f), new Vector2(0f, 72f));
			_input = CreateInputField(val2.transform);
			SetRect(((Component)_input).GetComponent<RectTransform>(), new Vector2(0.5f, 0.5f), new Vector2(570f, 46f), new Vector2(0f, 25f));
			((UnityEvent<string>)(object)_input.onValueChanged).AddListener((UnityAction<string>)delegate(string value)
			{
				if ((Object)(object)_counter != (Object)null)
				{
					_counter.text = $"{value.Length} / {_input.characterLimit}";
				}
			});
			_counter = CreateText("Counter", val2.transform, "0 / 50", 15, (TextAnchor)3);
			SetRect(((Graphic)_counter).rectTransform, new Vector2(0.5f, 0.5f), new Vector2(570f, 24f), new Vector2(0f, -14f));
			_status = CreateText("Status", val2.transform, string.Empty, 15, (TextAnchor)3);
			((Graphic)_status).color = new Color(1f, 0.62f, 0.32f, 1f);
			SetRect(((Graphic)_status).rectTransform, new Vector2(0.5f, 0.5f), new Vector2(570f, 34f), new Vector2(0f, -43f));
			_sendButton = CreateButton("Send", val2.transform, "TRANSMIT", PrimaryButtonColor);
			SetRect(((Component)_sendButton).GetComponent<RectTransform>(), new Vector2(0.5f, 0.5f), new Vector2(150f, 45f), new Vector2(-85f, -103f));
			((UnityEvent)_sendButton.onClick).AddListener((UnityAction)delegate
			{
				Plugin? owner = _owner;
				if (owner != null)
				{
					InputField? input = _input;
					owner.SubmitFromCanvas(((input != null) ? input.text : null) ?? string.Empty);
				}
			});
			_skipButton = CreateButton("Skip", val2.transform, "SILENCE", SecondaryButtonColor);
			SetRect(((Component)_skipButton).GetComponent<RectTransform>(), new Vector2(0.5f, 0.5f), new Vector2(150f, 45f), new Vector2(85f, -103f));
			((UnityEvent)_skipButton.onClick).AddListener((UnityAction)delegate
			{
				_owner?.SkipFromCanvas();
			});
			_sentConfirmation = CreateUiObject("SentConfirmation", val.transform, typeof(Image));
			SetRect(_sentConfirmation.GetComponent<RectTransform>(), new Vector2(0.5f, 1f), new Vector2(860f, 124f), new Vector2(0f, -105f));
			((Graphic)_sentConfirmation.GetComponent<Image>()).color = new Color(0.07f, 0.008f, 0.012f, 0.98f);
			_sentConfirmationTitle = CreateText("Title", _sentConfirmation.transform, "— FINAL WORDS TRANSMITTED —", 24, (TextAnchor)4);
			((Graphic)_sentConfirmationTitle).color = BloodRed;
			SetRect(((Graphic)_sentConfirmationTitle).rectTransform, new Vector2(0.5f, 0.5f), new Vector2(820f, 36f), new Vector2(0f, 31f));
			_sentConfirmationMessage = CreateText("Message", _sentConfirmation.transform, string.Empty, 22, (TextAnchor)4);
			((Graphic)_sentConfirmationMessage).color = MessageRed;
			SetRect(((Graphic)_sentConfirmationMessage).rectTransform, new Vector2(0.5f, 0.5f), new Vector2(820f, 58f), new Vector2(0f, -20f));
			_overlay.SetActive(false);
			_sentConfirmation.SetActive(false);
			_owner?.LogRuntimeMessage($"Last-words Canvas initialized; font available: {(Object)(object)_font != (Object)null}.");
		}

		private InputField CreateInputField(Transform parent)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = CreateUiObject("Input", parent, typeof(Image), typeof(InputField));
			((Graphic)val.GetComponent<Image>()).color = InputColor;
			Text val2 = CreateText("Text", val.transform, string.Empty, 21, (TextAnchor)3);
			StretchToParent(((Graphic)val2).rectTransform, 14f, 14f, 6f, 6f);
			Text val3 = CreateText("Placeholder", val.transform, "Write your final words...", 19, (TextAnchor)3);
			((Graphic)val3).color = new Color(0.68f, 0.7f, 0.68f, 0.75f);
			StretchToParent(((Graphic)val3).rectTransform, 14f, 14f, 6f, 6f);
			InputField component = val.GetComponent<InputField>();
			component.textComponent = val2;
			component.placeholder = (Graphic)(object)val3;
			((Selectable)component).targetGraphic = (Graphic)(object)val.GetComponent<Image>();
			component.lineType = (LineType)0;
			component.caretColor = Color.white;
			component.customCaretColor = true;
			return component;
		}

		private Button CreateButton(string name, Transform parent, string label, Color color)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = CreateUiObject(name, parent, typeof(Image), typeof(Button));
			Image component = val.GetComponent<Image>();
			((Graphic)component).color = color;
			Button component2 = val.GetComponent<Button>();
			((Selectable)component2).targetGraphic = (Graphic)(object)component;
			StretchToParent(((Graphic)CreateText("Label", val.transform, label, 20, (TextAnchor)4)).rectTransform);
			return component2;
		}

		private Text CreateText(string name, Transform parent, string value, int size, TextAnchor alignment)
		{
			//IL_003b: 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)
			Text component = CreateUiObject(name, parent, typeof(Text)).GetComponent<Text>();
			component.font = _font;
			component.text = value;
			component.fontSize = size;
			component.alignment = alignment;
			((Graphic)component).color = Color.white;
			component.horizontalOverflow = (HorizontalWrapMode)0;
			component.verticalOverflow = (VerticalWrapMode)0;
			return component;
		}

		private static GameObject CreateUiObject(string name, Transform parent, params Type[] components)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			Type[] array = new Type[components.Length + 1];
			array[0] = typeof(RectTransform);
			components.CopyTo(array, 1);
			GameObject val = new GameObject(name, array);
			val.transform.SetParent(parent, false);
			return val;
		}

		private static void SetRect(RectTransform rect, Vector2 anchor, Vector2 size, Vector2 position)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: 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)
			rect.anchorMin = anchor;
			rect.anchorMax = anchor;
			rect.pivot = new Vector2(0.5f, 0.5f);
			rect.sizeDelta = size;
			rect.anchoredPosition = position;
		}

		private static void StretchToParent(RectTransform rect, float left = 0f, float right = 0f, float top = 0f, float bottom = 0f)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: 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)
			rect.anchorMin = Vector2.zero;
			rect.anchorMax = Vector2.one;
			rect.offsetMin = new Vector2(left, bottom);
			rect.offsetMax = new Vector2(0f - right, 0f - top);
		}
	}
	internal static class LastWordsText
	{
		internal static string Normalize(string? value, int maximumLength)
		{
			if (string.IsNullOrWhiteSpace(value) || maximumLength <= 0)
			{
				return string.Empty;
			}
			string text = value.Trim();
			StringBuilder stringBuilder = new StringBuilder(Math.Min(text.Length, maximumLength));
			bool flag = false;
			for (int i = 0; i < text.Length; i++)
			{
				char c = text[i];
				if (stringBuilder.Length >= maximumLength)
				{
					break;
				}
				if (char.IsControl(c) || char.IsWhiteSpace(c))
				{
					if (!flag && stringBuilder.Length > 0)
					{
						stringBuilder.Append(' ');
						flag = true;
					}
				}
				else if (char.IsHighSurrogate(c) && i + 1 < text.Length && char.IsLowSurrogate(text[i + 1]))
				{
					if (stringBuilder.Length + 2 > maximumLength)
					{
						break;
					}
					stringBuilder.Append(c);
					stringBuilder.Append(text[++i]);
					flag = false;
				}
				else
				{
					StringBuilder stringBuilder2 = stringBuilder;
					stringBuilder2.Append(c switch
					{
						'<' => '<', 
						'>' => '>', 
						_ => c, 
					});
					flag = false;
				}
			}
			return stringBuilder.ToString().TrimEnd();
		}
	}
	[BepInPlugin("cn.lastwords.lethalcompany", "LastWords", "0.5.5")]
	public sealed class Plugin : BaseUnityPlugin
	{
		private const int SignalTranslatorMaximumLength = 10;

		private const float LocalConfirmationSeconds = 8f;

		private const string SubmitMessageName = "cn.lastwords.lethalcompany.submit.v2";

		private const string BroadcastMessageName = "cn.lastwords.lethalcompany.broadcast.v2";

		private static readonly MethodInfo? AddChatMessageMethod = typeof(HUDManager).GetMethod("AddChatMessage", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[4]
		{
			typeof(string),
			typeof(string),
			typeof(int),
			typeof(bool)
		}, null);

		private ConfigEntry<BroadcastMode> _broadcastMode;

		private ConfigEntry<bool> _allowWhenAllPlayersDeadForTesting;

		private ConfigEntry<int> _maximumMessageLength;

		private ConfigEntry<float> _openDelaySeconds;

		private GameObject? _runtimeObject;

		private LastWordsRuntime? _runtime;

		private NetworkManager? _registeredNetworkManager;

		private bool _networkHandlersRegistered;

		private PlayerControllerB? _trackedPlayer;

		private bool _wasDead;

		private bool _hasObservedAlive;

		private bool _chanceConsumed;

		private bool _pendingOpen;

		private bool _pendingClose;

		private bool _confirmationVisible;

		private bool _isOpen;

		private bool _loggedFirstLiveFrame;

		private bool _liveFrameSeen;

		private bool _frameFailureLogged;

		private int _lastTickFrame = -1;

		private float _openAt;

		private float _closeAt;

		private float _confirmationHideAt;

		private Harmony? _harmony;

		private CursorLockMode _previousCursorLockMode;

		private bool _previousCursorVisible;

		internal static Plugin? Instance { get; private set; }

		private void Awake()
		{
			Instance = this;
			_broadcastMode = ((BaseUnityPlugin)this).Config.Bind<BroadcastMode>("General", "BroadcastMode", BroadcastMode.Auto, "Auto uses a real ship Signal Translator whenever it is available and broadcasts the first 10 visible characters. Without the device it falls back to LastWords networking, which requires every player to install the mod.");
			_maximumMessageLength = ((BaseUnityPlugin)this).Config.Bind<int>("General", "MaximumMessageLength", 50, "Maximum input length. A real Signal Translator accepts the message but broadcasts only its first 10 visible characters.");
			_openDelaySeconds = ((BaseUnityPlugin)this).Config.Bind<float>("General", "OpenDelaySeconds", 0.75f, "Delay between death and opening the last-words window.");
			_allowWhenAllPlayersDeadForTesting = ((BaseUnityPlugin)this).Config.Bind<bool>("Testing", "AllowWhenAllPlayersDeadForTesting", false, "Development override that allows the last-words window in solo/all-dead rounds. Keep false for normal play.");
			InstallFrameHooks();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Configuration initialized; deferring Canvas creation until a patched live Unity frame.");
			((BaseUnityPlugin)this).Logger.LogInfo((object)"LastWords 0.5.5 loaded.");
		}

		public void Update()
		{
			RunLiveFrame("BaseUnityPlugin.Update");
		}

		private void InstallFrameHooks()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			try
			{
				_harmony = new Harmony("cn.lastwords.lethalcompany.framehooks");
				MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(Plugin), "PatchedFramePostfix", (Type[])null, (Type[])null);
				if (methodInfo == null)
				{
					throw new MissingMethodException(typeof(Plugin).FullName, "PatchedFramePostfix");
				}
				PatchFrameSource(typeof(PreInitSceneScript), "Start", methodInfo);
				PatchFrameSource(typeof(MenuManager), "Update", methodInfo);
				PatchFrameSource(typeof(HUDManager), "Update", methodInfo);
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Installed live-frame hooks for PreInitSceneScript.Start, MenuManager.Update, and HUDManager.Update.");
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"Could not install LastWords live-frame hooks: {arg}");
			}
		}

		private void PatchFrameSource(Type type, string methodName, MethodInfo postfix)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.DeclaredMethod(type, methodName, (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				throw new MissingMethodException(type.FullName, methodName);
			}
			_harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(postfix), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			bool flag = false;
			Patches patchInfo = Harmony.GetPatchInfo((MethodBase)methodInfo);
			if (patchInfo != null)
			{
				foreach (Patch postfix2 in patchInfo.Postfixes)
				{
					if (string.Equals(postfix2.owner, _harmony.Id, StringComparison.Ordinal))
					{
						flag = true;
						break;
					}
				}
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"LastWords frame hook {type.Name}.{methodName} installed: {flag}.");
			if (!flag)
			{
				throw new InvalidOperationException("Harmony did not report the " + type.Name + "." + methodName + " postfix.");
			}
		}

		private static void PatchedFramePostfix()
		{
			Instance?.RunLiveFrame("Harmony game-loop postfix");
		}

		private void RunLiveFrame(string source)
		{
			try
			{
				int frameCount = Time.frameCount;
				if (_lastTickFrame != frameCount)
				{
					_lastTickFrame = frameCount;
					_liveFrameSeen = true;
					if (!_loggedFirstLiveFrame)
					{
						_loggedFirstLiveFrame = true;
						((BaseUnityPlugin)this).Logger.LogInfo((object)("Live Unity frame source active: " + source + "."));
						EnsureRuntime();
					}
					Tick();
				}
			}
			catch (Exception arg)
			{
				if (!_frameFailureLogged)
				{
					_frameFailureLogged = true;
					((BaseUnityPlugin)this).Logger.LogError((object)$"LastWords live-frame callback failed: {arg}");
				}
			}
		}

		private void EnsureRuntime()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			if (!((Object)(object)_runtimeObject != (Object)null) || !((Object)(object)_runtime != (Object)null))
			{
				_runtimeObject = new GameObject("LastWords.Runtime");
				Object.DontDestroyOnLoad((Object)(object)_runtimeObject);
				_runtime = _runtimeObject.AddComponent<LastWordsRuntime>();
				_runtime.Initialize(this);
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"Dedicated runtime driver created on the first live Unity frame; active: {_runtimeObject.activeInHierarchy}.");
			}
		}

		internal void Tick()
		{
			MaintainNetworkMessaging();
			if (_confirmationVisible && Time.unscaledTime >= _confirmationHideAt)
			{
				_confirmationVisible = false;
				_runtime?.HideSentConfirmation();
			}
			PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
			if ((Object)(object)val == (Object)null)
			{
				ResetTracking();
				return;
			}
			if (val != _trackedPlayer)
			{
				TrackPlayer(val);
				return;
			}
			bool isPlayerDead = val.isPlayerDead;
			if (!isPlayerDead)
			{
				_hasObservedAlive = true;
				_chanceConsumed = false;
				if (_isOpen || _pendingOpen)
				{
					CloseWindow("player revived");
				}
			}
			else if (!_wasDead && _hasObservedAlive && !_chanceConsumed)
			{
				BeginLastWordsOpportunity(val, "state-poll fallback");
			}
			if (_pendingOpen && isPlayerDead && Time.unscaledTime >= _openAt)
			{
				OpenWindow();
			}
			if (_pendingClose && Time.unscaledTime >= _closeAt)
			{
				CloseWindow("send confirmation elapsed");
			}
			if (_isOpen)
			{
				Cursor.lockState = (CursorLockMode)0;
				Cursor.visible = true;
			}
			_wasDead = isPlayerDead;
		}

		private void OnDisable()
		{
			if (_liveFrameSeen)
			{
				_confirmationVisible = false;
				_runtime?.HideSentConfirmation();
				CloseWindow("plugin disabled");
			}
		}

		private void OnDestroy()
		{
			if (!_liveFrameSeen && Application.isPlaying)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Early Chainloader carrier destruction detected; preserving LastWords state for the patched live-frame bridge.");
				return;
			}
			UnregisterNetworkMessaging();
			if ((Object)(object)_runtimeObject != (Object)null)
			{
				Object.Destroy((Object)(object)_runtimeObject);
				_runtimeObject = null;
				_runtime = null;
			}
			if (Instance == this)
			{
				Instance = null;
			}
		}

		internal void SubmitFromCanvas(string rawMessage)
		{
			string text = LastWordsText.Normalize(rawMessage, EffectiveMaximumLength());
			if (text.Length == 0)
			{
				_runtime?.SetStatus("Please enter a message before sending.");
			}
			else
			{
				Submit(text);
			}
		}

		internal void SkipFromCanvas()
		{
			CloseWindow("player skipped");
		}

		private void Submit(string message)
		{
			HUDManager instance = HUDManager.Instance;
			PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
			if ((Object)(object)instance == (Object)null || (Object)(object)val == (Object)null || !val.isPlayerDead)
			{
				_runtime?.SetStatus("Cannot send right now; please try again.");
				return;
			}
			if (!CanPublishLastWords(val))
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Submission cancelled because no other living crew member remains.");
				CloseWindow("all crew members dead");
				return;
			}
			try
			{
				string text = message;
				bool flag = false;
				switch (_broadcastMode.Value)
				{
				case BroadcastMode.SignalTranslator:
				{
					if (!CanUseSignalTranslator(out string status2))
					{
						_runtime?.SetStatus(status2);
						return;
					}
					text = PrepareSignalTranslatorPayload(message);
					flag = !string.Equals(text, message, StringComparison.Ordinal);
					instance.UseSignalTranslatorServerRpc(text);
					LogSignalTranslatorSubmission(message, text, "SignalTranslator mode");
					break;
				}
				case BroadcastMode.Chat:
					SendCrewWideMessage(instance, message);
					break;
				default:
				{
					if (CanUseSignalTranslator(out string status))
					{
						text = PrepareSignalTranslatorPayload(message);
						flag = !string.Equals(text, message, StringComparison.Ordinal);
						instance.UseSignalTranslatorServerRpc(text);
						LogSignalTranslatorSubmission(message, text, "Auto mode");
					}
					else
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)("Auto mode using the LastWords network fallback: " + status + "."));
						SendCrewWideMessage(instance, message);
					}
					break;
				}
				}
				_runtime?.ShowSentConfirmation(FormatLastWords(val.playerUsername, text), flag ? "Signal Translator broadcast only the first 10 characters." : null);
				_pendingClose = true;
				_closeAt = Time.unscaledTime + 2.25f;
				_confirmationVisible = true;
				_confirmationHideAt = Time.unscaledTime + 8f;
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"Showing the sender an always-on-top local delivery banner for {8f:0.##} seconds.");
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"Could not submit last words: {arg}");
				_runtime?.SetStatus("Send failed; check the BepInEx log, then retry.");
			}
		}

		private unsafe void SendCrewWideMessage(HUDManager hud, string message)
		{
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			PlayerControllerB obj = GameNetworkManager.Instance?.localPlayerController;
			if ((Object)(object)obj == (Object)null)
			{
				throw new InvalidOperationException("The local player is unavailable.");
			}
			string text = FormatLastWords(obj.playerUsername, message);
			try
			{
				if (AddChatMessageMethod == null)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)"Could not find HUDManager.AddChatMessage; relying on the local Canvas confirmation.");
				}
				else
				{
					AddChatMessageMethod.Invoke(hud, new object[4]
					{
						text,
						string.Empty,
						-1,
						true
					});
					((BaseUnityPlugin)this).Logger.LogInfo((object)"Inserted last words into the sender's local chat history.");
				}
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)$"Could not insert the local chat copy; the LastWords network message will still be sent: {arg}");
			}
			MaintainNetworkMessaging();
			NetworkManager registeredNetworkManager = _registeredNetworkManager;
			if (!_networkHandlersRegistered || (Object)(object)registeredNetworkManager == (Object)null || !registeredNetworkManager.IsListening)
			{
				throw new InvalidOperationException("LastWords networking is not ready. Every player must install the mod and join the same lobby.");
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"LastWords network role: IsServer={registeredNetworkManager.IsServer}; IsHost={registeredNetworkManager.IsHost}; IsClient={registeredNetworkManager.IsClient}; LocalClientId={registeredNetworkManager.LocalClientId}.");
			if (registeredNetworkManager.IsServer)
			{
				BroadcastModMessage(text);
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Submitted last words through the host's LastWords broadcast channel.");
				return;
			}
			FastBufferWriter val = CreateMessageWriter(message);
			try
			{
				registeredNetworkManager.CustomMessagingManager.SendNamedMessage("cn.lastwords.lethalcompany.submit.v2", 0uL, val, (NetworkDelivery)3);
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Submitted last words to the host through the LastWords request channel.");
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
			}
		}

		private void MaintainNetworkMessaging()
		{
			NetworkManager singleton = NetworkManager.Singleton;
			if (singleton == _registeredNetworkManager)
			{
				if (_networkHandlersRegistered && ((Object)(object)singleton == (Object)null || !singleton.IsListening))
				{
					UnregisterNetworkMessaging();
				}
				else if (!_networkHandlersRegistered && (Object)(object)singleton != (Object)null && singleton.IsListening)
				{
					RegisterNetworkMessaging(singleton);
				}
			}
			else
			{
				UnregisterNetworkMessaging();
				if ((Object)(object)singleton != (Object)null && singleton.IsListening)
				{
					RegisterNetworkMessaging(singleton);
				}
			}
		}

		private void RegisterNetworkMessaging(NetworkManager networkManager)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			networkManager.CustomMessagingManager.RegisterNamedMessageHandler("cn.lastwords.lethalcompany.submit.v2", new HandleNamedMessageDelegate(HandleSubmitMessage));
			networkManager.CustomMessagingManager.RegisterNamedMessageHandler("cn.lastwords.lethalcompany.broadcast.v2", new HandleNamedMessageDelegate(HandleBroadcastMessage));
			_registeredNetworkManager = networkManager;
			_networkHandlersRegistered = true;
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"LastWords network handlers registered; LocalClientId={networkManager.LocalClientId}; IsServer={networkManager.IsServer}.");
		}

		private void UnregisterNetworkMessaging()
		{
			if (_networkHandlersRegistered && (Object)(object)_registeredNetworkManager != (Object)null)
			{
				try
				{
					_registeredNetworkManager.CustomMessagingManager.UnregisterNamedMessageHandler("cn.lastwords.lethalcompany.submit.v2");
					_registeredNetworkManager.CustomMessagingManager.UnregisterNamedMessageHandler("cn.lastwords.lethalcompany.broadcast.v2");
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not unregister LastWords network handlers cleanly: " + ex.Message));
				}
			}
			_networkHandlersRegistered = false;
			_registeredNetworkManager = null;
		}

		private void HandleSubmitMessage(ulong senderClientId, FastBufferReader reader)
		{
			NetworkManager registeredNetworkManager = _registeredNetworkManager;
			if ((Object)(object)registeredNetworkManager == (Object)null || !registeredNetworkManager.IsServer)
			{
				return;
			}
			string value = default(string);
			((FastBufferReader)(ref reader)).ReadValueSafe(ref value, false);
			string text = LastWordsText.Normalize(value, EffectiveMaximumLength());
			if (text.Length == 0)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)$"Rejected empty LastWords request from client {senderClientId}.");
				return;
			}
			PlayerControllerB val = FindPlayer(senderClientId);
			if ((Object)(object)val == (Object)null || !val.isPlayerDead || !CanPublishLastWords(val))
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)$"Rejected ineligible LastWords request from client {senderClientId}.");
				return;
			}
			BroadcastModMessage(FormatLastWords(val.playerUsername, text));
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"Validated and relayed last words from client {senderClientId}.");
		}

		private void HandleBroadcastMessage(ulong senderClientId, FastBufferReader reader)
		{
			if (senderClientId != 0L)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)$"Ignored LastWords broadcast from non-server client {senderClientId}.");
				return;
			}
			string text = default(string);
			((FastBufferReader)(ref reader)).ReadValueSafe(ref text, false);
			int num = Mathf.Clamp(_maximumMessageLength.Value, 1, 200) + 64;
			if (string.IsNullOrWhiteSpace(text) || text.Length > num)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Ignored malformed LastWords broadcast payload.");
				return;
			}
			HUDManager instance = HUDManager.Instance;
			if ((Object)(object)instance != (Object)null && AddChatMessageMethod != null)
			{
				try
				{
					AddChatMessageMethod.Invoke(instance, new object[4]
					{
						text,
						string.Empty,
						-1,
						true
					});
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not add received last words to local chat history: " + ex.Message));
				}
			}
			_runtime?.ShowReceivedMessage(text);
			_confirmationVisible = true;
			_confirmationHideAt = Time.unscaledTime + 8f;
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"Received crew last words from the host; showing the overlay for {8f:0.##} seconds.");
		}

		private unsafe void BroadcastModMessage(string message)
		{
			//IL_0024: 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_0035: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager registeredNetworkManager = _registeredNetworkManager;
			if ((Object)(object)registeredNetworkManager == (Object)null || !registeredNetworkManager.IsServer)
			{
				throw new InvalidOperationException("Only the server can broadcast LastWords messages.");
			}
			FastBufferWriter val = CreateMessageWriter(message);
			try
			{
				registeredNetworkManager.CustomMessagingManager.SendNamedMessageToAll("cn.lastwords.lethalcompany.broadcast.v2", val, (NetworkDelivery)3);
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
			}
		}

		private static FastBufferWriter CreateMessageWriter(string message)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			int num = Math.Max(64, message.Length * 4 + 16);
			FastBufferWriter result = default(FastBufferWriter);
			((FastBufferWriter)(ref result))..ctor(num, (Allocator)2, num);
			((FastBufferWriter)(ref result)).WriteValueSafe(message, false);
			return result;
		}

		private static string FormatLastWords(string playerName, string message)
		{
			string text = LastWordsText.Normalize(playerName, 24);
			if (text.Length == 0)
			{
				text = "UNKNOWN CREW MEMBER";
			}
			return "[DECEASED] " + text + ": " + message;
		}

		private static PlayerControllerB? FindPlayer(ulong clientId)
		{
			PlayerControllerB[] array = StartOfRound.Instance?.allPlayerScripts;
			if (array == null)
			{
				return null;
			}
			PlayerControllerB[] array2 = array;
			foreach (PlayerControllerB val in array2)
			{
				if ((Object)(object)val != (Object)null && val.isPlayerControlled && val.playerClientId == clientId)
				{
					return val;
				}
			}
			return null;
		}

		private static bool CanUseSignalTranslator(out string status)
		{
			SignalTranslator val = Object.FindObjectOfType<SignalTranslator>();
			if ((Object)(object)val == (Object)null)
			{
				status = "The ship has no Signal Translator. Use Auto or Chat mode instead.";
				return false;
			}
			float num = 8f - (Time.realtimeSinceStartup - val.timeLastUsingSignalTranslator);
			if (num > 0f)
			{
				status = $"Signal Translator cooling down: about {Mathf.CeilToInt(num)} seconds remaining.";
				return false;
			}
			status = string.Empty;
			return true;
		}

		private static string PrepareSignalTranslatorPayload(string message)
		{
			return LastWordsText.Normalize(message, 10);
		}

		private void LogSignalTranslatorSubmission(string originalMessage, string deliveredMessage, string mode)
		{
			if (string.Equals(originalMessage, deliveredMessage, StringComparison.Ordinal))
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Submitted last words through the Signal Translator (" + mode + ")."));
			}
			else
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Submitted last words through the Signal Translator (" + mode + "); " + $"broadcast payload was truncated from {originalMessage.Length} to {deliveredMessage.Length} characters."));
			}
		}

		private int EffectiveMaximumLength()
		{
			return Mathf.Clamp(_maximumMessageLength.Value, 1, 200);
		}

		private void TrackPlayer(PlayerControllerB localPlayer)
		{
			CloseWindow("local player object changed");
			_trackedPlayer = localPlayer;
			_wasDead = localPlayer.isPlayerDead;
			_hasObservedAlive = !localPlayer.isPlayerDead;
			_chanceConsumed = false;
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"Tracking local player object; initially dead: {_wasDead}.");
		}

		private void ResetTracking()
		{
			CloseWindow("local player unavailable");
			_trackedPlayer = null;
			_wasDead = false;
			_hasObservedAlive = false;
			_chanceConsumed = false;
		}

		private void OpenWindow()
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			_pendingOpen = false;
			_pendingClose = false;
			_confirmationVisible = false;
			_runtime?.HideSentConfirmation();
			if ((Object)(object)_trackedPlayer == (Object)null || !CanPublishLastWords(_trackedPlayer))
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Last-words window suppressed because no other living crew member remains.");
				return;
			}
			_isOpen = true;
			_previousCursorLockMode = Cursor.lockState;
			_previousCursorVisible = Cursor.visible;
			Cursor.lockState = (CursorLockMode)0;
			Cursor.visible = true;
			_runtime?.ShowWindow(EffectiveMaximumLength(), _broadcastMode.Value == BroadcastMode.SignalTranslator);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Last-words Canvas window opened.");
		}

		private void CloseWindow(string reason)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			_pendingOpen = false;
			_pendingClose = false;
			if (_isOpen)
			{
				_isOpen = false;
				_runtime?.HideWindow();
				Cursor.lockState = _previousCursorLockMode;
				Cursor.visible = _previousCursorVisible;
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Last-words window closed: " + reason + "."));
			}
		}

		internal void LogRuntimeMessage(string message)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)message);
		}

		private void BeginLastWordsOpportunity(PlayerControllerB localPlayer, string source)
		{
			if (_chanceConsumed)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Ignored duplicate local death notification from " + source + "."));
				return;
			}
			_trackedPlayer = localPlayer;
			_hasObservedAlive = true;
			_wasDead = true;
			_chanceConsumed = true;
			if (!CanPublishLastWords(localPlayer))
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Detected local player death via " + source + ", but suppressed last words because the whole crew is dead."));
				return;
			}
			_pendingOpen = true;
			_openAt = Time.unscaledTime + Mathf.Max(0f, _openDelaySeconds.Value);
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"Detected local player death via {source}; window scheduled for {_openDelaySeconds.Value:0.###} seconds later.");
			if (_openDelaySeconds.Value <= 0f)
			{
				OpenWindow();
			}
		}

		private bool CanPublishLastWords(PlayerControllerB localPlayer)
		{
			if (_allowWhenAllPlayersDeadForTesting.Value)
			{
				return true;
			}
			PlayerControllerB[] array = StartOfRound.Instance?.allPlayerScripts;
			if (array == null)
			{
				return false;
			}
			PlayerControllerB[] array2 = array;
			foreach (PlayerControllerB val in array2)
			{
				if ((Object)(object)val != (Object)null && val != localPlayer && val.isPlayerControlled && !val.isPlayerDead)
				{
					return true;
				}
			}
			return false;
		}
	}
	internal static class PluginInfo
	{
		internal const string Guid = "cn.lastwords.lethalcompany";

		internal const string Name = "LastWords";

		internal const string Version = "0.5.5";
	}
}