using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mirror;
using Steamworks;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.LowLevel;
using UnityEngine.InputSystem.UI;
using UnityEngine.InputSystem.Utilities;
using UnityEngine.SceneManagement;
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("CRACK.TextChat")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("CRACK.TextChat")]
[assembly: AssemblyTitle("CRACK.TextChat")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[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 CrackTextChat
{
public struct HelloV1 : NetworkMessage
{
public int Protocol;
}
public struct WelcomeV1 : NetworkMessage
{
public int Protocol;
}
public struct SayV1 : NetworkMessage
{
public string Text;
}
public struct LineV1 : NetworkMessage
{
public string Name;
public string Text;
}
public sealed class ChatNetwork
{
public const int Protocol = 1;
private const string CapabilityKey = "crack.textchat.protocol";
private readonly Plugin plugin;
private readonly Dictionary<NetworkConnectionToClient, MessageGate> peers = new Dictionary<NetworkConnectionToClient, MessageGate>();
private NetworkConnectionToServer clientConnection;
private float retryAt;
private float advertiseAt;
private bool welcomed;
private static readonly IDictionary ServerHandlers = (IDictionary)AccessTools.Field(typeof(NetworkServer), "handlers").GetValue(null);
private static readonly IDictionary ClientHandlers = (IDictionary)AccessTools.Field(typeof(NetworkClient), "handlers").GetValue(null);
public bool Ready
{
get
{
if (NetworkClient.isConnected)
{
return welcomed;
}
return false;
}
}
public string Status
{
get
{
if (NetworkClient.isConnected)
{
if (!Ready)
{
return "Waiting for TextChat host";
}
return "Crew chat";
}
return "Join a game to chat";
}
}
public ChatNetwork(Plugin plugin)
{
this.plugin = plugin;
RegisterCodecs();
}
public static void RegisterCodecs()
{
Writer<HelloV1>.write = delegate(NetworkWriter w, HelloV1 m)
{
NetworkWriterExtensions.WriteInt(w, m.Protocol);
};
Reader<HelloV1>.read = (NetworkReader r) => new HelloV1
{
Protocol = NetworkReaderExtensions.ReadInt(r)
};
Writer<WelcomeV1>.write = delegate(NetworkWriter w, WelcomeV1 m)
{
NetworkWriterExtensions.WriteInt(w, m.Protocol);
};
Reader<WelcomeV1>.read = (NetworkReader r) => new WelcomeV1
{
Protocol = NetworkReaderExtensions.ReadInt(r)
};
Writer<SayV1>.write = delegate(NetworkWriter w, SayV1 m)
{
NetworkWriterExtensions.WriteString(w, m.Text);
};
Reader<SayV1>.read = (NetworkReader r) => new SayV1
{
Text = ReadBounded(r, 1200)
};
Writer<LineV1>.write = delegate(NetworkWriter w, LineV1 m)
{
NetworkWriterExtensions.WriteString(w, m.Name);
NetworkWriterExtensions.WriteString(w, m.Text);
};
Reader<LineV1>.read = (NetworkReader r) => new LineV1
{
Name = ReadBounded(r, 256),
Text = ReadBounded(r, 1200)
};
}
private static string ReadBounded(NetworkReader reader, int maxBytes)
{
ushort num = NetworkReaderExtensions.ReadUShort(reader);
if (num == 0)
{
return "";
}
int num2 = num - 1;
if (num2 > maxBytes)
{
throw new InvalidDataException("TextChat message exceeds protocol limit.");
}
ArraySegment<byte> arraySegment = reader.ReadBytesSegment(num2);
return new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true).GetString(arraySegment.Array, arraySegment.Offset, arraySegment.Count);
}
public void Tick()
{
//IL_011d: Unknown result type (might be due to invalid IL or missing references)
//IL_0122: Unknown result type (might be due to invalid IL or missing references)
//IL_013a: Unknown result type (might be due to invalid IL or missing references)
if (NetworkServer.active)
{
if (!ServerHandlers.Contains(NetworkMessageId<HelloV1>.Id))
{
NetworkServer.RegisterHandler<HelloV1>((Action<NetworkConnectionToClient, HelloV1>)OnHello, true);
}
if (!ServerHandlers.Contains(NetworkMessageId<SayV1>.Id))
{
NetworkServer.RegisterHandler<SayV1>((Action<NetworkConnectionToClient, SayV1>)OnSay, true);
}
List<NetworkConnectionToClient> list = new List<NetworkConnectionToClient>();
foreach (NetworkConnectionToClient key in peers.Keys)
{
if (!NetworkServer.connections.TryGetValue(key.connectionId, out var value) || value != key)
{
list.Add(key);
}
}
foreach (NetworkConnectionToClient item in list)
{
peers.Remove(item);
}
if (Time.unscaledTime >= advertiseAt)
{
advertiseAt = Time.unscaledTime + 1f;
if ((Object)(object)SteamLobby.instance != (Object)null && SteamLobby.instance.currentLobbyID != CSteamID.Nil && SteamManager.Initialized)
{
SteamMatchmaking.SetLobbyData(SteamLobby.instance.currentLobbyID, "crack.textchat.protocol", 1.ToString());
}
}
}
else
{
peers.Clear();
}
if (NetworkClient.active)
{
if (!ClientHandlers.Contains(NetworkMessageId<WelcomeV1>.Id))
{
NetworkClient.RegisterHandler<WelcomeV1>((Action<WelcomeV1>)OnWelcome, true);
}
if (!ClientHandlers.Contains(NetworkMessageId<LineV1>.Id))
{
NetworkClient.RegisterHandler<LineV1>((Action<LineV1>)OnLine, true);
}
}
if (clientConnection != NetworkClient.connection)
{
clientConnection = NetworkClient.connection;
welcomed = false;
retryAt = 0f;
plugin.View?.ResetSession();
}
if (!NetworkClient.isConnected)
{
welcomed = false;
}
else if (!welcomed && clientConnection != null && ((NetworkConnection)clientConnection).isAuthenticated && NetworkClient.ready && (Object)(object)NetworkClient.localPlayer != (Object)null && Time.unscaledTime >= retryAt && HostSupportsChat())
{
retryAt = Time.unscaledTime + 3f;
NetworkClient.Send<HelloV1>(new HelloV1
{
Protocol = 1
}, 0);
}
}
private bool HostSupportsChat()
{
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
if (NetworkServer.active)
{
return true;
}
if ((Object)(object)SteamLobby.instance != (Object)null && SteamLobby.instance.currentLobbyID != CSteamID.Nil && SteamManager.Initialized)
{
return SteamMatchmaking.GetLobbyData(SteamLobby.instance.currentLobbyID, "crack.textchat.protocol") == 1.ToString();
}
return plugin.AssumeLanHost.Value;
}
private void OnHello(NetworkConnectionToClient connection, HelloV1 message)
{
if (message.Protocol == 1 && !((Object)(object)((NetworkConnection)connection).identity == (Object)null))
{
if (!peers.ContainsKey(connection))
{
peers.Add(connection, new MessageGate());
}
((NetworkConnection)connection).Send<WelcomeV1>(new WelcomeV1
{
Protocol = 1
}, 0);
}
}
private void OnWelcome(WelcomeV1 message)
{
if (message.Protocol == 1 && !welcomed)
{
welcomed = true;
plugin.View?.Add("TextChat", "Connected. Enter to chat · Esc to close", system: true);
}
}
private void OnSay(NetworkConnectionToClient connection, SayV1 message)
{
if (!peers.TryGetValue(connection, out var value) || (Object)(object)((NetworkConnection)connection).identity == (Object)null)
{
return;
}
PlayerController component = ((Component)((NetworkConnection)connection).identity).GetComponent<PlayerController>();
if ((Object)(object)component == (Object)null)
{
return;
}
string text = ChatRules.Clean(message.Text);
if (text.Length == 0 || !value.TryAccept(Time.unscaledTimeAsDouble, plugin.MessageInterval.Value))
{
return;
}
string text2 = ChatRules.Clean(component.steamName, 48);
if (text2.Length == 0)
{
text2 = "Player " + (component.index + 1);
}
LineV1 lineV = new LineV1
{
Name = text2,
Text = text
};
foreach (NetworkConnectionToClient key in peers.Keys)
{
if (((NetworkConnection)key).isAuthenticated && ((NetworkConnection)key).isReady)
{
((NetworkConnection)key).Send<LineV1>(lineV, 0);
}
}
}
private void OnLine(LineV1 line)
{
plugin.View?.Add(ChatRules.Clean(line.Name, 48), ChatRules.Clean(line.Text), system: false);
}
public bool Send(string text)
{
if (!Ready)
{
plugin.View?.Add("TextChat", "The host needs TextChat. For LAN, enable AssumeLanHostHasMod only when the host has it.", system: true);
return false;
}
text = ChatRules.Clean(text);
if (text.Length == 0)
{
return false;
}
NetworkClient.Send<SayV1>(new SayV1
{
Text = text
}, 0);
return true;
}
public void Dispose()
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
if (NetworkServer.active && (Object)(object)SteamLobby.instance != (Object)null && SteamLobby.instance.currentLobbyID != CSteamID.Nil && SteamManager.Initialized)
{
SteamMatchmaking.DeleteLobbyData(SteamLobby.instance.currentLobbyID, "crack.textchat.protocol");
}
NetworkServer.UnregisterHandler<HelloV1>();
NetworkServer.UnregisterHandler<SayV1>();
NetworkClient.UnregisterHandler<WelcomeV1>();
NetworkClient.UnregisterHandler<LineV1>();
peers.Clear();
}
}
public static class ChatRules
{
public const int MaxLength = 300;
public static string Clean(string value, int limit = 300)
{
if (string.IsNullOrEmpty(value))
{
return "";
}
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < value.Length; i++)
{
if (stringBuilder.Length >= limit)
{
break;
}
char c = value[i];
if (char.IsControl(c))
{
if (c == '\n' || c == '\r' || c == '\t')
{
stringBuilder.Append(' ');
}
}
else
{
if (char.GetUnicodeCategory(c) == UnicodeCategory.Format)
{
continue;
}
if (char.IsHighSurrogate(c))
{
if (i + 1 < value.Length && char.IsLowSurrogate(value[i + 1]) && stringBuilder.Length + 2 <= limit)
{
stringBuilder.Append(c).Append(value[++i]);
}
}
else if (!char.IsLowSurrogate(c))
{
stringBuilder.Append(c);
}
}
}
return stringBuilder.ToString().Trim();
}
}
public sealed class MessageGate
{
private double next;
public bool TryAccept(double now, double interval)
{
if (now < next)
{
return false;
}
next = now + interval;
return true;
}
}
public sealed class ChatView : MonoBehaviour
{
private Plugin plugin;
private GameObject canvasObject;
private RectTransform panel;
private CanvasGroup group;
private RectTransform content;
private ScrollRect scroll;
private ChatInputField input;
private TMP_Text count;
private TMP_FontAsset font;
private TMP_FontAsset fallbackFont;
private float fontRefreshAt;
private RectTransform viewport;
private RectTransform inputRect;
private TMP_Text hint;
private readonly Queue<GameObject> rows = new Queue<GameObject>();
private readonly List<InputAction> restoreActions = new List<InputAction>();
private Player capturedPlayer;
private CursorLockMode savedLock;
private bool savedVisible;
private bool restorePending;
private BaseInputModule module;
private BaseInput savedOverride;
private ChatBaseInput bridge;
private GameObject savedSelection;
private float lastMessage = -1000f;
private float lastSent = -1000f;
private int openFrame;
internal int CompositionFrame = -10;
internal string Composition = "";
private Keyboard keyboard;
private IMECompositionMode savedImeMode;
private WindowsImeContext nativeIme;
private GameObject ownEventSystem;
private bool submitPending;
private int submitFrame;
private int committedFrame = -10;
public bool IsOpen { get; private set; }
internal bool IsComposing
{
get
{
if (Composition.Length <= 0 && string.IsNullOrEmpty(Input.compositionString))
{
return CompositionFrame >= Time.frameCount - 1;
}
return true;
}
}
public void Initialize(Plugin owner)
{
//IL_007e: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Expected O, but got Unknown
//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
//IL_0107: Unknown result type (might be due to invalid IL or missing references)
//IL_0122: Unknown result type (might be due to invalid IL or missing references)
//IL_0127: Unknown result type (might be due to invalid IL or missing references)
//IL_0128: Unknown result type (might be due to invalid IL or missing references)
//IL_012e: Unknown result type (might be due to invalid IL or missing references)
//IL_013a: Unknown result type (might be due to invalid IL or missing references)
//IL_015f: Unknown result type (might be due to invalid IL or missing references)
//IL_0188: Unknown result type (might be due to invalid IL or missing references)
//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
//IL_01f0: 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_0214: Unknown result type (might be due to invalid IL or missing references)
//IL_028b: Unknown result type (might be due to invalid IL or missing references)
//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
//IL_02e4: Unknown result type (might be due to invalid IL or missing references)
//IL_0361: Unknown result type (might be due to invalid IL or missing references)
//IL_037c: Unknown result type (might be due to invalid IL or missing references)
//IL_0381: Unknown result type (might be due to invalid IL or missing references)
//IL_0382: Unknown result type (might be due to invalid IL or missing references)
//IL_0388: Unknown result type (might be due to invalid IL or missing references)
//IL_0394: Unknown result type (might be due to invalid IL or missing references)
//IL_03ae: Unknown result type (might be due to invalid IL or missing references)
//IL_03d2: Unknown result type (might be due to invalid IL or missing references)
//IL_0408: Unknown result type (might be due to invalid IL or missing references)
//IL_0423: Unknown result type (might be due to invalid IL or missing references)
//IL_0432: Unknown result type (might be due to invalid IL or missing references)
//IL_0472: Unknown result type (might be due to invalid IL or missing references)
//IL_048d: Unknown result type (might be due to invalid IL or missing references)
//IL_049c: 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_05a1: Unknown result type (might be due to invalid IL or missing references)
//IL_05f2: Unknown result type (might be due to invalid IL or missing references)
plugin = owner;
fallbackFont = TMP_FontAsset.CreateFontAsset(plugin.FontName.Value, "Regular", 90);
font = TMP_Settings.defaultFontAsset ?? fallbackFont;
canvasObject = new GameObject("TextChat Canvas", new Type[4]
{
typeof(RectTransform),
typeof(Canvas),
typeof(CanvasScaler),
typeof(GraphicRaycaster)
});
canvasObject.transform.SetParent(((Component)this).transform, false);
Canvas component = canvasObject.GetComponent<Canvas>();
component.renderMode = (RenderMode)0;
component.sortingOrder = 31000;
CanvasScaler component2 = canvasObject.GetComponent<CanvasScaler>();
component2.uiScaleMode = (ScaleMode)1;
component2.referenceResolution = new Vector2(1920f, 1080f);
component2.matchWidthOrHeight = 0.5f;
panel = Rect("Crew chat", canvasObject.transform, new Vector2(560f, 300f));
RectTransform obj = panel;
Vector2 anchorMin = (panel.anchorMax = Vector2.zero);
obj.anchorMin = anchorMin;
panel.pivot = Vector2.zero;
panel.anchoredPosition = new Vector2(24f, plugin.BottomOffset.Value);
Background(((Component)panel).gameObject, new Color(0.055f, 0.05f, 0.04f, 0.84f));
group = ((Component)panel).gameObject.AddComponent<CanvasGroup>();
group.alpha = 0f;
group.blocksRaycasts = false;
viewport = Rect("Messages", (Transform)(object)panel, Vector2.zero);
Stretch(viewport, new Vector2(14f, 66f), new Vector2(-14f, -12f));
Background(((Component)viewport).gameObject, Color.clear);
((Component)viewport).gameObject.AddComponent<RectMask2D>();
scroll = ((Component)viewport).gameObject.AddComponent<ScrollRect>();
scroll.horizontal = false;
scroll.movementType = (MovementType)2;
scroll.scrollSensitivity = 32f;
scroll.viewport = viewport;
content = Rect("History", (Transform)(object)viewport, Vector2.zero);
content.anchorMin = new Vector2(0f, 1f);
content.anchorMax = Vector2.one;
content.pivot = new Vector2(0.5f, 1f);
content.sizeDelta = Vector2.zero;
VerticalLayoutGroup obj2 = ((Component)content).gameObject.AddComponent<VerticalLayoutGroup>();
((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = true;
((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = true;
((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = true;
((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = false;
((HorizontalOrVerticalLayoutGroup)obj2).spacing = 5f;
((Component)content).gameObject.AddComponent<ContentSizeFitter>().verticalFit = (FitMode)2;
scroll.content = content;
inputRect = Rect("Message input", (Transform)(object)panel, new Vector2(532f, 36f));
RectTransform obj3 = inputRect;
anchorMin = (inputRect.anchorMax = Vector2.zero);
obj3.anchorMin = anchorMin;
inputRect.pivot = Vector2.zero;
inputRect.anchoredPosition = new Vector2(14f, 26f);
Image targetGraphic = Background(((Component)inputRect).gameObject, new Color(0.94f, 0.93f, 0.89f));
TextMeshProUGUI val = Label("", (Transform)(object)inputRect, plugin.FontSize.Value, new Color(0.1f, 0.09f, 0.07f));
Stretch(((TMP_Text)val).rectTransform, new Vector2(10f, 2f), new Vector2(-10f, -2f));
((TMP_Text)val).alignment = (TextAlignmentOptions)4097;
((TMP_Text)val).richText = false;
((TMP_Text)val).textWrappingMode = (TextWrappingModes)0;
TextMeshProUGUI val2 = Label("Type a message...", (Transform)(object)inputRect, 18, new Color(0.4f, 0.37f, 0.32f));
Stretch(((TMP_Text)val2).rectTransform, new Vector2(10f, 2f), new Vector2(-10f, -2f));
((TMP_Text)val2).alignment = (TextAlignmentOptions)4097;
input = ((Component)inputRect).gameObject.AddComponent<ChatInputField>();
input.Owner = this;
((Selectable)input).targetGraphic = (Graphic)(object)targetGraphic;
((TMP_InputField)input).textComponent = (TMP_Text)(object)val;
((TMP_InputField)input).textViewport = inputRect;
((TMP_InputField)input).richText = false;
((TMP_InputField)input).onFocusSelectAll = false;
((TMP_InputField)input).placeholder = (Graphic)(object)val2;
((TMP_InputField)input).characterLimit = 300;
((TMP_InputField)input).lineType = (LineType)0;
((TMP_InputField)input).customCaretColor = true;
((TMP_InputField)input).caretColor = new Color(0.12f, 0.1f, 0.08f);
((UnityEvent<string>)(object)((TMP_InputField)input).onValueChanged).AddListener((UnityAction<string>)delegate(string value)
{
count.text = value.Length + "/300";
});
hint = (TMP_Text)(object)Label("ENTER send / ESC close / Scroll history", (Transform)(object)panel, 12, new Color(0.6f, 0.66f, 0.71f));
Place(hint.rectTransform, 14f, -278f, 460f, 20f);
count = (TMP_Text)(object)Label("0/300", (Transform)(object)panel, 12, new Color(0.6f, 0.66f, 0.71f));
Place(count.rectTransform, 480f, -278f, 66f, 20f);
count.alignment = (TextAlignmentOptions)4100;
((Selectable)input).interactable = false;
((Behaviour)scroll).enabled = false;
}
private Player LocalPlayer()
{
if (!((Object)(object)NetworkClient.localPlayer == (Object)null))
{
return ((Component)NetworkClient.localPlayer).GetComponent<PlayerController>()?.player;
}
return null;
}
private bool InGameplayScene()
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
Scene activeScene = SceneManager.GetActiveScene();
if (((Scene)(ref activeScene)).IsValid() && ((Scene)(ref activeScene)).isLoaded)
{
return !string.Equals(((Scene)(ref activeScene)).name, "Menu", StringComparison.OrdinalIgnoreCase);
}
return false;
}
public void Tick()
{
//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
//IL_0162: Unknown result type (might be due to invalid IL or missing references)
//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
//IL_01fa: 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)
RefreshGameFont();
if (restorePending && plugin.ClosedFrame != Time.frameCount)
{
RestoreInput();
}
Player val = LocalPlayer();
if (!InGameplayScene() || !NetworkClient.isConnected || !NetworkClient.ready || NetworkClient.isLoadingScene || !((Object)(object)val != (Object)null) || !((Behaviour)val).isActiveAndEnabled || !val.IsInputReady)
{
if (IsOpen || rows.Count > 0)
{
ResetSession();
}
group.alpha = 0f;
group.blocksRaycasts = false;
canvasObject.SetActive(false);
return;
}
canvasObject.SetActive(true);
panel.anchoredPosition = new Vector2(24f, plugin.BottomOffset.Value);
panel.sizeDelta = new Vector2(560f, (float)(IsOpen ? 300 : 180));
((Component)inputRect).gameObject.SetActive(IsOpen);
((Component)hint).gameObject.SetActive(IsOpen);
((Component)count).gameObject.SetActive(IsOpen);
viewport.offsetMin = new Vector2(14f, (float)(IsOpen ? 66 : 10));
Keyboard current = Keyboard.current;
if (IsOpen)
{
if (!NetworkClient.isConnected || (Object)(object)LocalPlayer() != (Object)(object)capturedPlayer || !Application.isFocused || ((Object)(object)GameMenu.instance != (Object)null && GameMenu.instance.IsOpen) || (Object)(object)module == (Object)null || (Object)(object)EventSystem.current == (Object)null || (Object)(object)EventSystem.current.currentInputModule != (Object)(object)module)
{
Close();
}
else
{
GameplayActions gameplayInput = capturedPlayer.GameplayInput;
((GameplayActions)(ref gameplayInput)).Disable();
Cursor.lockState = (CursorLockMode)0;
Cursor.visible = true;
if (current != null && Time.frameCount > openFrame && (((ButtonControl)current.enterKey).wasPressedThisFrame || ((ButtonControl)current.numpadEnterKey).wasPressedThisFrame))
{
RequestSubmit();
}
if (current != null && ((ButtonControl)current.escapeKey).wasPressedThisFrame && Time.frameCount > openFrame)
{
Close();
}
}
}
else if (current != null && plugin.ClosedFrame != Time.frameCount && NetworkClient.isConnected && Application.isFocused && (int)plugin.OpenKey.Value != 0 && ((ButtonControl)current[plugin.OpenKey.Value]).wasPressedThisFrame && ((Object)(object)GameMenu.instance == (Object)null || !GameMenu.instance.IsOpen) && !KeybindPanel.IsRebinding && (Object)(object)LocalPlayer() != (Object)null && !OtherTextFieldSelected())
{
Open();
}
float alpha = ((!NetworkClient.isConnected) ? 0f : (IsOpen ? 1f : Mathf.Clamp01(plugin.FadeSeconds.Value + 1f - (Time.unscaledTime - lastMessage))));
group.alpha = alpha;
}
private bool OtherTextFieldSelected()
{
GameObject val = (((Object)(object)EventSystem.current == (Object)null) ? null : EventSystem.current.currentSelectedGameObject);
if ((Object)(object)val != (Object)null)
{
if (!((Object)(object)val.GetComponent<InputField>() != (Object)null))
{
return (Object)(object)val.GetComponent<TMP_InputField>() != (Object)null;
}
return true;
}
return false;
}
private void Open()
{
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
//IL_0089: Expected O, but got Unknown
//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
//IL_01de: Unknown result type (might be due to invalid IL or missing references)
//IL_021c: Unknown result type (might be due to invalid IL or missing references)
//IL_0221: Unknown result type (might be due to invalid IL or missing references)
//IL_022a: 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)
if (!InGameplayScene() || !NetworkClient.isConnected || !NetworkClient.ready || NetworkClient.isLoadingScene)
{
return;
}
capturedPlayer = LocalPlayer();
if ((Object)(object)capturedPlayer == (Object)null || !capturedPlayer.IsInputReady)
{
return;
}
RestoreInput();
if ((Object)(object)EventSystem.current == (Object)null)
{
ownEventSystem = new GameObject("TextChat EventSystem", new Type[2]
{
typeof(EventSystem),
typeof(InputSystemUIInputModule)
});
ownEventSystem.transform.SetParent(((Component)this).transform, false);
ownEventSystem.GetComponent<InputSystemUIInputModule>().AssignDefaultActions();
}
module = EventSystem.current.currentInputModule;
if ((Object)(object)module == (Object)null)
{
return;
}
savedSelection = EventSystem.current.currentSelectedGameObject;
savedOverride = module.inputOverride;
bridge = ((Component)module).gameObject.AddComponent<ChatBaseInput>();
bridge.Owner = this;
module.inputOverride = (BaseInput)(object)bridge;
keyboard = Keyboard.current;
Composition = "";
CompositionFrame = -10;
submitPending = false;
committedFrame = -10;
hint.text = "ENTER send / ESC close / Scroll history";
if (keyboard != null)
{
keyboard.onIMECompositionChange += OnComposition;
keyboard.onTextInput += OnTextInput;
keyboard.SetIMEEnabled(true);
}
savedImeMode = Input.imeCompositionMode;
Input.imeCompositionMode = (IMECompositionMode)1;
nativeIme = WindowsImeContext.Acquire();
GameplayActions gameplayInput = capturedPlayer.GameplayInput;
Enumerator<InputAction> enumerator = ((GameplayActions)(ref gameplayInput)).Get().actions.GetEnumerator();
try
{
while (enumerator.MoveNext())
{
InputAction current = enumerator.Current;
if (current.enabled)
{
restoreActions.Add(current);
}
}
}
finally
{
((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
}
gameplayInput = capturedPlayer.GameplayInput;
((GameplayActions)(ref gameplayInput)).Disable();
savedLock = Cursor.lockState;
savedVisible = Cursor.visible;
IsOpen = true;
openFrame = Time.frameCount;
Cursor.lockState = (CursorLockMode)0;
Cursor.visible = true;
group.blocksRaycasts = true;
((Component)inputRect).gameObject.SetActive(true);
((Component)hint).gameObject.SetActive(true);
((Component)count).gameObject.SetActive(true);
((Selectable)input).interactable = true;
((Behaviour)scroll).enabled = true;
((TMP_InputField)input).text = "";
EventSystem.current.SetSelectedGameObject(((Component)input).gameObject);
((TMP_InputField)input).ActivateInputField();
ScrollToBottom();
}
private unsafe void OnComposition(IMECompositionString value)
{
Composition = ((object)(*(IMECompositionString*)(&value))/*cast due to .constrained prefix*/).ToString();
CompositionFrame = Time.frameCount;
input.RefreshComposition();
}
private void OnTextInput(char value)
{
if (IsOpen && Time.frameCount > openFrame)
{
if (value == '\r' || value == '\n')
{
RequestSubmit();
}
else if (!char.IsControl(value))
{
Composition = "";
input.ReceiveCharacter(value);
committedFrame = Time.frameCount;
}
}
}
internal void RequestSubmit()
{
if (IsOpen && !submitPending)
{
submitPending = true;
submitFrame = Time.frameCount;
if (IsComposing)
{
nativeIme?.CompleteComposition();
}
}
}
private void LateUpdate()
{
ProcessPendingSubmit();
}
private void ProcessPendingSubmit()
{
if (submitPending && IsOpen && Time.frameCount > submitFrame && Time.frameCount > committedFrame && Time.frameCount > CompositionFrame && Composition.Length <= 0 && string.IsNullOrEmpty(Input.compositionString))
{
submitPending = false;
TrySubmit();
}
}
private void RefreshGameFont()
{
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
if (Time.unscaledTime < fontRefreshAt)
{
return;
}
fontRefreshAt = Time.unscaledTime + 2f;
Dictionary<TMP_FontAsset, int> dictionary = new Dictionary<TMP_FontAsset, int>();
TextMeshProUGUI[] array = Resources.FindObjectsOfTypeAll<TextMeshProUGUI>();
foreach (TextMeshProUGUI val in array)
{
if ((Object)(object)((TMP_Text)val).font == (Object)null || ((TMP_Text)val).transform.IsChildOf(canvasObject.transform))
{
continue;
}
Scene scene = ((Component)val).gameObject.scene;
if (((Scene)(ref scene)).IsValid())
{
if (!dictionary.ContainsKey(((TMP_Text)val).font))
{
dictionary[((TMP_Text)val).font] = 0;
}
dictionary[((TMP_Text)val).font]++;
}
}
int num = 0;
TMP_FontAsset key = font;
foreach (KeyValuePair<TMP_FontAsset, int> item in dictionary)
{
if (item.Value > num)
{
key = item.Key;
num = item.Value;
}
}
if (!((Object)(object)key == (Object)null) && !((Object)(object)key == (Object)(object)font))
{
font = key;
TMP_Text[] componentsInChildren = canvasObject.GetComponentsInChildren<TMP_Text>(true);
for (int i = 0; i < componentsInChildren.Length; i++)
{
componentsInChildren[i].font = font;
}
}
}
internal void ProcessInput(BaseEventData data)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Expected O, but got Unknown
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Invalid comparison between Unknown and I4
//IL_0091: Unknown result type (might be due to invalid IL or missing references)
//IL_0098: Invalid comparison between Unknown and I4
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Invalid comparison between Unknown and I4
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
//IL_00a2: Invalid comparison between Unknown and I4
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Invalid comparison between Unknown and I4
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Invalid comparison between Unknown and I4
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
//IL_006f: Invalid comparison between Unknown and I4
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Invalid comparison between Unknown and I4
Event val = new Event();
while (Event.PopEvent(val))
{
if (!IsOpen || Time.frameCount <= openFrame)
{
continue;
}
if ((int)val.rawType == 4)
{
if ((int)val.keyCode == 13 || (int)val.keyCode == 271)
{
RequestSubmit();
}
else if ((int)val.keyCode == 27)
{
Close();
}
else if (!IsComposing || ((int)val.keyCode != 8 && (int)val.keyCode != 127))
{
val.character = '\0';
((TMP_InputField)input).ProcessEvent(val);
}
}
else if (((int)val.type == 13 || (int)val.type == 14) && val.commandName == "SelectAll")
{
input.SelectAllText();
}
}
input.RefreshComposition();
((AbstractEventData)data).Use();
}
internal void TrySubmit()
{
string text = ChatRules.Clean(((TMP_InputField)input).text);
if (text.Length == 0)
{
Close();
}
else if (Time.unscaledTime - lastSent < plugin.MessageInterval.Value)
{
hint.text = "Please wait before sending another message";
}
else if (plugin.Network.Send(text))
{
lastSent = Time.unscaledTime;
Close();
}
}
public void Close()
{
//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
//IL_0192: Unknown result type (might be due to invalid IL or missing references)
if (IsOpen)
{
IsOpen = false;
submitPending = false;
plugin.ClosedFrame = Time.frameCount;
((TMP_InputField)input).DeactivateInputField(false);
((Selectable)input).interactable = false;
((TMP_InputField)input).text = "";
group.blocksRaycasts = false;
((Behaviour)scroll).enabled = false;
if ((Object)(object)module != (Object)null && (Object)(object)module.inputOverride == (Object)(object)bridge)
{
module.inputOverride = savedOverride;
}
if ((Object)(object)bridge != (Object)null)
{
Object.Destroy((Object)(object)bridge);
}
if (keyboard != null)
{
keyboard.onIMECompositionChange -= OnComposition;
keyboard.onTextInput -= OnTextInput;
keyboard.SetIMEEnabled(false);
}
Input.imeCompositionMode = savedImeMode;
nativeIme?.Dispose();
nativeIme = null;
Composition = "";
if ((Object)(object)EventSystem.current != (Object)null && (Object)(object)EventSystem.current.currentSelectedGameObject == (Object)(object)((Component)input).gameObject)
{
EventSystem.current.SetSelectedGameObject(savedSelection);
}
if ((!((Object)(object)GameMenu.instance != (Object)null) || !GameMenu.instance.IsOpen) && NetworkClient.isConnected && (Object)(object)capturedPlayer != (Object)null)
{
Cursor.lockState = savedLock;
Cursor.visible = savedVisible;
}
restorePending = true;
ScrollToBottom();
}
}
private void RestoreInput()
{
//IL_004d: 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_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_0062: 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)
if (restorePending && (Object)(object)capturedPlayer != (Object)null && NetworkClient.isConnected && ((Object)(object)GameMenu.instance == (Object)null || !GameMenu.instance.IsOpen))
{
capturedPlayer.RestoreGameplayInput();
GameplayActions gameplayInput = capturedPlayer.GameplayInput;
Enumerator<InputAction> enumerator = ((GameplayActions)(ref gameplayInput)).Get().actions.GetEnumerator();
try
{
while (enumerator.MoveNext())
{
InputAction current = enumerator.Current;
if (!restoreActions.Contains(current))
{
current.Disable();
}
}
}
finally
{
((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
}
}
restoreActions.Clear();
restorePending = false;
}
public void Add(string name, string text, bool system)
{
//IL_0098: 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)
bool flag = !IsOpen || scroll.verticalNormalizedPosition <= 0.05f;
TextMeshProUGUI val = Label(DateTime.Now.ToString("HH:mm") + " " + name + ": " + text, (Transform)(object)content, plugin.FontSize.Value, system ? new Color(0.84f, 0.8f, 0.68f) : new Color(0.94f, 0.95f, 0.96f));
((TMP_Text)val).richText = false;
((TMP_Text)val).textWrappingMode = (TextWrappingModes)1;
((TMP_Text)val).overflowMode = (TextOverflowModes)0;
((Component)val).gameObject.AddComponent<LayoutElement>().minHeight = plugin.FontSize.Value + 5;
rows.Enqueue(((Component)val).gameObject);
while (rows.Count > plugin.HistoryLimit.Value)
{
GameObject obj = rows.Dequeue();
obj.SetActive(false);
Object.Destroy((Object)(object)obj);
}
lastMessage = Time.unscaledTime;
if (flag)
{
ScrollToBottom();
}
}
private void ScrollToBottom()
{
Canvas.ForceUpdateCanvases();
LayoutRebuilder.ForceRebuildLayoutImmediate(content);
scroll.verticalNormalizedPosition = 0f;
}
public void ResetSession()
{
Close();
while (rows.Count > 0)
{
GameObject obj = rows.Dequeue();
obj.SetActive(false);
Object.Destroy((Object)(object)obj);
}
lastMessage = -1000f;
lastSent = -1000f;
}
private void OnDestroy()
{
Close();
RestoreInput();
if ((Object)(object)canvasObject != (Object)null)
{
Object.Destroy((Object)(object)canvasObject);
}
if ((Object)(object)ownEventSystem != (Object)null)
{
Object.Destroy((Object)(object)ownEventSystem);
}
if ((Object)(object)fallbackFont != (Object)null)
{
Object.Destroy((Object)(object)fallbackFont);
}
}
private static RectTransform Rect(string name, Transform parent, Vector2 size)
{
//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)
RectTransform component = new GameObject(name, new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>();
((Transform)component).SetParent(parent, false);
component.sizeDelta = size;
return component;
}
private TextMeshProUGUI Label(string value, Transform parent, int size, Color color)
{
//IL_0006: 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)
TextMeshProUGUI obj = ((Component)Rect("Text", parent, Vector2.zero)).gameObject.AddComponent<TextMeshProUGUI>();
((TMP_Text)obj).font = font;
((TMP_Text)obj).fontSharedMaterial = ((TMP_Asset)font).material;
((TMP_Text)obj).text = value;
((TMP_Text)obj).fontSize = size;
((Graphic)obj).color = color;
((Graphic)obj).raycastTarget = false;
((TMP_Text)obj).richText = false;
return obj;
}
private static Image Background(GameObject obj, Color color)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
Image obj2 = obj.AddComponent<Image>();
((Graphic)obj2).color = color;
return obj2;
}
private static void Place(RectTransform rect, float x, float y, float width, float height)
{
//IL_0013: 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_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: 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)
Vector2 val = default(Vector2);
((Vector2)(ref val))..ctor(0f, 1f);
rect.anchorMax = val;
rect.anchorMin = val;
rect.pivot = new Vector2(0f, 1f);
rect.anchoredPosition = new Vector2(x, y);
rect.sizeDelta = new Vector2(width, height);
}
private static void Stretch(RectTransform rect, Vector2 min, Vector2 max)
{
//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_0017: 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)
rect.anchorMin = Vector2.zero;
rect.anchorMax = Vector2.one;
rect.offsetMin = min;
rect.offsetMax = max;
}
}
public sealed class ChatInputField : TMP_InputField
{
internal ChatView Owner;
public override void OnUpdateSelected(BaseEventData eventData)
{
if (((TMP_InputField)this).isFocused && (Object)(object)Owner != (Object)null)
{
Owner.ProcessInput(eventData);
}
}
internal void RefreshComposition()
{
((TMP_InputField)this).UpdateLabel();
}
internal void SelectAllText()
{
((TMP_InputField)this).SelectAll();
}
internal void ReceiveCharacter(char value)
{
((TMP_InputField)this).Append(value);
((TMP_InputField)this).UpdateLabel();
}
}
public sealed class ChatBaseInput : BaseInput
{
internal ChatView Owner;
private Vector2 cursor;
public override string compositionString
{
get
{
if (!((Object)(object)Owner == (Object)null))
{
if (Owner.Composition.Length <= 0)
{
return Input.compositionString;
}
return Owner.Composition;
}
return "";
}
}
public override IMECompositionMode imeCompositionMode
{
get
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
return Input.imeCompositionMode;
}
set
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
Input.imeCompositionMode = value;
}
}
public override Vector2 compositionCursorPos
{
get
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
return cursor;
}
set
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
cursor = value;
Input.compositionCursorPos = value;
Keyboard current = Keyboard.current;
if (current != null)
{
current.SetIMECursorPosition(value);
}
}
}
public override bool touchSupported => false;
public override bool mousePresent => Mouse.current != null;
public override Vector2 mousePosition
{
get
{
//IL_0017: 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)
if (Mouse.current != null)
{
return ((InputControl<Vector2>)(object)((Pointer)Mouse.current).position).ReadValue();
}
return Vector2.zero;
}
}
public override Vector2 mouseScrollDelta
{
get
{
//IL_0017: 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)
if (Mouse.current != null)
{
return ((InputControl<Vector2>)(object)Mouse.current.scroll).ReadValue();
}
return Vector2.zero;
}
}
}
[BepInPlugin("crack.textchat", "CRACK TextChat", "1.0.0")]
[BepInProcess("CRACK.exe")]
[DefaultExecutionOrder(-10000)]
public sealed class Plugin : BaseUnityPlugin
{
public const string Guid = "crack.textchat";
internal static Plugin Instance;
internal ConfigEntry<bool> AssumeLanHost;
internal ConfigEntry<float> MessageInterval;
internal ConfigEntry<int> FontSize;
internal ConfigEntry<float> FadeSeconds;
internal ConfigEntry<int> HistoryLimit;
internal ConfigEntry<Key> OpenKey;
internal ConfigEntry<string> FontName;
internal ConfigEntry<float> BottomOffset;
internal ChatView View;
internal ChatNetwork Network;
private Harmony harmony;
internal int ClosedFrame = -1;
internal bool BlocksInput
{
get
{
if (!((Object)(object)View != (Object)null) || !View.IsOpen)
{
return ClosedFrame == Time.frameCount;
}
return true;
}
}
private void Awake()
{
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_0060: Expected O, but got Unknown
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_0095: Expected O, but got Unknown
//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
//IL_00d3: Expected O, but got Unknown
//IL_0101: Unknown result type (might be due to invalid IL or missing references)
//IL_010b: Expected O, but got Unknown
//IL_0164: Unknown result type (might be due to invalid IL or missing references)
//IL_016e: Expected O, but got Unknown
//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
//IL_01cd: Expected O, but got Unknown
Instance = this;
AssumeLanHost = ((BaseUnityPlugin)this).Config.Bind<bool>("Network", "AssumeLanHostHasMod", false, "LAN clients only: enable only if the host also has TextChat 1.x. Steam lobbies discover support automatically.");
MessageInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Network", "MessageIntervalSeconds", 0.75f, new ConfigDescription("Host-enforced minimum time between messages.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 10f), Array.Empty<object>()));
FontSize = ((BaseUnityPlugin)this).Config.Bind<int>("UI", "FontSize", 20, new ConfigDescription("Chat font size. Restart to apply.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(14, 32), Array.Empty<object>()));
FadeSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "VisibleSeconds", 12f, new ConfigDescription("Time before closed chat fades out.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(3f, 120f), Array.Empty<object>()));
HistoryLimit = ((BaseUnityPlugin)this).Config.Bind<int>("UI", "HistoryLimit", 100, new ConfigDescription("Maximum messages retained for this session.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(20, 300), Array.Empty<object>()));
FontName = ((BaseUnityPlugin)this).Config.Bind<string>("UI", "FontName", "Malgun Gothic", "Temporary OS fallback before the game's TextMeshPro font is loaded. The game's font and localized fallbacks are preferred.");
BottomOffset = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "BottomOffset", 200f, new ConfigDescription("Chat bottom margin at 1080p. Keeps chat above the hotbar.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(100f, 500f), Array.Empty<object>()));
OpenKey = ((BaseUnityPlugin)this).Config.Bind<Key>("Controls", "OpenKey", (Key)2, "Key used to open chat. Enter always sends while chat is open.");
Network = new ChatNetwork(this);
View = ((Component)this).gameObject.AddComponent<ChatView>();
View.Initialize(this);
harmony = new Harmony("crack.textchat");
harmony.PatchAll(typeof(Plugin).Assembly);
((BaseUnityPlugin)this).Logger.LogInfo((object)"CRACK TextChat 1.0.0 loaded. Press Enter in a game to chat.");
}
private void Update()
{
Network.Tick();
View.Tick();
}
private void OnDestroy()
{
Harmony obj = harmony;
if (obj != null)
{
obj.UnpatchSelf();
}
View?.Close();
Network?.Dispose();
if ((Object)(object)View != (Object)null)
{
Object.Destroy((Object)(object)View);
}
Instance = null;
}
[HarmonyPatch(typeof(GameMenu), "Update")]
[HarmonyPrefix]
private static bool MenuInput()
{
if (!((Object)(object)Instance == (Object)null))
{
return !Instance.BlocksInput;
}
return true;
}
[HarmonyPatch(typeof(Player), "RestoreGameplayInput")]
[HarmonyPostfix]
private static void RestoredInput(Player __instance)
{
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)Instance != (Object)null && Instance.BlocksInput && ((NetworkBehaviour)__instance).isOwned && __instance.IsInputReady)
{
GameplayActions gameplayInput = __instance.GameplayInput;
((GameplayActions)(ref gameplayInput)).Disable();
}
}
[HarmonyPatch(typeof(Player), "Update")]
[HarmonyPrefix]
private static void PlayerInput(Player __instance)
{
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)Instance != (Object)null && Instance.BlocksInput && ((NetworkBehaviour)__instance).isOwned && __instance.IsInputReady)
{
GameplayActions gameplayInput = __instance.GameplayInput;
((GameplayActions)(ref gameplayInput)).Disable();
}
}
}
internal sealed class WindowsImeContext : IDisposable
{
private IntPtr window;
private IntPtr created;
private IntPtr previous;
private bool changed;
internal static WindowsImeContext Acquire()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Invalid comparison between Unknown and I4
WindowsImeContext windowsImeContext = new WindowsImeContext();
if ((int)Application.platform != 2)
{
return windowsImeContext;
}
try
{
using (Process process = Process.GetCurrentProcess())
{
windowsImeContext.window = process.MainWindowHandle;
}
if (windowsImeContext.window == IntPtr.Zero)
{
return windowsImeContext;
}
IntPtr intPtr = ImmGetContext(windowsImeContext.window);
if (intPtr != IntPtr.Zero)
{
ImmReleaseContext(windowsImeContext.window, intPtr);
return windowsImeContext;
}
windowsImeContext.changed = ImmAssociateContextEx(windowsImeContext.window, IntPtr.Zero, 16u);
intPtr = ImmGetContext(windowsImeContext.window);
if (intPtr != IntPtr.Zero)
{
ImmReleaseContext(windowsImeContext.window, intPtr);
return windowsImeContext;
}
windowsImeContext.created = ImmCreateContext();
if (windowsImeContext.created != IntPtr.Zero)
{
windowsImeContext.previous = ImmAssociateContext(windowsImeContext.window, windowsImeContext.created);
windowsImeContext.changed = true;
}
}
catch (DllNotFoundException)
{
}
catch (EntryPointNotFoundException)
{
}
return windowsImeContext;
}
public void Dispose()
{
if (changed && window != IntPtr.Zero)
{
ImmAssociateContext(window, previous);
}
if (created != IntPtr.Zero)
{
ImmDestroyContext(created);
}
window = (created = IntPtr.Zero);
changed = false;
}
internal void CompleteComposition()
{
if (window == IntPtr.Zero)
{
return;
}
IntPtr intPtr = ImmGetContext(window);
if (intPtr == IntPtr.Zero)
{
return;
}
try
{
ImmNotifyIME(intPtr, 21u, 1u, 0u);
}
finally
{
ImmReleaseContext(window, intPtr);
}
}
[DllImport("imm32.dll")]
private static extern IntPtr ImmGetContext(IntPtr hwnd);
[DllImport("imm32.dll")]
private static extern bool ImmReleaseContext(IntPtr hwnd, IntPtr context);
[DllImport("imm32.dll")]
private static extern bool ImmAssociateContextEx(IntPtr hwnd, IntPtr context, uint flags);
[DllImport("imm32.dll")]
private static extern IntPtr ImmAssociateContext(IntPtr hwnd, IntPtr context);
[DllImport("imm32.dll")]
private static extern IntPtr ImmCreateContext();
[DllImport("imm32.dll")]
private static extern bool ImmDestroyContext(IntPtr context);
[DllImport("imm32.dll")]
private static extern bool ImmNotifyIME(IntPtr context, uint action, uint index, uint value);
}
}