using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using AK;
using Agents;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using CellMenu;
using Dissonance;
using GTFO.API;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Localization;
using Microsoft.CodeAnalysis;
using Player;
using SNetwork;
using TMPro;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("BetterTextChat")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("BetterTextChat")]
[assembly: AssemblyTitle("BetterTextChat")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.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]
[Microsoft.CodeAnalysis.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;
}
}
}
namespace BetterTextChat
{
internal static class BetterComposition
{
private static int caretPosition;
private static bool caretVisible;
private static float caretVisibilityTimer;
private static PlayerAgent? customFromPlayer;
private static PlayerAgent? customToPlayer;
[HarmonyPatch(typeof(PlayerChatManager), "UpdateTextChatInput")]
[HarmonyPrefix]
private static void PlayerChatManager__UpdateTextChatInput__Prefix(PlayerChatManager __instance, ref bool __runOriginal)
{
__runOriginal = false;
if (!PlayerChatManager.TextChatInputEnabled)
{
return;
}
if (PlayerChatManager.Current != null && !PlayerChatManager.InChatMode && InputMapper.GetButtonDownKeyMouseGamepad((InputAction)56, (eFocusState)0))
{
PlayerChatManager.Log("Open chat window");
__instance.EnterChatMode();
}
else if (InputMapper.GetButtonDownKeyMouseGamepad((InputAction)57, (eFocusState)0))
{
__instance.ExitChatMode();
}
else if (PlayerChatManager.Current != null && PlayerChatManager.InChatMode)
{
int num = caretPosition;
string currentValue = __instance.m_currentValue;
ChatInputRepetitionManager.Update();
UpdateCaretPosition(__instance);
UpdateMCurrentValue(__instance);
if (caretPosition != num || currentValue != __instance.m_currentValue)
{
UpdateCaretVisibility(forceVisible: true);
}
if (currentValue != __instance.m_currentValue)
{
TypingIndicator.OnLocalPlayerTyping();
}
UpdateRecipientPlayer();
__instance.m_currentImeCompositionString = Input.compositionString;
__instance.UpdateMessage();
}
}
private static void UpdateCaretPosition(PlayerChatManager __instance)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Invalid comparison between Unknown and I4
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Invalid comparison between Unknown and I4
if ((int)ChatInputRepetitionManager.inputActionThisFrame == 17)
{
caretPosition--;
}
if ((int)ChatInputRepetitionManager.inputActionThisFrame == 18)
{
caretPosition++;
}
if (InputMapper.GetButtonDownKeyMouseGamepad((InputAction)21, (eFocusState)0))
{
caretPosition = 0;
}
if (InputMapper.GetButtonDownKeyMouseGamepad((InputAction)22, (eFocusState)0))
{
caretPosition = __instance.m_currentValue.Length;
}
caretPosition = Mathf.Clamp(caretPosition, 0, __instance.m_currentValue.Length);
}
private static void UpdateMCurrentValue(PlayerChatManager __instance)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Invalid comparison between Unknown and I4
if ((int)ChatInputRepetitionManager.inputActionThisFrame == 19 && __instance.m_currentValue.Length > caretPosition)
{
__instance.m_currentValue = __instance.m_currentValue.Remove(caretPosition, 1);
}
string inputString = Input.inputString;
for (int i = 0; i < inputString.Length; i++)
{
char c = inputString[i];
if (!ConfigManager.allowForbiddenChars.Value && ((Il2CppArrayBase<int>)(object)__instance.m_forbiddenChars).Contains((int)c))
{
continue;
}
switch (c)
{
case '\b':
if (caretPosition > 0)
{
__instance.m_currentValue = __instance.m_currentValue.Remove(caretPosition - 1, 1);
caretPosition--;
}
break;
default:
if (c != '\r')
{
__instance.m_currentValue = __instance.m_currentValue.Insert(caretPosition, c.ToString());
caretPosition++;
break;
}
goto case '\n';
case '\n':
if (Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303))
{
__instance.m_currentValue = __instance.m_currentValue.Insert(caretPosition, "\n");
caretPosition++;
}
else
{
__instance.m_currentValue = WordWrap.Wrap(__instance.m_currentValue, __instance.m_maxLen);
__instance.m_currentImeCompositionString = "";
__instance.PostMessage();
}
break;
}
}
if ((Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305)) && Input.GetKeyDown((KeyCode)99))
{
GUIUtility.systemCopyBuffer = __instance.m_currentValue;
}
if ((Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305)) && Input.GetKeyDown((KeyCode)118))
{
string text = GUIUtility.systemCopyBuffer.ReplaceLineEndings("\n");
__instance.m_currentValue = __instance.m_currentValue.Insert(caretPosition, text);
caretPosition += text.Length;
}
}
private static void UpdateRecipientPlayer()
{
//IL_009d: Unknown result type (might be due to invalid IL or missing references)
//IL_00a2: 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_00b5: Unknown result type (might be due to invalid IL or missing references)
bool flag = Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305);
Dictionary<KeyCode, int> dictionary = new Dictionary<KeyCode, int>
{
{
(KeyCode)282,
0
},
{
(KeyCode)283,
1
},
{
(KeyCode)284,
2
},
{
(KeyCode)285,
3
},
{
(KeyCode)286,
4
},
{
(KeyCode)287,
5
},
{
(KeyCode)288,
6
},
{
(KeyCode)289,
7
}
};
foreach (KeyCode key in dictionary.Keys)
{
if (!Input.GetKeyDown(key))
{
continue;
}
int num = dictionary[key];
Enumerator<PlayerAgent> enumerator2 = PlayerManager.PlayerAgentsInLevel.GetEnumerator();
while (enumerator2.MoveNext())
{
PlayerAgent current2 = enumerator2.Current;
if (current2.PlayerSlotIndex == num)
{
if (flag)
{
customFromPlayer = (((Object)(object)customFromPlayer == (Object)(object)current2) ? null : current2);
}
else
{
customToPlayer = (((Object)(object)customToPlayer == (Object)(object)current2) ? null : current2);
}
break;
}
}
break;
}
}
[HarmonyPatch(typeof(PlayerChatManager), "EnterChatMode")]
[HarmonyPostfix]
private static void PlayerChatManager__EnterChatMode__Postfix()
{
UpdateCaretVisibility(forceVisible: true);
}
[HarmonyPatch(typeof(PlayerChatManager), "ExitChatMode")]
[HarmonyPostfix]
private static void PlayerChatManager__ExitChatMode__Postfix(PlayerChatManager __instance)
{
if (ConfigManager.discardDraftMessage.Value)
{
caretPosition = 0;
__instance.m_currentValue = "";
__instance.m_currentImeCompositionString = "";
customFromPlayer = null;
customToPlayer = null;
__instance.UpdateMessage();
}
}
[HarmonyPatch(typeof(PlayerChatManager), "PostMessage")]
[HarmonyPrefix]
private static void PlayerChatManager__PostMessage__Prefix(ref bool __runOriginal)
{
__runOriginal = false;
}
[HarmonyPatch(typeof(PlayerChatManager), "PostMessage")]
[HarmonyPostfix]
private static void PlayerChatManager__PostMessage__Postfix(PlayerChatManager __instance)
{
if (__instance.m_currentValue.Trim('\n').Length > 0)
{
string text = WordWrap.Wrap(__instance.m_currentValue, __instance.m_maxLen);
if (customFromPlayer == null)
{
customFromPlayer = PlayerManager.GetLocalPlayerAgent();
}
string[] array = text.Split('\n');
foreach (string text2 in array)
{
PlayerChatManager.WantToSentTextMessage(customFromPlayer, text2, customToPlayer);
}
}
caretPosition = 0;
__instance.m_currentValue = "";
__instance.m_currentImeCompositionString = "";
customFromPlayer = null;
customToPlayer = null;
__instance.ExitChatMode();
}
[HarmonyPatch(typeof(PUI_GameEventLog), "Update")]
[HarmonyPostfix]
private static void PUI_GameEventLog__Update__Postfix(PUI_GameEventLog __instance)
{
//IL_0262: Unknown result type (might be due to invalid IL or missing references)
//IL_026d: Unknown result type (might be due to invalid IL or missing references)
//IL_0299: Unknown result type (might be due to invalid IL or missing references)
if (PlayerChatManager.InChatMode)
{
((TMP_Text)__instance.m_txtInput).enableWordWrapping = false;
((TMP_Text)__instance.m_txtInput).overflowMode = (TextOverflowModes)0;
((TMP_Text)__instance.m_txtInput).alignment = (TextAlignmentOptions)1025;
UpdateCaretVisibility();
string text = __instance.m_textInputString ?? "";
if (caretPosition == text.Length)
{
if (caretVisible)
{
text += "_";
text = WordWrap.Wrap(text, PlayerChatManager.Current.m_maxLen);
}
else
{
text += " ";
text = WordWrap.Wrap(text, PlayerChatManager.Current.m_maxLen);
}
}
else if (caretVisible)
{
char c = text[caretPosition];
char c2 = (char)WordWrap.GetCharType(c);
text = text.Remove(caretPosition, 1);
text = text.Insert(caretPosition, c2.ToString());
text = WordWrap.Wrap(text, PlayerChatManager.Current.m_maxLen);
string text2 = "<mark=#FFF>_</mark>";
if (c2 == '\ue000')
{
text2 += "\n";
}
text = text.Replace(c2.ToString(), text2);
}
else
{
text = WordWrap.Wrap(text, PlayerChatManager.Current.m_maxLen);
}
((TMP_Text)__instance.m_txtInput).text = text;
}
else
{
((TMP_Text)__instance.m_txtInput).text = "";
}
string text3 = "";
if (customFromPlayer != null)
{
text3 = text3 + "From " + PlayerNameExtentions.GetColoredName(customFromPlayer, (string)null) + "\n";
}
if (customToPlayer != null)
{
text3 = text3 + "To " + PlayerNameExtentions.GetColoredName(customToPlayer, (string)null) + "\n";
}
if (text3.Length > 0)
{
((TMP_Text)__instance.m_txtInput).text = "<size=80%>" + text3 + "\n</size>" + ((TMP_Text)__instance.m_txtInput).text;
}
float num = ((TMP_Text)__instance.m_txtInput).preferredHeight + 5.1f;
Transform val = __instance.m_chatActiveRoot.transform.FindChild("Input Background Active");
SpriteRenderer component = ((Component)val).GetComponent<SpriteRenderer>();
component.size = new Vector2(component.size.x, num);
RectTransform component2 = ((Component)val).GetComponent<RectTransform>();
((Transform)component2).localPosition = new Vector3(0f, num / 2f - 1f, 0f);
__instance.ShowAndUpdateItemPositions();
}
[HarmonyPatch(typeof(PUI_GameEventLog), "ShowAndUpdateItemPositions")]
[HarmonyPrefix]
private static void PUI_GameEventLog__ShowAndUpdateItemPositions__Prefix(PUI_GameEventLog __instance, ref bool __runOriginal)
{
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
__runOriginal = false;
float num = ((TMP_Text)__instance.m_txtInput).preferredHeight + 5.1f;
float num2 = (((TMP_Text)__instance.m_txtInput).text.Contains('\n') ? (num - __instance.m_logItemHeight) : 0f);
for (int i = 0; i < __instance.m_logItems.Count; i++)
{
((Component)__instance.m_logItems[i]).transform.localPosition = new Vector3(0f, num2 + (float)(__instance.m_logItems.Count - i - 1) * __instance.m_logItemHeight);
}
}
private static void UpdateCaretVisibility(bool forceVisible = false)
{
if (forceVisible)
{
caretVisible = true;
caretVisibilityTimer = Time.time + 0.6f;
}
else if (Time.time > caretVisibilityTimer)
{
caretVisible = !caretVisible;
caretVisibilityTimer = Time.time + 0.6f;
}
}
}
internal static class ChatInputRepetitionManager
{
private static readonly InputAction[] inputActionsToWatch;
private static InputAction repeatInputAction;
private static float repeatDelayTimer;
private static float repeatRateTimer;
public static InputAction inputActionThisFrame;
public static void Update()
{
//IL_0002: 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_0069: Unknown result type (might be due to invalid IL or missing references)
//IL_0092: Unknown result type (might be due to invalid IL or missing references)
//IL_0095: 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_00a6: Unknown result type (might be due to invalid IL or missing references)
//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
inputActionThisFrame = (InputAction)0;
if (!PlayerChatManager.InChatMode)
{
return;
}
if (InputMapper.GetButtonKeyMouseGamepad(repeatInputAction, (eFocusState)0))
{
if (Time.time > repeatDelayTimer && Time.time > repeatRateTimer)
{
inputActionThisFrame = repeatInputAction;
repeatRateTimer = Time.time + 0.05f;
}
return;
}
repeatInputAction = (InputAction)0;
repeatDelayTimer = 0f;
repeatRateTimer = 0f;
InputAction[] array = inputActionsToWatch;
foreach (InputAction val in array)
{
if (InputMapper.GetButtonKeyMouseGamepad(val, (eFocusState)0))
{
inputActionThisFrame = val;
repeatInputAction = val;
repeatDelayTimer = Time.time + 0.35f;
break;
}
}
}
static ChatInputRepetitionManager()
{
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
InputAction[] array = new InputAction[3];
RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
inputActionsToWatch = (InputAction[])(object)array;
repeatInputAction = (InputAction)0;
repeatDelayTimer = 0f;
repeatRateTimer = 0f;
inputActionThisFrame = (InputAction)0;
}
}
internal static class WordWrap
{
public enum CharType
{
LineSeparator = 57344,
WordSeparator,
Other
}
public static CharType GetCharType(char c)
{
if (c == '\ue000' || c == '\n')
{
return CharType.LineSeparator;
}
if (c == '\ue001' || char.IsSeparator(c))
{
return CharType.WordSeparator;
}
return CharType.Other;
}
public static string Wrap(string original_text, int width)
{
StringBuilder stringBuilder = new StringBuilder();
StringBuilder stringBuilder2 = new StringBuilder();
StringBuilder stringBuilder3 = new StringBuilder();
foreach (char c in original_text)
{
if (GetCharType(c) == CharType.LineSeparator)
{
if (stringBuilder2.Length + stringBuilder3.Length > width)
{
stringBuilder.Append(stringBuilder2);
stringBuilder.Append('\n');
stringBuilder2.Clear();
}
stringBuilder2.Append(stringBuilder3);
stringBuilder3.Clear();
stringBuilder.Append(stringBuilder2);
stringBuilder.Append(c);
stringBuilder2.Clear();
}
else if (GetCharType(c) == CharType.WordSeparator)
{
if (stringBuilder2.Length + stringBuilder3.Length > width)
{
stringBuilder.Append(stringBuilder2);
stringBuilder.Append('\n');
stringBuilder2.Clear();
}
stringBuilder2.Append(stringBuilder3);
stringBuilder2.Append(c);
stringBuilder3.Clear();
}
else
{
stringBuilder3.Append(c);
if (stringBuilder3.Length > width)
{
int num = width - stringBuilder2.Length;
stringBuilder2.Append(stringBuilder3.ToString(0, num));
stringBuilder3.Remove(0, num);
stringBuilder.Append(stringBuilder2);
stringBuilder.Append('\n');
stringBuilder2.Clear();
}
}
}
if (stringBuilder2.Length + stringBuilder3.Length > width)
{
stringBuilder.Append(stringBuilder2);
stringBuilder.Append('\n');
stringBuilder2.Clear();
}
stringBuilder2.Append(stringBuilder3);
stringBuilder3.Clear();
stringBuilder.Append(stringBuilder2);
stringBuilder2.Clear();
if (stringBuilder.Length > 0)
{
if (stringBuilder[stringBuilder.Length - 1] == '\n')
{
if (original_text[original_text.Length - 1] != '\n')
{
stringBuilder.Remove(stringBuilder.Length - 1, 1);
}
}
}
return stringBuilder.ToString();
}
}
internal static class PluginInfo
{
public const string GUID = "Andocas.BetterTextChat";
public const string NAME = "BetterTextChat";
public const string VERSION = "0.5.0";
}
[BepInPlugin("Andocas.BetterTextChat", "BetterTextChat", "0.5.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
internal class Plugin : BasePlugin
{
public override void Load()
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Expected O, but got Unknown
Utils.LogInfo("Andocas.BetterTextChat is loading...");
Harmony val = new Harmony("Andocas.BetterTextChat");
val.PatchAll(typeof(BetterComposition));
PUI_GameEventLog.s_logItemsMax = ConfigManager.chatHistoryLength.Value;
val.PatchAll(typeof(ScrollableGameEventLog));
TypingIndicator.Setup();
val.PatchAll(typeof(TypingIndicator));
((BasePlugin)this).AddComponent<PttSoundPlayer>();
Utils.LogInfo("Andocas.BetterTextChat is loaded");
}
}
internal static class ConfigManager
{
public static readonly ConfigEntry<bool> allowForbiddenChars;
public static readonly ConfigEntry<bool> discardDraftMessage;
public static readonly ConfigEntry<int> chatHistoryLength;
public static readonly ConfigEntry<bool> showTypingIndicator;
public static readonly ConfigEntry<bool> sendTypingIndicator;
static ConfigManager()
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Expected O, but got Unknown
ConfigFile val = new ConfigFile(Path.Combine(Paths.ConfigPath, "BetterTextChat.cfg"), true);
allowForbiddenChars = val.Bind<bool>("General", "Allow special characters", true, "Makes it possible to type <, >, and = in chat. (Beware: Things can get weird if you use formatting tags, especially across multiple lines.)");
discardDraftMessage = val.Bind<bool>("General", "Discard draft message", false, "In vanilla, when you close the chat box, your message will still be there next time you open it. This option clears the chat box when it's closed.");
chatHistoryLength = val.Bind<int>("General", "Chat history length", 15, "Number of messages to show at once in the chat history.");
showTypingIndicator = val.Bind<bool>("Typing indicator", "Display typing indicator", true, "Show a message like [PlayerName is typing...] when other BetterTextChat users are typing in chat.");
sendTypingIndicator = val.Bind<bool>("Typing indicator", "Send typing indicator", true, "Let other BetterTextChat users know when you are typing in chat.");
}
}
internal static class ScrollableGameEventLog
{
private static readonly Dictionary<int, PUI_GameEventLog_ExtensionData> extensionDataForEachInstance = new Dictionary<int, PUI_GameEventLog_ExtensionData>();
private static PUI_GameEventLog_ExtensionData GetInstanceData(PUI_GameEventLog __instance)
{
int instanceID = ((Object)__instance).GetInstanceID();
if (!extensionDataForEachInstance.ContainsKey(instanceID))
{
extensionDataForEachInstance[instanceID] = new PUI_GameEventLog_ExtensionData(instanceID);
}
return extensionDataForEachInstance[instanceID];
}
[HarmonyPatch(typeof(PUI_GameEventLog), "AddLogItem")]
[HarmonyPrefix]
private static void PUI_GameEventLog__AddLogItem__Prefix(PUI_GameEventLog __instance, ref bool __runOriginal, string log, eGameEventChatLogType type)
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
__runOriginal = false;
PUI_GameEventLog_ExtensionData instanceData = GetInstanceData(__instance);
log = FixMessagesFromBots(log, type);
instanceData.rawEventLog.Add((log, type));
UpdateMLogItems(__instance);
}
[HarmonyPatch(typeof(PUI_GameEventLog), "OnLevelCleanup")]
[HarmonyPrefix]
private static void PUI_GameEventLog__OnLevelCleanup__Prefix(PUI_GameEventLog __instance, ref bool __runOriginal)
{
__runOriginal = false;
if ((Object)(object)__instance != (Object)(object)CM_PageLoadout.Current.m_gameEventLog)
{
PUI_GameEventLog_ExtensionData instanceData = GetInstanceData(GuiManager.PlayerLayer.m_gameEventLog);
instanceData.rawEventLog.Clear();
}
}
[HarmonyPatch(typeof(PlayerChatManager), "EnterChatMode")]
[HarmonyPatch(typeof(PlayerChatManager), "ExitChatMode")]
[HarmonyPostfix]
private static void PlayerChatManager__EnterExitChatMode__Postfix()
{
foreach (PUI_GameEventLog_ExtensionData value in extensionDataForEachInstance.Values)
{
value.scrollPosition = null;
}
}
[HarmonyPatch(typeof(PUI_GameEventLog), "Update")]
[HarmonyPostfix]
private static void PUI_GameEventLog__Update__Postfix(PUI_GameEventLog __instance)
{
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0087: Unknown result type (might be due to invalid IL or missing references)
PUI_GameEventLog_ExtensionData instanceData = GetInstanceData(__instance);
int num = Math.Min(__instance.m_limitNRLines, PUI_GameEventLog.s_logItemsMax);
if (PlayerChatManager.TextChatInputEnabled && PlayerChatManager.InChatMode && Input.mouseScrollDelta.y != 0f)
{
int? scrollPosition = instanceData.scrollPosition;
if (!scrollPosition.HasValue)
{
instanceData.scrollPosition = instanceData.rawEventLog.Count - num;
}
instanceData.scrollPosition -= (int)Input.mouseScrollDelta.y;
if (instanceData.scrollPosition < 0)
{
instanceData.scrollPosition = 0;
}
if (instanceData.scrollPosition >= instanceData.rawEventLog.Count - num)
{
instanceData.scrollPosition = null;
}
}
UpdateMLogItems(__instance);
}
private static void UpdateMLogItems(PUI_GameEventLog __instance)
{
//IL_012c: Unknown result type (might be due to invalid IL or missing references)
//IL_0131: Unknown result type (might be due to invalid IL or missing references)
//IL_015b: Unknown result type (might be due to invalid IL or missing references)
PUI_GameEventLog_ExtensionData instanceData = GetInstanceData(__instance);
int num = Math.Min(__instance.m_limitNRLines, PUI_GameEventLog.s_logItemsMax);
int sequenceHashCode = instanceData.rawEventLog.GetSequenceHashCode();
if (instanceData.scrollPosition == instanceData.previousScrollPosition && sequenceHashCode == instanceData.previousRawEventLogHash)
{
return;
}
instanceData.previousScrollPosition = instanceData.scrollPosition;
instanceData.previousRawEventLogHash = sequenceHashCode;
Enumerator<PUI_GameEventLog_Item> enumerator = __instance.m_logItems.GetEnumerator();
while (enumerator.MoveNext())
{
PUI_GameEventLog_Item current = enumerator.Current;
Object.Destroy((Object)(object)((Component)current).gameObject);
}
__instance.m_logItems.Clear();
int num2 = instanceData.scrollPosition ?? Mathf.Max(instanceData.rawEventLog.Count - num, 0);
int count = Mathf.Min(num, instanceData.rawEventLog.Count - num2);
foreach (var item3 in instanceData.rawEventLog.GetRange(num2, count))
{
string item = item3.Item1;
eGameEventChatLogType item2 = item3.Item2;
PUI_GameEventLog_Item val = GOUtil.SpawnChildAndGetComp<PUI_GameEventLog_Item>(__instance.m_logItemPrefab, __instance.m_itemAlign);
((RectTransformComp)val).Setup();
val.SetText(item);
val.SetType(item2);
__instance.m_logItems.Add(val);
}
__instance.ShowAndUpdateItemPositions();
__instance.ResetHideTimer();
}
[HarmonyPatch(typeof(CM_PageMap), "UpdateZoomAndPan")]
[HarmonyPrefix]
private static void CM_PageMap__UpdateZoomAndPan__Prefix(CM_PageMap __instance, ref bool __runOriginal)
{
if (PlayerChatManager.InChatMode && ((CM_PageBase)__instance).ScrollInput != 0f)
{
__runOriginal = false;
}
}
private static string FixMessagesFromBots(string message, eGameEventChatLogType type)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
if ((int)type == 0 && message.StartsWith("<color=orange>[Bot]</color><color=#"))
{
Dictionary<string, string> dictionary = new Dictionary<string, string>
{
{ "<color=orange>[Bot]</color><color=#C21F4E>> > Woods</color>: ", "<color=#C21F4E>> > <color=orange>[Bot]</color>Woods</color>: " },
{ "<color=orange>[Bot]</color><color=#18935E>> > Dauda</color>: ", "<color=#18935E>> > <color=orange>[Bot]</color>Dauda</color>: " },
{ "<color=orange>[Bot]</color><color=#20558C>> > Hackett</color>: ", "<color=#20558C>> > <color=orange>[Bot]</color>Hackett</color>: " },
{ "<color=orange>[Bot]</color><color=#7A1A8E>> > Bishop</color>: ", "<color=#7A1A8E>> > <color=orange>[Bot]</color>Bishop</color>: " }
};
foreach (KeyValuePair<string, string> item in dictionary)
{
if (message.StartsWith(item.Key))
{
return item.Value + message.AsSpan(item.Value.Length);
}
}
}
return message;
}
}
internal class PUI_GameEventLog_ExtensionData
{
public int instanceID;
public List<(string, eGameEventChatLogType)> rawEventLog = new List<(string, eGameEventChatLogType)>();
public int previousRawEventLogHash = 0;
public int? scrollPosition = null;
public int? previousScrollPosition = null;
public PUI_GameEventLog_ExtensionData(int instanceID)
{
this.instanceID = instanceID;
}
}
internal static class Extensions
{
public static int GetSequenceHashCode<T>(this List<T> sequence)
{
return sequence.Aggregate(487, (int current, T item) => current * 31 + (item?.GetHashCode() ?? 0));
}
}
internal static class TypingIndicator
{
private static readonly Dictionary<ulong, SNet_Player> playersWithBetterTextChat = new Dictionary<ulong, SNet_Player>();
private static readonly Dictionary<ulong, TypingPlayerData> typingPlayers = new Dictionary<ulong, TypingPlayerData>();
private static readonly Dictionary<ulong, float> lastMessageFromPlayer = new Dictionary<ulong, float>();
internal static void Setup()
{
SetupHello();
SetupPlayerIsTyping();
}
[HarmonyPatch(typeof(SNet_GlobalManager), "OnPlayerEvent")]
[HarmonyPostfix]
private static void SNet_GlobalManager__OnPlayerEvent__Postfix(SNet_Player player, SNet_PlayerEvent playerEvent)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0003: Invalid comparison between Unknown and I4
//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
//IL_00aa: Invalid comparison between Unknown and I4
if ((int)playerEvent == 2)
{
if (player.IsLocal)
{
Enumerator<SNet_Player> enumerator = SNet.LobbyPlayers.GetEnumerator();
while (enumerator.MoveNext())
{
SNet_Player current = enumerator.Current;
if (!current.IsLocal)
{
Utils.LogInfo("Sending Hello to " + ((Object)current).name);
NetworkAPI.InvokeEvent<EmptyStruct>("BetterTextChat-Hello", default(EmptyStruct), current, (SNet_ChannelType)0);
}
}
}
else
{
Utils.LogInfo("Sending Hello to " + ((Object)player).name);
NetworkAPI.InvokeEvent<EmptyStruct>("BetterTextChat-Hello", default(EmptyStruct), player, (SNet_ChannelType)0);
}
}
if ((int)playerEvent == 0 && playersWithBetterTextChat.ContainsKey(player.Lookup))
{
playersWithBetterTextChat.Remove(player.Lookup);
}
}
private static void SetupHello()
{
NetworkAPI.RegisterEvent<EmptyStruct>("BetterTextChat-Hello", (Action<ulong, EmptyStruct>)OnSNetPlayerHello);
}
private static void OnSNetPlayerHello(ulong steamID, EmptyStruct emptyStruct)
{
SNet_Player value = default(SNet_Player);
if (SNet.Core.TryGetPlayer(steamID, ref value, false))
{
playersWithBetterTextChat[steamID] = value;
return;
}
Utils.LogError($"OnSNetPlayerHello > Could not find SNet_Player for {steamID}");
}
internal static void OnLocalPlayerTyping()
{
if (ConfigManager.sendTypingIndicator.Value)
{
NetworkAPI.InvokeEvent<EmptyStruct>("BetterTextChat-PlayerIsTyping", default(EmptyStruct), playersWithBetterTextChat.Values.ToList(), (SNet_ChannelType)4);
}
}
private static ulong PHash(PlayerAgent playerAgent)
{
return ((Agent)playerAgent).m_replicator.OwningPlayer.Lookup;
}
private static void SetupPlayerIsTyping()
{
NetworkAPI.RegisterEvent<EmptyStruct>("BetterTextChat-PlayerIsTyping", (Action<ulong, EmptyStruct>)OnSNetPlayerTyping);
}
private static void OnSNetPlayerTyping(ulong steamID, EmptyStruct emptyStruct)
{
if (!ConfigManager.showTypingIndicator.Value || (lastMessageFromPlayer.ContainsKey(steamID) && Time.time < lastMessageFromPlayer[steamID] + 1f))
{
return;
}
SNet_Player sNetPlayer = default(SNet_Player);
if (typingPlayers.ContainsKey(steamID))
{
typingPlayers[steamID].lastSeenTypingAt = Time.time;
}
else if (SNet.Core.TryGetPlayer(steamID, ref sNetPlayer, false))
{
PlayerAgent playerAgentFromSNetPlayer = GetPlayerAgentFromSNetPlayer(sNetPlayer);
if (playerAgentFromSNetPlayer != null)
{
typingPlayers[steamID] = new TypingPlayerData(playerAgentFromSNetPlayer, Time.time);
}
}
}
[HarmonyPatch(typeof(PlayerChatManager), "DoSendChatMessage")]
[HarmonyPostfix]
private static void PlayerChatManager__DoSendChatMessage__Postfix(pChatMessage data)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
lastMessageFromPlayer[data.fromPlayer.lookup] = Time.time;
if (typingPlayers.ContainsKey(data.fromPlayer.lookup))
{
typingPlayers.Remove(data.fromPlayer.lookup);
}
}
[HarmonyPatch(typeof(PUI_GameEventLog), "UpdateHelpText")]
[HarmonyPrefix]
private static void PUI_GameEventLog__UpdateHelpText__Prefix(ref bool __runOriginal)
{
__runOriginal = false;
}
[HarmonyPatch(typeof(PUI_GameEventLog), "Update")]
[HarmonyPostfix]
private static void PUI_GameEventLog__Update__Postfix(PUI_GameEventLog __instance)
{
//IL_0092: Unknown result type (might be due to invalid IL or missing references)
//IL_0098: Invalid comparison between Unknown and I4
__instance.m_checkPushToTalk = CellSettingsManager.SettingsData.VoiceChat.Mode.Value == 1;
foreach (TypingPlayerData item in typingPlayers.Values.ToList())
{
if (Time.time > item.lastSeenTypingAt + 2f)
{
typingPlayers.Remove(PHash(item.playerAgent));
}
}
List<string> list = new List<string>();
bool flag = (int)LocalizationAPI.CurrentLanguage == 1;
if (PlayerChatManager.Current.m_dissonanceVoiceBroadcast.IsTransmitting)
{
list.Add("<color=red>" + Text.Get(966u) + "</color>");
}
if (PlayerChatManager.Current.m_speakingPlayers.Count > 0)
{
List<string> list2 = new List<string>();
Enumerator<VoicePlayerState> enumerator2 = PlayerChatManager.Current.m_speakingPlayers.GetEnumerator();
while (enumerator2.MoveNext())
{
VoicePlayerState current2 = enumerator2.Current;
SNet_Player sNetPlayerByVoiceState = PlayerChatManager.Current.GetSNetPlayerByVoiceState(current2);
PlayerAgent playerAgentFromSNetPlayer = GetPlayerAgentFromSNetPlayer(sNetPlayerByVoiceState);
if (playerAgentFromSNetPlayer != null)
{
list2.Add(PlayerNameExtentions.GetColoredName(playerAgentFromSNetPlayer, (string)null));
}
}
if (flag)
{
list.Add($"[{FormatStringList(list2)} {FormatIsArePlural(list2)} speaking]");
}
else
{
foreach (string item2 in list2)
{
list.Add(Text.Format(965u, (Object[])(object)new Object[1] { Object.op_Implicit(item2) }));
}
}
}
if (typingPlayers.Count > 0)
{
List<string> list3 = new List<string>();
foreach (TypingPlayerData item3 in typingPlayers.Values.OrderBy((TypingPlayerData playerData) => playerData.playerAgent.PlayerSlotIndex))
{
list3.Add(PlayerNameExtentions.GetColoredName(item3.playerAgent, (string)null));
}
list.Add($"[{FormatStringList(list3)} {FormatIsArePlural(list3)} typing...]");
}
if (list.Count > 0)
{
((TMP_Text)__instance.m_txtHelp).text = string.Join(" ", list);
}
else if (__instance.m_checkPushToTalk)
{
((TMP_Text)__instance.m_txtHelp).text = Text.Format(1392u, (Object[])(object)new Object[4]
{
Object.op_Implicit("<color=orange>[" + InputMapper.GetBindingName((InputAction)56) + "]</color>"),
Object.op_Implicit("<color=orange>[" + InputMapper.GetBindingName((InputAction)55) + "]</color>"),
Object.op_Implicit("<color=orange>[" + InputMapper.GetBindingName((InputAction)33) + "]</color>"),
Object.op_Implicit("<color=orange>[" + InputMapper.GetBindingName((InputAction)63) + "]</color>")
});
}
else
{
((TMP_Text)__instance.m_txtHelp).text = Text.Format(1393u, (Object[])(object)new Object[3]
{
Object.op_Implicit("<color=orange>[" + InputMapper.GetBindingName((InputAction)56) + "]</color>"),
Object.op_Implicit("<color=orange>[" + InputMapper.GetBindingName((InputAction)33) + "]</color>"),
Object.op_Implicit("<color=orange>[" + InputMapper.GetBindingName((InputAction)63) + "]</color>")
});
}
}
private static PlayerAgent? GetPlayerAgentFromSNetPlayer(SNet_Player sNetPlayer)
{
Enumerator<PlayerAgent> enumerator = PlayerManager.PlayerAgentsInLevel.GetEnumerator();
while (enumerator.MoveNext())
{
PlayerAgent current = enumerator.Current;
if ((Object)(object)((Agent)current).m_replicator.OwningPlayer == (Object)(object)sNetPlayer)
{
return current;
}
}
Utils.LogError("GetPlayerAgentFromSNetPlayer > Could not find PlayerAgent for " + ((Object)sNetPlayer).name);
return null;
}
private static string FormatStringList(List<string> strings)
{
switch (strings.Count)
{
case 0:
return string.Empty;
case 1:
return strings[0];
case 2:
return strings[0] + " and " + strings[1];
default:
return string.Join(", ", strings.GetRange(0, strings.Count - 1)) + ", and " + strings[strings.Count - 1];
}
}
private static string FormatIsArePlural(List<string> strings)
{
return (strings.Count == 1) ? "is" : "are";
}
}
[StructLayout(LayoutKind.Sequential, Size = 1)]
public struct EmptyStruct
{
}
internal class TypingPlayerData
{
public PlayerAgent playerAgent;
public float lastSeenTypingAt;
public TypingPlayerData(PlayerAgent playerAgent, float lastSeenTypingAt)
{
this.playerAgent = playerAgent;
this.lastSeenTypingAt = lastSeenTypingAt;
}
}
internal class PttSoundPlayer : MonoBehaviour
{
private bool previousTransmittingStatus = false;
private void Update()
{
bool flag = CellSettingsManager.SettingsData.VoiceChat.Mode.Value == 1;
bool value = CellSettingsManager.SettingsData.VoiceChat.PushToTalk_EnableSound.Value;
bool isTransmitting = PlayerChatManager.Current.m_dissonanceVoiceBroadcast.IsTransmitting;
if (flag && value)
{
if (isTransmitting && !previousTransmittingStatus)
{
CM_PageBase.PostSound(EVENTS.PUSH_TO_TALK_ON, "");
}
if (previousTransmittingStatus && !isTransmitting)
{
CM_PageBase.PostSound(EVENTS.PUSH_TO_TALK_OFF, "");
}
}
previousTransmittingStatus = isTransmitting;
}
}
internal static class Utils
{
private static readonly ManualLogSource logger = Logger.CreateLogSource("Andocas.BetterTextChat");
public static void LogInfo(object? o)
{
logger.LogInfo((object)GetMessage(o));
}
public static void LogError(object? o)
{
logger.LogError((object)GetMessage(o));
}
private static string GetMessage(object? o)
{
if (o == null)
{
return "No string representation for <null>";
}
return o.ToString() ?? $"No string representation for <{o.GetType()}>";
}
}
}