using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HBS;
using HBS.DebugConsole;
using HBS.Net;
using HBS.Util;
using HarmonyLib;
using Necro;
using Necro.Signaling;
using Necro.UI;
using UnityEngine;
using UnityEngine.UI;
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyCopyright("Copyright © KoMiKoZa 2026")]
[assembly: ComVisible(false)]
[assembly: Guid("b9800a51-2b96-4772-b75c-02fb8a64988e")]
[assembly: AssemblyProduct("NecroChat")]
[assembly: AssemblyTitle("NecroChat")]
[assembly: AssemblyCompany("KoMiKoZa")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyDescription("Multiplayer chat mod for Necropolis")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace KoMiKoZa.Necropolis.ChatMod;
public enum ChatDisplayMode
{
Basic,
AbovePlayer,
BasicAndAbovePlayer,
Smart
}
public enum ChatFontStyle
{
Basic,
Necro
}
public enum ChatSoundStyle
{
None,
Sound1,
Sound2,
Sound3,
Sound4,
Sound5
}
[BepInPlugin("komikoza.necropolis.chat", "NecroChat", "1.0.1")]
public class ChatModPlugin : BaseUnityPlugin, ObjectDataReceiver
{
private const string GUID = "komikoza.necropolis.chat";
private const string NAME = "NecroChat";
private const string VERSION = "1.0.1";
private const int MIN_FONT_SIZE = 20;
private const int MAX_FONT_SIZE = 40;
private const int MAX_MESSAGE_LENGTH = 100;
private const float ABOVE_PLAYER_FADE_IN_TIME = 0.3f;
private const float CHATBOX_FADE_IN_TIME = 0.5f;
private const uint NETWORK_ROUTER_ID = 51367u;
private const byte MSG_CHAT = 1;
private const float MIN_WIDTH = 300f;
private const float MIN_HEIGHT = 200f;
private const float MAX_WIDTH = 800f;
private const float MAX_HEIGHT = 600f;
private const float INPUT_HEIGHT = 30f;
private const float PADDING = 10f;
private const float HEADER_HEIGHT = 55f;
private const float RESIZE_HANDLE_SIZE = 24f;
private const string DEFAULT_NAME_COLOR = "ffcc00";
private const string EVENT_COLOR_JOIN = "FFFF00";
private const string EVENT_COLOR_LEAVE = "FFA500";
private const string EVENT_COLOR_INCAP = "FF4444";
private const string EVENT_COLOR_REVIVED = "44FF44";
private const string EVENT_COLOR_RESPAWN = "FFA500";
private const string EVENT_COLOR_ONEHIT = "FF4444";
private const float EVENT_DEBOUNCE_TIME = 1f;
private const float CHAT_REOPEN_DELAY = 0.15f;
private const string DYE_COLOR_PROPERTY = "_SecondaryColor";
internal static ManualLogSource Log;
internal static ConfigEntry<bool> ModEnabled;
internal static ConfigEntry<bool> DebugMode;
internal static ConfigEntry<bool> EnableLogging;
internal static ConfigEntry<bool> HidePlayerNameOnChat;
internal static ConfigEntry<bool> UsePlayerDyeColors;
internal static ConfigEntry<bool> ColorAbovePlayerMessage;
internal static ConfigEntry<bool> AbovePlayerAnimations;
internal static ConfigEntry<bool> ChatBoxAnimations;
internal static ConfigEntry<bool> GameEventMessages;
internal static ConfigEntry<bool> ShowTimestamps;
internal static ConfigEntry<ChatSoundStyle> ChatSound;
internal static ConfigEntry<ChatFontStyle> FontStyle;
internal static ConfigEntry<ChatDisplayMode> DisplayMode;
internal static ConfigEntry<KeyCode> ToggleHistoryKey;
internal static ConfigEntry<KeyCode> OpenChatKey;
internal static ConfigEntry<int> FontSize;
internal static ConfigEntry<int> MaxMessages;
internal static ConfigEntry<int> MaxVisibleMessages;
internal static ConfigEntry<int> MessageDisplayTime;
internal static ConfigEntry<int> MessageFadeTime;
internal static ConfigEntry<int> AbovePlayerDisplayTime;
internal static ConfigEntry<int> AbovePlayerFadeTime;
internal static ConfigEntry<int> AbovePlayerFontSize;
internal static ConfigEntry<int> AbovePlayerWidth;
internal static ConfigEntry<int> SmartModeDistance;
internal static ConfigEntry<int> ChatBoxOpacity;
private static string chatLogPath;
private static string currentLogFile;
private static ChatModPlugin instance;
internal static bool chatOpen = false;
private static bool showFullHistory = false;
private static string inputText = "";
private static bool clearInputNextFrame = false;
private static List<ChatMessage> messages = new List<ChatMessage>();
private static Vector2 scrollPosition = Vector2.zero;
private static GUIStyle labelStyle;
private static GUIStyle inputStyle;
private static GUIStyle boxStyle;
private static GUIStyle headerStyle;
private static GUIStyle resizeHandleStyle;
private static GUIStyle abovePlayerStyle;
private static bool stylesInitialized = false;
private static bool hasShownDebugMessages = false;
private static Font fontNecro = null;
private static bool fontsLoaded = false;
private static float lastFontCheckTime = 0f;
private static Texture2D backgroundTex;
private static Texture2D headerTex;
private static Texture2D resizeTex;
private static float chatWidth = 500f;
private static float chatHeight = 375f;
private static Vector2 windowPosition = new Vector2(-1f, -1f);
private static bool isDragging = false;
private static bool isResizing = false;
private static Vector2 dragOffset = Vector2.zero;
private static Vector2 resizeStartPos = Vector2.zero;
private static Vector2 resizeStartSize = Vector2.zero;
private static MouseState previousMouseState = (MouseState)1;
private static FieldInfo trackedObjectsField = null;
private static int selectedMessageIndex = -1;
private static GUIStyle selectedLabelStyle;
private static Texture2D selectionTex;
private static HashSet<Actor> subscribedActors = new HashSet<Actor>();
private static Dictionary<Actor, bool> actorHadAutoResurrect = new Dictionary<Actor, bool>();
private static HashSet<Actor> actorDidSpawnReset = new HashSet<Actor>();
private static Dictionary<Actor, float> lastReviveTime = new Dictionary<Actor, float>();
private static Dictionary<string, float> lastJoinLeaveTime = new Dictionary<string, float>();
internal static Actor lastReviver = null;
private static int lastKnownPlayerCount = 0;
private static bool hasAutoOpenedChat = false;
private static bool gameEventCallbacksRegistered = false;
private static HashSet<Actor> hiddenHUDIndicators = new HashSet<Actor>();
private static Dictionary<string, float> senderCornerTransitionTime = new Dictionary<string, float>();
private static HashSet<string> sendersCurrentlyInCorner = new HashSet<string>();
private static float lastChatCloseTime = 0f;
private static readonly uint[] CHAT_SOUND_IDS = new uint[6] { 0u, 3970834679u, 2594522141u, 1594216792u, 3857650026u, 4279107860u };
private static int lastOpacitySetting = -1;
private void Awake()
{
//IL_023b: Unknown result type (might be due to invalid IL or missing references)
//IL_0245: Expected O, but got Unknown
//IL_0270: Unknown result type (might be due to invalid IL or missing references)
//IL_027a: Expected O, but got Unknown
//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
//IL_02ad: Expected O, but got Unknown
//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
//IL_02e0: Expected O, but got Unknown
//IL_0308: Unknown result type (might be due to invalid IL or missing references)
//IL_0312: Expected O, but got Unknown
//IL_033b: Unknown result type (might be due to invalid IL or missing references)
//IL_0345: Expected O, but got Unknown
//IL_036d: Unknown result type (might be due to invalid IL or missing references)
//IL_0377: Expected O, but got Unknown
//IL_03a2: Unknown result type (might be due to invalid IL or missing references)
//IL_03ac: Expected O, but got Unknown
//IL_03e0: Unknown result type (might be due to invalid IL or missing references)
//IL_03ea: Expected O, but got Unknown
//IL_0415: Unknown result type (might be due to invalid IL or missing references)
//IL_041f: Expected O, but got Unknown
//IL_0449: Unknown result type (might be due to invalid IL or missing references)
//IL_0453: Expected O, but got Unknown
//IL_05d0: Unknown result type (might be due to invalid IL or missing references)
//IL_05d7: Expected O, but got Unknown
instance = this;
Log = ((BaseUnityPlugin)this).Logger;
ModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ModEnabled", true, "Enable or disable this mod");
DebugMode = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DebugMode", false, "Enable debug logging and offline chat testing");
EnableLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableLogging", false, "Save chat messages to a log file in /chatlogs folder");
HidePlayerNameOnChat = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "HidePlayerNameOnChat", true, "Hide player name display when showing chat above them");
UsePlayerDyeColors = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "UsePlayerDyeColors", true, "Color player names using their character dye color");
ColorAbovePlayerMessage = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ColorAbovePlayerMessage", true, "Color entire above-player message with player's dye color");
AbovePlayerAnimations = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AbovePlayerAnimations", true, "Enable fade-in and slide-up animations for above-player messages");
ChatBoxAnimations = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ChatBoxAnimations", true, "Enable fade-in animation for chatbox messages");
GameEventMessages = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "GameEventMessages", true, "Show game event messages (player join/leave, incap, revive, etc.) in chat");
ShowTimestamps = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowTimestamps", false, "Show timestamps (HH:mm) on messages in chat box");
ChatSound = ((BaseUnityPlugin)this).Config.Bind<ChatSoundStyle>("General", "ChatSound", ChatSoundStyle.Sound2, "Sound style for chat messages (None to disable)");
FontStyle = ((BaseUnityPlugin)this).Config.Bind<ChatFontStyle>("General", "FontStyle", ChatFontStyle.Necro, "Font style to use for chat text");
DisplayMode = ((BaseUnityPlugin)this).Config.Bind<ChatDisplayMode>("General", "DisplayMode", ChatDisplayMode.Smart, "Chat display mode");
try
{
ChatDisplayMode value = DisplayMode.Value;
}
catch
{
DisplayMode.Value = ChatDisplayMode.Smart;
}
ToggleHistoryKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "ToggleHistoryKey", (KeyCode)9, "Key to hold to show chat history");
OpenChatKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "OpenChatKey", (KeyCode)13, "Key to open chat (send is always Enter)");
FontSize = ((BaseUnityPlugin)this).Config.Bind<int>("General", "FontSize", 25, new ConfigDescription("Chat font size", (AcceptableValueBase)(object)new AcceptableValueRange<int>(20, 40), new object[0]));
MaxMessages = ((BaseUnityPlugin)this).Config.Bind<int>("General", "MaxMessages", 50, new ConfigDescription("Maximum messages to keep in history", (AcceptableValueBase)(object)new AcceptableValueRange<int>(50, 100), new object[0]));
MaxVisibleMessages = ((BaseUnityPlugin)this).Config.Bind<int>("General", "MaxVisibleMessages", 5, new ConfigDescription("Max messages shown on screen", (AcceptableValueBase)(object)new AcceptableValueRange<int>(3, 10), new object[0]));
MessageDisplayTime = ((BaseUnityPlugin)this).Config.Bind<int>("General", "MessageDisplayTime", 5, new ConfigDescription("Seconds before messages start fading", (AcceptableValueBase)(object)new AcceptableValueRange<int>(5, 12), new object[0]));
MessageFadeTime = ((BaseUnityPlugin)this).Config.Bind<int>("General", "MessageFadeTime", 2, new ConfigDescription("Fade animation duration in seconds", (AcceptableValueBase)(object)new AcceptableValueRange<int>(2, 8), new object[0]));
AbovePlayerDisplayTime = ((BaseUnityPlugin)this).Config.Bind<int>("General", "AbovePlayerDisplayTime", 5, new ConfigDescription("Seconds before above-player messages start fading", (AcceptableValueBase)(object)new AcceptableValueRange<int>(5, 12), new object[0]));
AbovePlayerFadeTime = ((BaseUnityPlugin)this).Config.Bind<int>("General", "AbovePlayerFadeTime", 2, new ConfigDescription("Above-player fade duration in seconds", (AcceptableValueBase)(object)new AcceptableValueRange<int>(2, 8), new object[0]));
AbovePlayerFontSize = ((BaseUnityPlugin)this).Config.Bind<int>("General", "AbovePlayerFontSize", 40, new ConfigDescription("Above-player font size", (AcceptableValueBase)(object)new AcceptableValueRange<int>(20, 50), new object[0]));
AbovePlayerWidth = ((BaseUnityPlugin)this).Config.Bind<int>("General", "AbovePlayerWidth", 400, new ConfigDescription("Above-player text max width in pixels", (AcceptableValueBase)(object)new AcceptableValueRange<int>(300, 500), new object[0]));
SmartModeDistance = ((BaseUnityPlugin)this).Config.Bind<int>("General", "SmartModeDistance", 30, new ConfigDescription("Smart mode distance threshold", (AcceptableValueBase)(object)new AcceptableValueRange<int>(20, 100), new object[0]));
ChatBoxOpacity = ((BaseUnityPlugin)this).Config.Bind<int>("General", "ChatBoxOpacity", 70, new ConfigDescription("Chat box background opacity (0-100%)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), new object[0]));
chatLogPath = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "chatlogs");
if (EnableLogging.Value)
{
try
{
if (!Directory.Exists(chatLogPath))
{
Directory.CreateDirectory(chatLogPath);
}
string arg = DateTime.Now.ToString("yyyy-MM-dd");
currentLogFile = Path.Combine(chatLogPath, $"chat_{arg}.txt");
if (!File.Exists(currentLogFile))
{
string contents = "================================================" + Environment.NewLine + string.Format("[NecroChat] v{0} - Chat Log", "1.0.1") + Environment.NewLine + string.Format(" - Generated: {0}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")) + Environment.NewLine + "================================================" + Environment.NewLine + Environment.NewLine;
File.WriteAllText(currentLogFile, contents);
}
}
catch (Exception ex)
{
Log.LogError((object)("Failed to create chat log folder: " + ex.Message));
}
}
if (!ModEnabled.Value)
{
Log.LogInfo((object)"Disabled");
return;
}
try
{
Harmony val = new Harmony("komikoza.necropolis.chat");
val.PatchAll();
ObjectDataRouter.Singleton.Register(51367u, (ObjectDataReceiver)(object)this);
RegisterGameEventCallbacks();
Log.LogInfo((object)"================================================");
Log.LogInfo((object)string.Format("[{0}] v{1} loaded!", "NecroChat", "1.0.1"));
Log.LogInfo((object)" - Advanced multiplayer text chat for Necropolis");
Log.LogInfo((object)"================================================");
}
catch (Exception ex)
{
Log.LogError((object)string.Format("[{0}] Failed to load: {1}", "NecroChat", ex));
}
}
private bool IsChatAllowed()
{
if (DebugMode.Value)
{
return true;
}
if (!LazySingletonBehavior<NetworkManager>.HasInstance)
{
return false;
}
return LazySingletonBehavior<NetworkManager>.Instance.IsMultiplayer;
}
private int GetCurrentPlayerCount()
{
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_0083: Invalid comparison between Unknown and I4
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
//IL_008e: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: Invalid comparison between Unknown and I4
try
{
if (!LazySingletonBehavior<NetworkManager>.HasInstance)
{
return 0;
}
NetworkManager val = LazySingletonBehavior<NetworkManager>.Instance;
if (!val.IsMultiplayer)
{
return 0;
}
int num = 1;
if (val.VirtualCouch != null)
{
foreach (VirtualCouchSeat item in val.VirtualCouch)
{
if (item != null && item.platformHandle != null)
{
num++;
}
else if (item != null && ((int)item.setupState == 2 || (int)item.setupState == 0 || (int)item.setupState == 1))
{
num++;
}
}
}
return num;
}
catch
{
return 0;
}
}
private bool IsInLobbyWithPlayers()
{
return GetCurrentPlayerCount() >= 2;
}
private bool IsInLobby()
{
if (!ThirdPersonCameraControl.HasInstance)
{
return true;
}
if ((Object)(object)ThirdPersonCameraControl.Instance.CharacterActor == (Object)null)
{
return true;
}
if (!ThirdPersonCameraControl.Instance.CharacterActor.IsAlive)
{
return true;
}
return false;
}
internal static bool IsInMultiplayerLobby()
{
if (!LazySingletonBehavior<NetworkManager>.HasInstance)
{
return false;
}
if (!LazySingletonBehavior<NetworkManager>.Instance.IsMultiplayer)
{
return false;
}
if (!ThirdPersonCameraControl.HasInstance)
{
return true;
}
if ((Object)(object)ThirdPersonCameraControl.Instance.CharacterActor == (Object)null)
{
return true;
}
if (!ThirdPersonCameraControl.Instance.CharacterActor.IsAlive)
{
return true;
}
return false;
}
private bool IsMenuBlockingChat()
{
if (Menu_MainMenu.IsShowing)
{
return true;
}
if (ItemMenuController.IsShowing)
{
return true;
}
if (ModalDialogController.IsShowing)
{
return true;
}
return false;
}
private void RestoreExpiredHUDIndicators()
{
if (hiddenHUDIndicators.Count == 0)
{
return;
}
if (!HidePlayerNameOnChat.Value)
{
RestoreAllHUDIndicators();
return;
}
float num = AbovePlayerDisplayTime.Value;
float num2 = AbovePlayerFadeTime.Value;
float num3 = num + num2;
HashSet<string> hashSet = new HashSet<string>();
foreach (ChatMessage message in messages)
{
float num4 = Time.time - message.Timestamp;
if (num4 <= num3)
{
hashSet.Add(message.Sender);
}
}
List<Actor> list = new List<Actor>();
foreach (Actor hiddenHUDIndicator in hiddenHUDIndicators)
{
if ((Object)(object)hiddenHUDIndicator == (Object)null)
{
list.Add(hiddenHUDIndicator);
continue;
}
string actorDisplayName = GetActorDisplayName(hiddenHUDIndicator);
if (string.IsNullOrEmpty(actorDisplayName) || !hashSet.Contains(actorDisplayName))
{
HUDIndicator hUDIndicatorForActor = GetHUDIndicatorForActor(hiddenHUDIndicator);
if ((Object)(object)hUDIndicatorForActor != (Object)null)
{
((Component)hUDIndicatorForActor).gameObject.SetActive(true);
}
list.Add(hiddenHUDIndicator);
}
}
foreach (Actor item in list)
{
hiddenHUDIndicators.Remove(item);
}
}
private void RestoreAllHUDIndicators()
{
foreach (Actor hiddenHUDIndicator in hiddenHUDIndicators)
{
if (!((Object)(object)hiddenHUDIndicator == (Object)null))
{
HUDIndicator hUDIndicatorForActor = GetHUDIndicatorForActor(hiddenHUDIndicator);
if ((Object)(object)hUDIndicatorForActor != (Object)null)
{
((Component)hUDIndicatorForActor).gameObject.SetActive(true);
}
}
}
hiddenHUDIndicators.Clear();
}
private void Update()
{
//IL_015a: Unknown result type (might be due to invalid IL or missing references)
if (!ModEnabled.Value || !IsChatAllowed())
{
return;
}
if (!gameEventCallbacksRegistered)
{
RegisterGameEventCallbacks();
}
if (!hasShownDebugMessages && !IsInLobby())
{
hasShownDebugMessages = true;
if (DebugMode.Value)
{
messages.Add(new ChatMessage("[NecroChat] Debugging is enabled", Time.time, "FFFF00"));
}
if (EnableLogging.Value)
{
messages.Add(new ChatMessage("[NecroChat] Logging is enabled", Time.time, "FFFF00"));
}
}
int currentPlayerCount = GetCurrentPlayerCount();
if (IsInLobby() && currentPlayerCount >= 2 && lastKnownPlayerCount < 2 && !hasAutoOpenedChat && !chatOpen && !IsGameUIBlocking(allowLobby: true))
{
OpenChat();
hasAutoOpenedChat = true;
if (DebugMode.Value)
{
Log.LogInfo((object)"LOBBY CHAT auto-opened on player join");
}
}
if (currentPlayerCount < 2)
{
hasAutoOpenedChat = false;
}
lastKnownPlayerCount = currentPlayerCount;
if (!chatOpen && !IsGameUIBlocking(allowLobby: true))
{
bool key = Input.GetKey(ToggleHistoryKey.Value);
if (key && !showFullHistory)
{
showFullHistory = true;
if (DebugMode.Value)
{
Log.LogInfo((object)"History SHOWN (Tab held)");
}
}
else if (!key && showFullHistory)
{
showFullHistory = false;
if (DebugMode.Value)
{
Log.LogInfo((object)"History HIDDEN (Tab released)");
}
}
}
if (showFullHistory && IsMenuBlockingChat())
{
if (DebugMode.Value)
{
Log.LogInfo((object)"History HIDDEN (menu opened)");
}
showFullHistory = false;
}
RestoreExpiredHUDIndicators();
UpdateActorSubscriptions();
}
private bool IsGameUIBlocking(bool allowLobby = false)
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Invalid comparison between Unknown and I4
if (LazySingletonBehavior<DebugConsole>.HasInstance && ((Behaviour)LazySingletonBehavior<DebugConsole>.Instance).enabled && (int)LazySingletonBehavior<DebugConsole>.Instance.mode != -1)
{
return true;
}
if (allowLobby && IsInMultiplayerLobby())
{
if (ModalDialogController.IsShowing)
{
return true;
}
return false;
}
if (ItemMenuController.IsShowing)
{
return true;
}
if (Menu_MainMenu.IsShowing)
{
return true;
}
if (ModalDialogController.IsShowing)
{
return true;
}
if (!ThirdPersonCameraControl.HasInstance)
{
return true;
}
if ((Object)(object)ThirdPersonCameraControl.Instance.CharacterActor == (Object)null)
{
return true;
}
if (!ThirdPersonCameraControl.Instance.CharacterActor.IsAlive)
{
return true;
}
return false;
}
private void OpenChat()
{
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
if (chatOpen)
{
return;
}
chatOpen = true;
if (ThirdPersonCameraControl.HasInstance)
{
if (LazySingletonBehavior<EventSystemObjectHandler>.HasInstance)
{
LazySingletonBehavior<EventSystemObjectHandler>.Instance.SetInputDisabled(true);
}
if (SceneSingletonBehavior<NecroKeyboardManager>.HasInstance)
{
previousMouseState = SceneSingletonBehavior<NecroKeyboardManager>.Instance.CurMouseState;
SceneSingletonBehavior<NecroKeyboardManager>.Instance.SetProfileState((MouseState)0);
}
ThirdPersonCameraControl.Instance.StopMainPlayerMovement();
}
Cursor.visible = true;
Cursor.lockState = (CursorLockMode)0;
if (DebugMode.Value)
{
Log.LogInfo((object)"Chat OPENED");
}
}
private void CloseChat()
{
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
if (!chatOpen)
{
return;
}
chatOpen = false;
selectedMessageIndex = -1;
if (ThirdPersonCameraControl.HasInstance)
{
if (LazySingletonBehavior<EventSystemObjectHandler>.HasInstance)
{
LazySingletonBehavior<EventSystemObjectHandler>.Instance.SetInputDisabled(false);
}
if (SceneSingletonBehavior<NecroKeyboardManager>.HasInstance)
{
SceneSingletonBehavior<NecroKeyboardManager>.Instance.SetProfileState(previousMouseState);
}
}
lastChatCloseTime = Time.time;
if (DebugMode.Value)
{
Log.LogInfo((object)"Chat CLOSED");
}
}
private void SendChatMessage(string text)
{
string text2 = text.Replace("\n", "").Replace("\r", "").Trim();
if (text2.Length > 100)
{
text2 = text2.Substring(0, 100);
}
if (DebugMode.Value)
{
Log.LogInfo((object)("SendMessage: '" + text2 + "' (length=" + text2.Length + ")"));
}
if (!string.IsNullOrEmpty(text2))
{
string localPlayerName = GetLocalPlayerName();
bool isAction = false;
string text3 = text2;
if (text2.StartsWith("/me ", StringComparison.OrdinalIgnoreCase))
{
isAction = true;
text3 = text2.Substring(4);
}
else if (text2.Equals("/me", StringComparison.OrdinalIgnoreCase))
{
return;
}
AddMessage(localPlayerName, text3, isAction, playSound: true);
BroadcastChatMessage(localPlayerName, text3, isAction);
}
}
private string GetLocalPlayerName()
{
try
{
if (LazySingletonBehavior<NetworkManager>.HasInstance && LazySingletonBehavior<NetworkManager>.Instance.LocalVirtualCouchSeat != null && LazySingletonBehavior<NetworkManager>.Instance.LocalVirtualCouchSeat.platformHandle != null)
{
string name = LazySingletonBehavior<NetworkManager>.Instance.LocalVirtualCouchSeat.platformHandle.Name;
if (!string.IsNullOrEmpty(name))
{
return name;
}
}
}
catch
{
}
return "Player";
}
private void AddMessage(string sender, string text, bool isAction = false, bool playSound = false)
{
messages.Add(new ChatMessage(sender, text, Time.time, isAction));
while (messages.Count > MaxMessages.Value)
{
messages.RemoveAt(0);
}
scrollPosition.y = float.MaxValue;
if (playSound && ChatSound.Value != 0)
{
PlayChatSound();
}
EnsureChatLogInitialized();
if (!EnableLogging.Value || string.IsNullOrEmpty(currentLogFile))
{
return;
}
try
{
string arg = DateTime.Now.ToString("HH:mm:ss");
File.AppendAllText(contents: ((!isAction) ? $"[{arg}] {sender}: {text}" : $"[{arg}] * {sender} {text}") + Environment.NewLine, path: currentLogFile);
}
catch (Exception ex)
{
if (DebugMode.Value)
{
Log.LogError((object)("Failed to write chat log: " + ex.Message));
}
}
}
private void PlayChatSound()
{
try
{
int value = (int)ChatSound.Value;
if (value > 0 && value < CHAT_SOUND_IDS.Length)
{
AkSoundEngine.PostEvent(CHAT_SOUND_IDS[value], ((Component)this).gameObject);
}
}
catch
{
}
}
private void AddSystemMessage(string text, string color)
{
if (!GameEventMessages.Value)
{
return;
}
messages.Add(new ChatMessage(text, Time.time, color));
while (messages.Count > MaxMessages.Value)
{
messages.RemoveAt(0);
}
scrollPosition.y = float.MaxValue;
EnsureChatLogInitialized();
if (EnableLogging.Value && !string.IsNullOrEmpty(currentLogFile))
{
try
{
string arg = DateTime.Now.ToString("HH:mm:ss");
string text2 = $"[{arg}] [SYSTEM] {text}";
File.AppendAllText(currentLogFile, text2 + Environment.NewLine);
}
catch
{
}
}
if (DebugMode.Value)
{
Log.LogInfo((object)("System: " + text));
}
}
private void RegisterGameEventCallbacks()
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Expected O, but got Unknown
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Expected O, but got Unknown
if (!gameEventCallbacksRegistered && LazySingletonBehavior<NetworkManager>.HasInstance)
{
NetworkManager val = LazySingletonBehavior<NetworkManager>.Instance;
val.RegisterConnectCallback(new NetworkManagerOnConnect(OnPlayerConnect));
val.RegisterDisconnectCallback(new NetworkManagerOnDisconnect(OnPlayerDisconnect));
gameEventCallbacksRegistered = true;
if (DebugMode.Value)
{
Log.LogInfo((object)"Registered game event callbacks");
}
}
}
private void UnregisterGameEventCallbacks()
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Expected O, but got Unknown
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Expected O, but got Unknown
if (LazySingletonBehavior<NetworkManager>.HasInstance)
{
NetworkManager val = LazySingletonBehavior<NetworkManager>.Instance;
val.UnregisterConnectCallback(new NetworkManagerOnConnect(OnPlayerConnect));
val.UnregisterDisconnectCallback(new NetworkManagerOnDisconnect(OnPlayerDisconnect));
}
}
private void OnPlayerConnect(VirtualCouchSeat seat)
{
if (seat == null || seat.platformHandle == null)
{
return;
}
string name = seat.platformHandle.Name;
if (!string.IsNullOrEmpty(name))
{
string key = "join_" + name;
float time = Time.time;
if (!lastJoinLeaveTime.TryGetValue(key, out var value) || !(time - value < 1f))
{
lastJoinLeaveTime[key] = time;
AddSystemMessage(name + " has joined the session", "FFFF00");
}
}
}
private void OnPlayerDisconnect(VirtualCouchSeat seat)
{
if (seat == null || seat.platformHandle == null)
{
return;
}
string name = seat.platformHandle.Name;
if (!string.IsNullOrEmpty(name))
{
string key = "leave_" + name;
float time = Time.time;
if (!lastJoinLeaveTime.TryGetValue(key, out var value) || !(time - value < 1f))
{
lastJoinLeaveTime[key] = time;
AddSystemMessage(name + " has left the session", "FFA500");
}
}
}
private void SubscribeToActorEvents(Actor actor)
{
if (!((Object)(object)actor == (Object)null) && !subscribedActors.Contains(actor))
{
actor.OnKilled += delegate
{
OnActorKilled(actor);
};
actor.OnResurrect += delegate
{
OnActorResurrected(actor);
};
subscribedActors.Add(actor);
if (DebugMode.Value)
{
Log.LogInfo((object)("Subscribed to actor events: " + GetActorDisplayName(actor)));
}
}
}
private void OnActorKilled(Actor actor)
{
if ((Object)(object)actor == (Object)null || !actor.IsPlayer)
{
return;
}
string actorDisplayName = GetActorDisplayName(actor);
if (!string.IsNullOrEmpty(actorDisplayName))
{
actorHadAutoResurrect[actor] = actor.WillAutoResurrect;
if (actor.WillAutoResurrect)
{
AddSystemMessage(actorDisplayName + " has cheated death!", "44FF44");
}
else
{
AddSystemMessage(actorDisplayName + " has fallen!", "FF4444");
}
}
}
private void OnActorResurrected(Actor actor)
{
if ((Object)(object)actor == (Object)null || !actor.IsPlayer)
{
return;
}
string actorDisplayName = GetActorDisplayName(actor);
if (string.IsNullOrEmpty(actorDisplayName))
{
return;
}
if (actorDidSpawnReset.Contains(actor))
{
actorDidSpawnReset.Remove(actor);
return;
}
bool value = false;
if (actorHadAutoResurrect.TryGetValue(actor, out value) && value)
{
actorHadAutoResurrect.Remove(actor);
return;
}
actorHadAutoResurrect.Remove(actor);
float time = Time.time;
if (lastReviveTime.TryGetValue(actor, out var value2) && time - value2 < 1f)
{
return;
}
lastReviveTime[actor] = time;
if ((Object)(object)lastReviver != (Object)null && (Object)(object)lastReviver != (Object)(object)actor)
{
string actorDisplayName2 = GetActorDisplayName(lastReviver);
if (!string.IsNullOrEmpty(actorDisplayName2))
{
AddSystemMessage(actorDisplayName + " was revived by " + actorDisplayName2 + "!", "44FF44");
lastReviver = null;
return;
}
}
lastReviver = null;
AddSystemMessage(actorDisplayName + " was revived!", "44FF44");
}
internal static void OnActorSpawnReset(Actor actor)
{
if (!((Object)(object)instance == (Object)null) && !((Object)(object)actor == (Object)null) && actor.IsPlayer)
{
string actorDisplayName = instance.GetActorDisplayName(actor);
if (!string.IsNullOrEmpty(actorDisplayName))
{
actorDidSpawnReset.Add(actor);
instance.AddSystemMessage(actorDisplayName + " has respawned (lost all gear)", "FFA500");
}
}
}
internal static void OnOneHitProtection(Actor actor)
{
if (!((Object)(object)instance == (Object)null) && !((Object)(object)actor == (Object)null) && actor.IsPlayer)
{
string actorDisplayName = instance.GetActorDisplayName(actor);
if (!string.IsNullOrEmpty(actorDisplayName))
{
instance.AddSystemMessage(actorDisplayName + " narrowly escaped death!", "FF4444");
}
}
}
private void UpdateActorSubscriptions()
{
if (!LazySingletonBehavior<NetworkManager>.HasInstance || !GameEventMessages.Value)
{
return;
}
NetworkManager val = LazySingletonBehavior<NetworkManager>.Instance;
if (!val.IsMultiplayer)
{
return;
}
if (ThirdPersonCameraControl.HasInstance && (Object)(object)ThirdPersonCameraControl.Instance.CharacterActor != (Object)null)
{
SubscribeToActorEvents(ThirdPersonCameraControl.Instance.CharacterActor);
}
if (val.VirtualCouch == null)
{
return;
}
foreach (VirtualCouchSeat item in val.VirtualCouch)
{
if (item != null && (Object)(object)item.actor != (Object)null)
{
SubscribeToActorEvents(item.actor);
}
}
}
private void BroadcastChatMessage(string sender, string text, bool isAction = false)
{
try
{
if (!LazySingletonBehavior<NetworkManager>.HasInstance)
{
return;
}
if (!LazySingletonBehavior<NetworkManager>.Instance.IsMultiplayer)
{
if (DebugMode.Value)
{
Log.LogInfo((object)"Not in multiplayer, skipping broadcast");
}
return;
}
int num = Serialization.STORAGE_SPACE_BYTE + Serialization.StorageSpaceString(sender) + Serialization.StorageSpaceString(text) + Serialization.STORAGE_SPACE_BYTE;
SerializationStream routedBuffer = ObjectDataRouter.Singleton.GetRoutedBuffer((ObjectDataReceiver)(object)this, num);
if (routedBuffer != null)
{
routedBuffer.PutByte((byte)1);
routedBuffer.PutString(sender);
routedBuffer.PutString(text);
routedBuffer.PutByte((byte)(isAction ? 1 : 0));
LazySingletonBehavior<NetworkManager>.Instance.SendReliable(routedBuffer);
if (DebugMode.Value)
{
Log.LogInfo((object)"Broadcast sent");
}
}
}
catch (Exception ex)
{
Log.LogError((object)("Broadcast error: " + ex));
}
}
public void Receive(SerializationStream stream)
{
try
{
byte @byte = stream.GetByte();
if (@byte == 1)
{
string @string = stream.GetString();
string string2 = stream.GetString();
bool flag = false;
try
{
flag = stream.GetByte() == 1;
}
catch
{
}
if (DebugMode.Value)
{
Log.LogInfo((object)$"Received: {@string}: {string2} (action={flag})");
}
AddMessage(@string, string2, flag, playSound: true);
}
}
catch (Exception ex)
{
Log.LogError((object)("Receive error: " + ex));
}
}
private float GetInputHeight()
{
return Mathf.Max(30f, (float)FontSize.Value + 16f);
}
private float GetMessageHeight(ChatMessage msg, float width)
{
//IL_0090: Unknown result type (might be due to invalid IL or missing references)
//IL_0096: Expected O, but got Unknown
string text = (ShowTimestamps.Value ? "[00:00] " : "");
string text2 = (msg.IsSystemMessage ? (text + msg.Text) : ((!msg.IsAction) ? $"{text}{msg.Sender}: {msg.Text}" : $"{text}*{msg.Sender} {msg.Text}*"));
if (labelStyle != null)
{
GUIContent val = new GUIContent(text2);
float num = labelStyle.CalcHeight(val, width);
return num + 4f;
}
float num2 = (float)FontSize.Value + 10f;
float num3 = width / ((float)FontSize.Value * 0.55f);
if (num3 < 10f)
{
num3 = 10f;
}
int num4 = Mathf.CeilToInt((float)text2.Length / num3);
if (num4 < 1)
{
num4 = 1;
}
return num2 * (float)num4;
}
private void EnsureChatLogInitialized()
{
if (!EnableLogging.Value || !string.IsNullOrEmpty(currentLogFile))
{
return;
}
try
{
if (string.IsNullOrEmpty(chatLogPath))
{
chatLogPath = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "chatlogs");
}
if (!Directory.Exists(chatLogPath))
{
Directory.CreateDirectory(chatLogPath);
}
string arg = DateTime.Now.ToString("yyyy-MM-dd");
currentLogFile = Path.Combine(chatLogPath, $"chat_{arg}.txt");
if (!File.Exists(currentLogFile))
{
string contents = "================================================" + Environment.NewLine + string.Format("[NecroChat] v{0} - Chat Log", "1.0.1") + Environment.NewLine + string.Format(" - Generated: {0}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")) + Environment.NewLine + "================================================" + Environment.NewLine + Environment.NewLine;
File.WriteAllText(currentLogFile, contents);
}
}
catch (Exception ex)
{
if (DebugMode.Value)
{
Log.LogError((object)("Failed to initialize chat log: " + ex.Message));
}
}
}
private void OnGUI()
{
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Invalid comparison between Unknown and I4
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
//IL_00cf: Invalid comparison between Unknown and I4
//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
//IL_0109: Unknown result type (might be due to invalid IL or missing references)
//IL_010f: Invalid comparison between Unknown and I4
//IL_0193: Unknown result type (might be due to invalid IL or missing references)
//IL_0199: Invalid comparison between Unknown and I4
//IL_0120: Unknown result type (might be due to invalid IL or missing references)
//IL_0125: Unknown result type (might be due to invalid IL or missing references)
//IL_012a: Unknown result type (might be due to invalid IL or missing references)
//IL_012f: Unknown result type (might be due to invalid IL or missing references)
//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
//IL_01d3: Invalid comparison between Unknown and I4
//IL_0210: Unknown result type (might be due to invalid IL or missing references)
//IL_0294: Unknown result type (might be due to invalid IL or missing references)
//IL_029e: Unknown result type (might be due to invalid IL or missing references)
//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
//IL_02af: Invalid comparison between Unknown and I4
//IL_0246: Unknown result type (might be due to invalid IL or missing references)
//IL_024d: Invalid comparison between Unknown and I4
//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
//IL_02bc: Invalid comparison between Unknown and I4
//IL_0250: Unknown result type (might be due to invalid IL or missing references)
//IL_025a: Invalid comparison between Unknown and I4
//IL_02d9: Unknown result type (might be due to invalid IL or missing references)
//IL_02df: Invalid comparison between Unknown and I4
//IL_025d: Unknown result type (might be due to invalid IL or missing references)
//IL_0264: Invalid comparison between Unknown and I4
//IL_0267: Unknown result type (might be due to invalid IL or missing references)
//IL_026e: Invalid comparison between Unknown and I4
//IL_0271: Unknown result type (might be due to invalid IL or missing references)
//IL_0278: Invalid comparison between Unknown and I4
//IL_03d9: Unknown result type (might be due to invalid IL or missing references)
//IL_03df: Invalid comparison between Unknown and I4
//IL_03e2: Unknown result type (might be due to invalid IL or missing references)
//IL_03e9: Invalid comparison between Unknown and I4
//IL_043e: Unknown result type (might be due to invalid IL or missing references)
//IL_0444: Invalid comparison between Unknown and I4
//IL_0447: Unknown result type (might be due to invalid IL or missing references)
//IL_044e: Invalid comparison between Unknown and I4
//IL_0398: Unknown result type (might be due to invalid IL or missing references)
//IL_039f: Invalid comparison between Unknown and I4
//IL_03a6: Unknown result type (might be due to invalid IL or missing references)
//IL_03b0: Invalid comparison between Unknown and I4
if (!ModEnabled.Value)
{
return;
}
if (clearInputNextFrame && (int)Event.current.type == 7)
{
inputText = "";
clearInputNextFrame = false;
}
InitializeStyles();
if (windowPosition.x < -0.5f)
{
chatWidth = 500f;
chatHeight = 375f;
windowPosition = new Vector2(10f, ((float)Screen.height - chatHeight) / 2f);
}
Event current = Event.current;
if (!Input.GetMouseButton(0))
{
isDragging = false;
isResizing = false;
}
if (isDragging && (int)current.type == 3)
{
windowPosition = current.mousePosition - dragOffset;
current.Use();
}
else if (isResizing && (int)current.type == 3)
{
Vector2 val = current.mousePosition - resizeStartPos;
chatWidth = Mathf.Clamp(resizeStartSize.x + val.x, 300f, 800f);
chatHeight = Mathf.Clamp(resizeStartSize.y + val.y, 200f, 600f);
current.Use();
}
if ((isDragging || isResizing) && (int)current.type == 1)
{
isDragging = false;
isResizing = false;
current.Use();
}
if (chatOpen && (current.isMouse || (int)current.type == 6))
{
Rect val2 = default(Rect);
((Rect)(ref val2))..ctor(windowPosition.x, windowPosition.y, chatWidth, chatHeight);
if (!((Rect)(ref val2)).Contains(current.mousePosition))
{
current.Use();
}
}
if (!chatOpen || !current.isKey || (int)current.keyCode == 13 || (int)current.keyCode == 271 || (int)current.keyCode == 27 || (int)current.keyCode == 9 || (int)current.keyCode != 99 || !current.control)
{
}
bool flag = current.keyCode == OpenChatKey.Value;
bool flag2 = (int)current.keyCode == 13 || (int)current.keyCode == 271;
bool flag3 = Time.time - lastChatCloseTime > 0.15f;
if ((int)current.type == 4 && (flag || flag2))
{
if (chatOpen && flag2)
{
if (DebugMode.Value)
{
Log.LogInfo((object)"Sending message, closing chat");
}
string text = inputText;
SendChatMessage(text);
inputText = "";
CloseChat();
current.Use();
return;
}
if (!chatOpen && flag && flag3 && !showFullHistory && IsChatAllowed() && !IsGameUIBlocking(allowLobby: true))
{
if ((int)OpenChatKey.Value != 13 && (int)OpenChatKey.Value != 271)
{
clearInputNextFrame = true;
}
OpenChat();
current.Use();
return;
}
}
if ((int)current.type == 4 && (int)current.keyCode == 27 && chatOpen)
{
if (selectedMessageIndex >= 0)
{
selectedMessageIndex = -1;
current.Use();
}
else
{
CloseChat();
current.Use();
}
}
else if ((int)current.type == 4 && (int)current.keyCode == 99 && current.control && (chatOpen || showFullHistory) && selectedMessageIndex >= 0 && selectedMessageIndex < messages.Count)
{
ChatMessage chatMessage = messages[selectedMessageIndex];
string text3 = (GUIUtility.systemCopyBuffer = (chatMessage.IsSystemMessage ? ("[SYSTEM] " + chatMessage.Text) : ((!chatMessage.IsAction) ? $"{chatMessage.Sender}: {chatMessage.Text}" : $"* {chatMessage.Sender} {chatMessage.Text}")));
if (DebugMode.Value)
{
Log.LogInfo((object)("Copied to clipboard: " + text3));
}
current.Use();
}
else
{
if (!IsChatAllowed())
{
return;
}
bool flag4 = IsMenuBlockingChat();
if (!chatOpen && !showFullHistory && (!HasRecentMessages() || flag4))
{
return;
}
windowPosition.x = Mathf.Clamp(windowPosition.x, 0f, (float)Screen.width - chatWidth);
windowPosition.y = Mathf.Clamp(windowPosition.y, 0f, (float)Screen.height - chatHeight);
float x = windowPosition.x;
float y = windowPosition.y;
bool flag5 = IsInMultiplayerLobby();
ChatDisplayMode value = DisplayMode.Value;
if (!flag5 && (value == ChatDisplayMode.AbovePlayer || value == ChatDisplayMode.BasicAndAbovePlayer || value == ChatDisplayMode.Smart))
{
DrawAbovePlayerMessages();
}
bool flag6 = true;
if (!chatOpen && !showFullHistory && value == ChatDisplayMode.AbovePlayer && !flag5)
{
flag6 = false;
}
if (chatOpen || showFullHistory)
{
DrawChatWindow(x, y);
}
else if (flag6)
{
if (value == ChatDisplayMode.Smart && !flag5)
{
DrawRecentMessagesFiltered(x, y, onlyFarPlayers: true);
}
else
{
DrawRecentMessages(x, y);
}
}
if (chatOpen && current.isKey)
{
current.Use();
}
}
}
private void InitializeStyles()
{
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_0089: Unknown result type (might be due to invalid IL or missing references)
//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
//IL_00d0: Expected O, but got Unknown
//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
//IL_0109: Expected O, but got Unknown
//IL_0130: Unknown result type (might be due to invalid IL or missing references)
//IL_0148: Unknown result type (might be due to invalid IL or missing references)
//IL_0152: Expected O, but got Unknown
//IL_016d: Unknown result type (might be due to invalid IL or missing references)
//IL_018d: Unknown result type (might be due to invalid IL or missing references)
//IL_0197: Expected O, but got Unknown
//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
//IL_01da: Unknown result type (might be due to invalid IL or missing references)
//IL_01e4: Expected O, but got Unknown
//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
//IL_0203: Unknown result type (might be due to invalid IL or missing references)
//IL_0230: Unknown result type (might be due to invalid IL or missing references)
//IL_023a: Expected O, but got Unknown
//IL_0259: Unknown result type (might be due to invalid IL or missing references)
//IL_0263: Expected O, but got Unknown
//IL_0282: Unknown result type (might be due to invalid IL or missing references)
//IL_02af: Unknown result type (might be due to invalid IL or missing references)
//IL_02b9: Expected O, but got Unknown
//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
//IL_02c4: Expected O, but got Unknown
//IL_02db: Unknown result type (might be due to invalid IL or missing references)
//IL_02e5: Expected O, but got Unknown
//IL_0300: Unknown result type (might be due to invalid IL or missing references)
//IL_0320: Unknown result type (might be due to invalid IL or missing references)
//IL_032a: Expected O, but got Unknown
//IL_0334: Unknown result type (might be due to invalid IL or missing references)
//IL_0378: Unknown result type (might be due to invalid IL or missing references)
//IL_0382: Expected O, but got Unknown
//IL_038c: Unknown result type (might be due to invalid IL or missing references)
int value = ChatBoxOpacity.Value;
if ((Object)(object)backgroundTex != (Object)null && value != lastOpacitySetting)
{
float num = (float)value / 100f;
backgroundTex.SetPixel(0, 0, new Color(0f, 0f, 0f, num));
backgroundTex.Apply();
headerTex.SetPixel(0, 0, new Color(0.2f, 0.2f, 0.3f, Mathf.Min(1f, num + 0.2f)));
headerTex.Apply();
lastOpacitySetting = value;
}
if (!stylesInitialized)
{
float num = (float)value / 100f;
lastOpacitySetting = value;
backgroundTex = new Texture2D(1, 1);
backgroundTex.SetPixel(0, 0, new Color(0f, 0f, 0f, num));
backgroundTex.Apply();
headerTex = new Texture2D(1, 1);
headerTex.SetPixel(0, 0, new Color(0.2f, 0.2f, 0.3f, Mathf.Min(1f, num + 0.2f)));
headerTex.Apply();
resizeTex = new Texture2D(1, 1);
resizeTex.SetPixel(0, 0, new Color(1f, 0.9f, 0f, 0.9f));
resizeTex.Apply();
labelStyle = new GUIStyle(GUI.skin.label);
labelStyle.normal.textColor = Color.white;
labelStyle.wordWrap = true;
labelStyle.richText = true;
labelStyle.clipping = (TextClipping)0;
inputStyle = new GUIStyle(GUI.skin.textField);
inputStyle.normal.textColor = Color.white;
inputStyle.focused.textColor = Color.white;
inputStyle.wordWrap = false;
inputStyle.clipping = (TextClipping)1;
boxStyle = new GUIStyle(GUI.skin.box);
boxStyle.normal.background = backgroundTex;
headerStyle = new GUIStyle(GUI.skin.box);
headerStyle.normal.background = headerTex;
headerStyle.normal.textColor = Color.white;
headerStyle.alignment = (TextAnchor)3;
headerStyle.fontSize = 12;
headerStyle.padding = new RectOffset(8, 8, 0, 0);
resizeHandleStyle = new GUIStyle();
resizeHandleStyle.normal.background = resizeTex;
selectionTex = new Texture2D(1, 1);
selectionTex.SetPixel(0, 0, new Color(0.3f, 0.5f, 0.8f, 0.5f));
selectionTex.Apply();
selectedLabelStyle = new GUIStyle(GUI.skin.label);
selectedLabelStyle.normal.textColor = Color.white;
selectedLabelStyle.normal.background = selectionTex;
selectedLabelStyle.wordWrap = true;
selectedLabelStyle.richText = true;
selectedLabelStyle.clipping = (TextClipping)0;
abovePlayerStyle = new GUIStyle();
abovePlayerStyle.normal.textColor = Color.white;
abovePlayerStyle.alignment = (TextAnchor)1;
abovePlayerStyle.wordWrap = true;
abovePlayerStyle.richText = true;
stylesInitialized = true;
}
if (!fontsLoaded && Time.time - lastFontCheckTime > 1f)
{
lastFontCheckTime = Time.time;
LoadFontsByName();
}
Font font = ((FontStyle.Value == ChatFontStyle.Necro) ? fontNecro : null);
labelStyle.font = font;
inputStyle.font = font;
selectedLabelStyle.font = font;
abovePlayerStyle.font = font;
int fontSize = Mathf.Clamp(FontSize.Value, 20, 40);
labelStyle.fontSize = fontSize;
inputStyle.fontSize = fontSize;
selectedLabelStyle.fontSize = fontSize;
}
private void LoadFontsByName()
{
try
{
Text[] array = Resources.FindObjectsOfTypeAll<Text>();
Text[] array2 = array;
foreach (Text val in array2)
{
if (!((Object)(object)val == (Object)null) && !((Object)(object)val.font == (Object)null) && (Object)(object)fontNecro == (Object)null && ((Object)val.font).name == "Nexa Slab Regular")
{
fontNecro = val.font;
fontsLoaded = true;
break;
}
}
}
catch (Exception ex)
{
Log.LogError((object)("Error loading fonts: " + ex.Message));
}
}
private bool HasRecentMessages()
{
if (messages.Count == 0)
{
return false;
}
if (MessageDisplayTime.Value <= 0 && MessageFadeTime.Value <= 0)
{
return true;
}
float num = MessageDisplayTime.Value + MessageFadeTime.Value;
float num2 = Time.time - num;
foreach (ChatMessage message in messages)
{
if (message.Timestamp >= num2)
{
return true;
}
}
return false;
}
private void DrawChatWindow(float x, float y)
{
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
//IL_010d: Unknown result type (might be due to invalid IL or missing references)
//IL_0123: Unknown result type (might be due to invalid IL or missing references)
//IL_012a: Expected O, but got Unknown
//IL_014c: Unknown result type (might be due to invalid IL or missing references)
//IL_0153: Expected O, but got Unknown
//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
//IL_00da: Unknown result type (might be due to invalid IL or missing references)
//IL_00df: Unknown result type (might be due to invalid IL or missing references)
//IL_0186: Unknown result type (might be due to invalid IL or missing references)
//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
//IL_0212: Unknown result type (might be due to invalid IL or missing references)
//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
//IL_0222: Unknown result type (might be due to invalid IL or missing references)
//IL_0227: Unknown result type (might be due to invalid IL or missing references)
//IL_023d: Unknown result type (might be due to invalid IL or missing references)
//IL_0252: Unknown result type (might be due to invalid IL or missing references)
//IL_0259: Expected O, but got Unknown
//IL_0272: Unknown result type (might be due to invalid IL or missing references)
//IL_027c: Expected O, but got Unknown
//IL_0283: Unknown result type (might be due to invalid IL or missing references)
//IL_028d: Expected O, but got Unknown
//IL_02a9: 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_02f3: Unknown result type (might be due to invalid IL or missing references)
//IL_03ce: 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_03d5: Unknown result type (might be due to invalid IL or missing references)
//IL_03d7: Unknown result type (might be due to invalid IL or missing references)
//IL_03dc: Unknown result type (might be due to invalid IL or missing references)
//IL_051b: Unknown result type (might be due to invalid IL or missing references)
//IL_052d: Unknown result type (might be due to invalid IL or missing references)
//IL_053c: Unknown result type (might be due to invalid IL or missing references)
//IL_0541: Unknown result type (might be due to invalid IL or missing references)
//IL_0546: Unknown result type (might be due to invalid IL or missing references)
//IL_05a8: Unknown result type (might be due to invalid IL or missing references)
//IL_0474: Unknown result type (might be due to invalid IL or missing references)
//IL_0486: Unknown result type (might be due to invalid IL or missing references)
Event current = Event.current;
float inputHeight = GetInputHeight();
Rect val = default(Rect);
((Rect)(ref val))..ctor(x, y, chatWidth, 55f);
Rect val2 = default(Rect);
((Rect)(ref val2))..ctor(x + chatWidth - 24f, y + chatHeight - 24f, 24f, 24f);
if ((int)current.type == 0 && ((Rect)(ref val)).Contains(current.mousePosition) && !isResizing)
{
isDragging = true;
dragOffset = current.mousePosition - windowPosition;
current.Use();
}
if ((int)current.type == 0 && ((Rect)(ref val2)).Contains(current.mousePosition) && !isDragging)
{
isResizing = true;
resizeStartPos = current.mousePosition;
resizeStartSize = new Vector2(chatWidth, chatHeight);
current.Use();
}
GUI.Box(new Rect(x, y, chatWidth, chatHeight), "", boxStyle);
GUI.Box(val, "", headerStyle);
GUIStyle val3 = new GUIStyle(headerStyle);
val3.alignment = (TextAnchor)4;
val3.fontSize = headerStyle.fontSize + 2;
GUIStyle val4 = new GUIStyle(headerStyle);
val4.alignment = (TextAnchor)1;
val4.fontSize = headerStyle.fontSize;
val4.wordWrap = true;
if (showFullHistory)
{
GUI.Label(val, "<b>NECROCHAT HISTORY</b>", val3);
}
else if (IsInMultiplayerLobby())
{
GUI.Label(val, "<b>NECROCHAT LOBBY</b>", val3);
}
else
{
float num = 20f;
Rect val5 = default(Rect);
((Rect)(ref val5))..ctor(x, y, chatWidth, num);
Rect val6 = default(Rect);
((Rect)(ref val6))..ctor(x + 5f, y + num, chatWidth - 10f, 55f - num);
GUI.Label(val5, string.Format("<b>NECROCHAT</b> v{0}", "1.0.1"), val3);
GUI.Label(val6, "ENTER=Send, ESC=Close, Click=Select, Mouse-drag to resize/reposition", val4);
}
Color color = GUI.color;
GUI.color = new Color(1f, 0.9f, 0f, 0.9f);
GUIStyle val7 = new GUIStyle(GUI.skin.label);
val7.fontSize = 20;
val7.alignment = (TextAnchor)8;
val7.padding = new RectOffset(0, 0, 0, 0);
val7.margin = new RectOffset(0, 0, 0, 0);
val7.normal.textColor = new Color(1f, 0.9f, 0f, 0.9f);
Rect val8 = default(Rect);
((Rect)(ref val8))..ctor(((Rect)(ref val2)).x + 2f, ((Rect)(ref val2)).y + 7f, ((Rect)(ref val2)).width, ((Rect)(ref val2)).height);
GUI.Label(val8, "◢", val7);
GUI.color = color;
float num2 = y + 55f + 5f;
float num3 = (chatOpen ? (inputHeight + 20f) : 10f);
float num4 = chatHeight - 55f - num3 - 5f;
num4 = Mathf.Max(num4, 50f);
float num5 = chatWidth - 30f - 20f;
Rect val9 = default(Rect);
((Rect)(ref val9))..ctor(x + 10f, num2, chatWidth - 20f, num4);
float num6 = 0f;
for (int i = 0; i < messages.Count; i++)
{
num6 += GetMessageHeight(messages[i], num5);
}
Rect val10 = default(Rect);
((Rect)(ref val10))..ctor(0f, 0f, num5, num6);
scrollPosition = GUI.BeginScrollView(val9, scrollPosition, val10);
float num7 = 0f;
Rect val11 = default(Rect);
for (int i = 0; i < messages.Count; i++)
{
ChatMessage msg = messages[i];
float messageHeight = GetMessageHeight(msg, num5);
float messageAlpha = GetMessageAlpha(msg);
if (messageAlpha > 0f || showFullHistory || chatOpen)
{
float alpha = ((showFullHistory || chatOpen) ? 1f : messageAlpha);
bool isSelected = i == selectedMessageIndex;
((Rect)(ref val11))..ctor(0f, num7, num5, messageHeight);
if ((int)current.type == 0 && current.button == 0 && ((Rect)(ref val11)).Contains(current.mousePosition))
{
selectedMessageIndex = ((selectedMessageIndex == i) ? (-1) : i);
current.Use();
}
DrawMessageLine(0f, num7, num5, messageHeight, msg, alpha, isSelected);
}
num7 += messageHeight;
}
GUI.EndScrollView();
Rect val12 = default(Rect);
((Rect)(ref val12))..ctor(0f, 0f, chatWidth, chatHeight);
if ((int)current.type == 0 && current.button == 0 && !((Rect)(ref val9)).Contains(current.mousePosition) && ((Rect)(ref val12)).Contains(current.mousePosition - windowPosition))
{
selectedMessageIndex = -1;
}
if (chatOpen)
{
float num8 = y + chatHeight - inputHeight - 10f;
GUI.SetNextControlName("ChatInputField");
inputText = GUI.TextField(new Rect(x + 10f, num8, chatWidth - 20f, inputHeight), inputText, 100, inputStyle);
if (inputText.IndexOf('\n') >= 0 || inputText.IndexOf('\r') >= 0)
{
inputText = inputText.Replace("\n", "").Replace("\r", "");
}
if (inputText.Length > 100)
{
inputText = inputText.Substring(0, 100);
}
GUI.FocusControl("ChatInputField");
}
}
private void DrawRecentMessages(float x, float y)
{
DrawRecentMessagesFiltered(x, y, onlyFarPlayers: false);
}
private void DrawRecentMessagesFiltered(float x, float y, bool onlyFarPlayers)
{
List<ChatMessage> list = new List<ChatMessage>();
float num = MessageDisplayTime.Value + MessageFadeTime.Value;
float num2 = Time.time - num;
foreach (ChatMessage message in messages)
{
if (message.Timestamp >= num2)
{
list.Add(message);
}
}
if (list.Count == 0)
{
return;
}
HashSet<string> hashSet = new HashSet<string>();
int num3 = Mathf.Clamp(MaxVisibleMessages.Value, 1, 20);
float width = chatWidth - 20f;
int num4 = Math.Max(0, list.Count - num3);
float num5 = y + chatHeight - 10f;
for (int num6 = list.Count - 1; num6 >= num4; num6--)
{
ChatMessage current = list[num6];
if (onlyFarPlayers)
{
Actor val = FindActorByPlayerName(current.Sender);
if ((Object)(object)val != (Object)null)
{
float distanceToCamera = GetDistanceToCamera(val);
if (distanceToCamera <= (float)SmartModeDistance.Value)
{
sendersCurrentlyInCorner.Remove(current.Sender);
senderCornerTransitionTime.Remove(current.Sender);
continue;
}
hashSet.Add(current.Sender);
if (!sendersCurrentlyInCorner.Contains(current.Sender))
{
sendersCurrentlyInCorner.Add(current.Sender);
senderCornerTransitionTime[current.Sender] = Time.time;
}
}
}
float messageHeight = GetMessageHeight(current, width);
float num7 = GetMessageAlpha(current);
if (onlyFarPlayers && ChatBoxAnimations.Value && !string.IsNullOrEmpty(current.Sender) && senderCornerTransitionTime.TryGetValue(current.Sender, out var value))
{
float num8 = Time.time - value;
if (num8 < 0.5f)
{
float num9 = num8 / 0.5f;
num7 = Mathf.Min(num7, num9);
}
}
if (num7 > 0f)
{
num5 -= messageHeight;
DrawMessageWithShadow(x + 10f, num5, width, messageHeight, current, num7);
}
}
}
private void DrawMessageLine(float x, float y, float width, float height, ChatMessage msg, float alpha, bool isSelected = false)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_0172: Unknown result type (might be due to invalid IL or missing references)
//IL_0180: Unknown result type (might be due to invalid IL or missing references)
Color color = GUI.color;
GUI.color = new Color(1f, 1f, 1f, alpha);
string text = ((int)(alpha * 255f)).ToString("X2");
string text2 = "";
if (ShowTimestamps.Value)
{
text2 = string.Format("<color=#888888{0}>[{1}]</color> ", text, msg.RealTime.ToString("HH:mm"));
}
string text3;
if (msg.IsSystemMessage)
{
text3 = $"{text2}<color=#{msg.SystemColor}{text}><b>{msg.Text}</b></color>";
}
else
{
string playerDyeColorHex = GetPlayerDyeColorHex(msg.Sender);
text3 = ((!msg.IsAction) ? string.Format("{0}<color=#{1}{2}><b>{3}</b></color><color=#FFFFFF{2}>: {4}</color>", text2, playerDyeColorHex, text, msg.Sender, msg.Text) : $"{text2}<color=#7EC8E3{text}><b><i>*{msg.Sender} {msg.Text}*</i></b></color>");
}
GUIStyle val = (isSelected ? selectedLabelStyle : labelStyle);
GUI.Label(new Rect(x, y, width, height), text3, val);
GUI.color = color;
}
private void DrawMessageWithShadow(float x, float y, float width, float height, ChatMessage msg, float alpha)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0216: Unknown result type (might be due to invalid IL or missing references)
//IL_0232: Unknown result type (might be due to invalid IL or missing references)
//IL_0254: Unknown result type (might be due to invalid IL or missing references)
//IL_0264: Unknown result type (might be due to invalid IL or missing references)
//IL_0276: Unknown result type (might be due to invalid IL or missing references)
Color color = GUI.color;
string text = ((int)(alpha * 255f)).ToString("X2");
string text2 = ((int)(alpha * 0.8f * 255f)).ToString("X2");
string text3 = "";
string text4 = "";
if (ShowTimestamps.Value)
{
string arg = msg.RealTime.ToString("HH:mm");
text3 = $"<color=#888888{text}>[{arg}]</color> ";
text4 = $"<color=#000000{text2}>[{arg}]</color> ";
}
string text5;
string text6;
if (msg.IsSystemMessage)
{
text5 = $"{text4}<color=#000000{text2}><b>{msg.Text}</b></color>";
text6 = $"{text3}<color=#{msg.SystemColor}{text}><b>{msg.Text}</b></color>";
}
else
{
string playerDyeColorHex = GetPlayerDyeColorHex(msg.Sender);
if (msg.IsAction)
{
text5 = $"{text4}<color=#000000{text2}><b><i>*{msg.Sender} {msg.Text}*</i></b></color>";
text6 = $"{text3}<color=#7EC8E3{text}><b><i>*{msg.Sender} {msg.Text}*</i></b></color>";
}
else
{
text5 = $"{text4}<color=#000000{text2}><b>{msg.Sender}</b>: {msg.Text}</color>";
text6 = string.Format("{0}<color=#{1}{2}><b>{3}</b></color><color=#FFFFFF{2}>: {4}</color>", text3, playerDyeColorHex, text, msg.Sender, msg.Text);
}
}
GUI.color = new Color(0f, 0f, 0f, alpha * 0.8f);
GUI.Label(new Rect(x + 1f, y + 1f, width, height), text5, labelStyle);
GUI.color = new Color(1f, 1f, 1f, alpha);
GUI.Label(new Rect(x, y, width, height), text6, labelStyle);
GUI.color = color;
}
private Actor FindActorByPlayerName(string playerName)
{
try
{
if (!LazySingletonBehavior<NetworkManager>.HasInstance)
{
return null;
}
NetworkManager val = LazySingletonBehavior<NetworkManager>.Instance;
if (val.LocalVirtualCouchSeat != null && val.LocalVirtualCouchSeat.platformHandle != null && val.LocalVirtualCouchSeat.platformHandle.Name == playerName && ThirdPersonCameraControl.HasInstance && (Object)(object)ThirdPersonCameraControl.Instance.CharacterActor != (Object)null)
{
return ThirdPersonCameraControl.Instance.CharacterActor;
}
if (val.VirtualCouch != null)
{
foreach (VirtualCouchSeat item in val.VirtualCouch)
{
if (item != null && item.platformHandle != null && item.platformHandle.Name == playerName && (Object)(object)item.actor != (Object)null)
{
return item.actor;
}
}
}
}
catch
{
}
return null;
}
private float GetDistanceToCamera(Actor actor)
{
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)actor == (Object)null || (Object)(object)actor.Body == (Object)null)
{
return float.MaxValue;
}
if (!ThirdPersonCameraControl.HasInstance)
{
return float.MaxValue;
}
Camera component = ((Component)ThirdPersonCameraControl.Instance).GetComponent<Camera>();
if ((Object)(object)component == (Object)null)
{
return float.MaxValue;
}
return Vector3.Distance(((Component)component).transform.position, ((Component)actor.Body).transform.position);
}
private void DrawAbovePlayerMessages()
{
//IL_0255: Unknown result type (might be due to invalid IL or missing references)
//IL_0266: Unknown result type (might be due to invalid IL or missing references)
//IL_026b: Unknown result type (might be due to invalid IL or missing references)
//IL_0270: Unknown result type (might be due to invalid IL or missing references)
//IL_0273: Unknown result type (might be due to invalid IL or missing references)
//IL_0275: Unknown result type (might be due to invalid IL or missing references)
//IL_027a: Unknown result type (might be due to invalid IL or missing references)
if (!ThirdPersonCameraControl.HasInstance)
{
return;
}
Camera component = ((Component)ThirdPersonCameraControl.Instance).GetComponent<Camera>();
if ((Object)(object)component == (Object)null)
{
return;
}
ChatDisplayMode value = DisplayMode.Value;
if (value == ChatDisplayMode.Basic)
{
return;
}
float num = AbovePlayerDisplayTime.Value;
float num2 = AbovePlayerFadeTime.Value;
float num3 = num + num2;
Dictionary<string, List<ChatMessage>> dictionary = new Dictionary<string, List<ChatMessage>>();
foreach (ChatMessage message in messages)
{
float num4 = Time.time - message.Timestamp;
if (!(num4 > num3))
{
if (!dictionary.ContainsKey(message.Sender))
{
dictionary[message.Sender] = new List<ChatMessage>();
}
dictionary[message.Sender].Add(message);
}
}
foreach (KeyValuePair<string, List<ChatMessage>> item in dictionary)
{
string key = item.Key;
List<ChatMessage> value2 = item.Value;
Actor val = FindActorByPlayerName(key);
if ((Object)(object)val == (Object)null || (Object)(object)val.Body == (Object)null)
{
continue;
}
float distanceToCamera = GetDistanceToCamera(val);
float num5 = 1f;
if (value == ChatDisplayMode.Smart)
{
float num6 = SmartModeDistance.Value;
float num7 = 5f;
if (distanceToCamera > num6)
{
continue;
}
if (distanceToCamera > num6 - num7 && ChatBoxAnimations.Value)
{
num5 = (num6 - distanceToCamera) / num7;
}
}
float num8 = 0f;
if ((Object)(object)val.Body.thisController != (Object)null)
{
float num9 = ((val.actorDefId != null && val.actorDefId.StartsWith("Brute")) ? 1.1f : 0.95f);
num8 = val.Body.thisController.height * num9;
}
Vector3 val2 = ((Component)val.Body).transform.position + new Vector3(0f, num8, 0f);
Vector3 val3 = component.WorldToScreenPoint(val2);
bool flag = val3.z < 0f;
if (flag)
{
val3.x = (float)Screen.width - val3.x;
val3.y = (float)Screen.height - val3.y;
}
bool flag2 = flag || val3.x < 50f || val3.x > (float)(Screen.width - 50) || val3.y < 50f || val3.y > (float)(Screen.height - 50);
if (flag2 && distanceToCamera > (float)SmartModeDistance.Value)
{
continue;
}
if (flag2)
{
float num10 = (float)Screen.width / 2f;
float num11 = (float)Screen.height / 2f;
float num12 = val3.x - num10;
float num13 = val3.y - num11;
float num14 = Mathf.Abs(num12);
float num15 = Mathf.Abs(num13);
float num16 = 60f;
if (num14 / ((float)Screen.width / 2f) > num15 / ((float)Screen.height / 2f))
{
float num17 = ((float)Screen.width / 2f - num16) / num14;
val3.x = num10 + num12 * num17;
val3.y = Mathf.Clamp(num11 + num13 * num17, num16, (float)Screen.height - num16);
}
else
{
float num17 = ((float)Screen.height / 2f - num16) / num15;
val3.y = num11 + num13 * num17;
val3.x = Mathf.Clamp(num10 + num12 * num17, num16, (float)Screen.width - num16);
}
}
float num18 = (float)Screen.height - val3.y;
if (HidePlayerNameOnChat.Value && (Object)(object)val.Body != (Object)null && SceneSingletonBehavior<HUDManager>.HasInstance)
{
HUDIndicator hUDIndicatorForActor = GetHUDIndicatorForActor(val);
if ((Object)(object)hUDIndicatorForActor != (Object)null)
{
((Component)hUDIndicatorForActor).gameObject.SetActive(false);
hiddenHUDIndicators.Add(val);
}
}
float num19 = num18;
for (int num20 = value2.Count - 1; num20 >= 0; num20--)
{
ChatMessage current = value2[num20];
float num4 = Time.time - current.Timestamp;
float num21 = 1f;
float num22 = 1f;
bool value3 = AbovePlayerAnimations.Value;
if (value3 && num4 < 0.3f)
{
num21 = num4 / 0.3f;
num22 = num21;
}
else if (num4 > num && num2 > 0f)
{
float num23 = (num4 - num) / num2;
num21 = 1f - num23;
}
num21 *= num5;
float num24 = (value3 ? ((1f - num22) * 25f) : 0f);
float num25 = DrawAbovePlayerText(val3.x, num19 + num24, current, num21, flag2);
float num26 = (value3 ? (num25 * num22) : num25);
num19 -= num26 + (value3 ? (5f * num22) : 5f);
if (num19 < 0f)
{
break;
}
}
}
}
private HUDIndicator GetHUDIndicatorForActor(Actor actor)
{
try
{
if (!SceneSingletonBehavior<HUDManager>.HasInstance)
{
return null;
}
if ((Object)(object)actor == (Object)null || (Object)(object)actor.Body == (Object)null)
{
return null;
}
if ((object)trackedObjectsField == null)
{
trackedObjectsField = typeof(HUDManager).GetField("trackedObjects", BindingFlags.Instance | BindingFlags.NonPublic);
}
if ((object)trackedObjectsField == null)
{
return null;
}
HUDManager obj = SceneSingletonBehavior<HUDManager>.Instance;
if (!(trackedObjectsField.GetValue(obj) is Dictionary<GameObject, HUDIndicator> dictionary))
{
return null;
}
if (dictionary.TryGetValue(((Component)actor.Body).gameObject, out var value))
{
return value;
}
}
catch
{
}
return null;
}
private string GetPlayerDyeColorHex(string playerName)
{
if (!UsePlayerDyeColors.Value)
{
return "ffcc00";
}
try
{
Actor val = FindActorByPlayerName(playerName);
if ((Object)(object)val != (Object)null)
{
return GetActorDyeColor(val);
}
}
catch
{
}
return "ffcc00";
}
private Color GetPlayerDyeColor(Actor actor)
{
//IL_0105: Unknown result type (might be due to invalid IL or missing references)
//IL_0106: Unknown result type (might be due to invalid IL or missing references)
//IL_010a: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
Color result = default(Color);
((Color)(ref result))..ctor(1f, 0.84f, 0f);
if ((Object)(object)actor == (Object)null || (Object)(object)actor.Body == (Object)null)
{
return result;
}
try
{
if (actor.Body.bodyRenderers != null && actor.Body.bodyRenderers.Count > 0)
{
foreach (Renderer bodyRenderer in actor.Body.bodyRenderers)
{
if ((Object)(object)bodyRenderer != (Object)null && (Object)(object)bodyRenderer.material != (Object)null && bodyRenderer.material.HasProperty("_SecondaryColor"))
{
return bodyRenderer.material.GetColor("_SecondaryColor");
}
}
}
}
catch
{
}
return result;
}
private string GetActorDyeColor(Actor actor)
{
//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
//IL_00ce: 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)
try
{
if ((Object)(object)actor == (Object)null || (Object)(object)actor.Body == (Object)null)
{
return "ffcc00";
}
if (actor.Body.bodyRenderers != null && actor.Body.bodyRenderers.Count > 0)
{
foreach (Renderer bodyRenderer in actor.Body.bodyRenderers)
{
if ((Object)(object)bodyRenderer != (Object)null && (Object)(object)bodyRenderer.material != (Object)null && bodyRenderer.material.HasProperty("_SecondaryColor"))
{
Color color = bodyRenderer.material.GetColor("_SecondaryColor");
return ColorToHex(color);
}
}
}
Inventory val = Inventory.Get(((Component)actor.Body).gameObject, true);
if ((Object)(object)val != (Object)null && val.HasColorSet)
{
string activeColorSet = val.ActiveColorSet;
if (!string.IsNullOrEmpty(activeColorSet))
{
ColorPaletteDef palette = ColorPaletteApplicator.GetPalette(activeColorSet);
if (palette != null && palette.colors != null && palette.colorPropertyNames != null)
{
for (int i = 0; i < palette.colorPropertyNames.Length; i++)
{
if (palette.colorPropertyNames[i] == "_SecondaryColor")
{
return ColorToHex(palette.colors[i]);
}
}
}
}
}
}
catch
{
}
return "ffcc00";
}
private string ColorToHex(Color color)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//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)
float num = default(float);
float num2 = default(float);
float num3 = default(float);
Color.RGBToHSV(color, ref num, ref num2, ref num3);
if (num3 < 0.75f)
{
num3 = 0.75f + num3 * 0.25f;
}
if (num2 > 0.7f)
{
num2 *= 0.8f;
}
Color val = Color.HSVToRGB(num, num2, num3);
int num4 = (int)(val.r * 255f);
int num5 = (int)(val.g * 255f);
int num6 = (int)(val.b * 255f);
return $"{num4:X2}{num5:X2}{num6:X2}";
}
private string GetActorDisplayName(Actor actor)
{
try
{
if ((Object)(object)actor == (Object)null)
{
return "";
}
if (actor.Possessor != null && actor.Possessor.platformHandle != null && !string.IsNullOrEmpty(actor.Possessor.platformHandle.Name))
{
return actor.Possessor.platformHandle.Name;
}
}
catch
{
}
return "";
}
private float DrawAbovePlayerText(float x, float y, ChatMessage msg, float alpha, bool showSender = false)
{
//IL_0100: Unknown result type (might be due to invalid IL or missing references)
//IL_0107: Expected O, but got Unknown
//IL_03b7: Unknown result type (might be due to invalid IL or missing references)
//IL_03d6: Unknown result type (might be due to invalid IL or missing references)
//IL_03f6: Unknown result type (might be due to invalid IL or missing references)
//IL_0409: Unknown result type (might be due to invalid IL or missing references)
//IL_0418: Unknown result type (might be due to invalid IL or missing references)
string text = ((int)(alpha * 255f)).ToString("X2");
string arg = ((int)(alpha * 0.8f * 255f)).ToString("X2");
float num = AbovePlayerWidth.Value;
int num2 = 0;
bool value = ColorAbovePlayerMessage.Value;
string text2 = ((!showSender || value) ? (msg.IsAction ? $"*{msg.Text}*" : msg.Text) : (msg.IsAction ? $"*{msg.Sender} {msg.Text}*" : $"{msg.Sender}: {msg.Text}"));
int value2 = AbovePlayerFontSize.Value;
int num3 = 10;
int num4 = value2;
GUIStyle val = abovePlayerStyle;
float num5 = num;
float num6 = 0f;
int num7 = ((num2 > 0) ? Mathf.Max(1, num2 / (value2 + 4)) : 6);
GUIContent val2 = new GUIContent(text2);
while (num4 >= num3)
{
val.fontSize = num4;
num6 = val.CalcHeight(val2, num);
float num8 = (float)num4 + 4f;
int num9 = Mathf.CeilToInt(num6 / num8);
bool flag = num2 <= 0 || num6 <= (float)num2;
bool flag2 = num9 <= num7;
if (flag && flag2)
{
break;
}
num4 -= 2;
}
if (num4 < num3)
{
num4 = num3;
}
val.fontSize = num4;
num6 = val.CalcHeight(val2, num);
if (num2 > 0)
{
num6 = Mathf.Min(num6, (float)num2);
}
string playerDyeColorHex = GetPlayerDyeColorHex(msg.Sender);
string text3;
string text4;
if (msg.IsAction)
{
if (value)
{
text3 = $"<color=#{playerDyeColorHex}{text}><b><i>*{msg.Text}*</i></b></color>";
text4 = $"<color=#000000{arg}><b><i>*{msg.Text}*</i></b></color>";
}
else if (showSender)
{
text3 = $"<color=#7EC8E3{text}><b><i>*{msg.Sender} {msg.Text}*</i></b></color>";
text4 = $"<color=#000000{arg}><b><i>*{msg.Sender} {msg.Text}*</i></b></color>";
}
else
{
text3 = $"<color=#7EC8E3{text}><b><i>*{msg.Text}*</i></b></color>";
text4 = $"<color=#000000{arg}><b><i>*{msg.Text}*</i></b></color>";
}
}
else if (value)
{
text3 = $"<color=#{playerDyeColorHex}{text}>{msg.Text}</color>";
text4 = $"<color=#000000{arg}>{msg.Text}</color>";
}
else if (showSender)
{
text3 = string.Format("<color=#{0}{1}><b>{2}</b></color><color=#FFFFFF{1}>: {3}</color>", playerDyeColorHex, text, msg.Sender, msg.Text);
text4 = $"<color=#000000{arg}><b>{msg.Sender}</b>: {msg.Text}</color>";
}
else
{
text3 = $"<color=#FFFFFF{text}>{msg.Text}</color>";
text4 = $"<color=#000000{arg}>{msg.Text}</color>";
}
float num10 = x - num5 / 2f;
float num11 = y - num6;
if (num10 < 5f)
{
num10 = 5f;
}
if (num10 + num5 > (float)(Screen.width - 5))
{
num10 = (float)Screen.width - num5 - 5f;
}
GUI.color = new Color(0f, 0f, 0f, alpha * 0.8f);
GUI.Label(new Rect(num10 + 1f, num11 + 1f, num5, num6), text4, val);
GUI.color = new Color(1f, 1f, 1f, alpha);
GUI.Label(new Rect(num10, num11, num5, num6), text3, val);
GUI.color = Color.white;
return num6;
}
private float GetMessageAlpha(ChatMessage msg)
{
int value = MessageDisplayTime.Value;
int value2 = MessageFadeTime.Value;
if (value <= 0 && value2 <= 0)
{
return 1f;
}
float num = Time.time - msg.Timestamp;
if (ChatBoxAnimations.Value && num < 0.5f)
{
return num / 0.5f;
}
if (num < (float)value)
{
return 1f;
}
if (value2 > 0 && num < (float)(value + value2))
{
float num2 = (num - (float)value) / (float)value2;
return 1f - num2;
}
return 0f;
}
private void OnDestroy()
{
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
RestoreAllHUDIndicators();
UnregisterGameEventCallbacks();
subscribedActors.Clear();
actorHadAutoResurrect.Clear();
actorDidSpawnReset.Clear();
lastReviveTime.Clear();
lastJoinLeaveTime.Clear();
if (chatOpen)
{
if (LazySingletonBehavior<EventSystemObjectHandler>.HasInstance)
{
LazySingletonBehavior<EventSystemObjectHandler>.Instance.SetInputDisabled(false);
}
if (SceneSingletonBehavior<NecroKeyboardManager>.HasInstance)
{
SceneSingletonBehavior<NecroKeyboardManager>.Instance.SetProfileState(previousMouseState);
}
}
if (ObjectDataRouter.Singleton != null)
{
ObjectDataRouter.Singleton.Unregister((ObjectDataReceiver)(object)this);
}
instance = null;
if ((Object)(object)backgroundTex != (Object)null)
{
Object.Destroy((Object)(object)backgroundTex);
}
if ((Object)(object)headerTex != (Object)null)
{
Object.Destroy((Object)(object)headerTex);
}
if ((Object)(object)resizeTex != (Object)null)
{
Object.Destroy((Object)(object)resizeTex);
}
if ((Object)(object)selectionTex != (Object)null)
{
Object.Destroy((Object)(object)selectionTex);
}
}
}
public class ChatMessage
{
public string Sender { get; private set; }
public string Text { get; private set; }
public float Timestamp { get; private set; }
public DateTime RealTime { get; private set; }
public bool IsAction { get; private set; }
public bool IsSystemMessage { get; private set; }
public string SystemColor { get; private set; }
public ChatMessage(string sender, string text, float timestamp, bool isAction = false)
{
Sender = sender;
Text = text;
Timestamp = timestamp;
RealTime = DateTime.Now;
IsAction = isAction;
IsSystemMessage = false;
SystemColor = null;
}
public ChatMessage(string text, float timestamp, string color)
{
Sender = "";
Text = text;
Timestamp = timestamp;
RealTime = DateTime.Now;
IsAction = false;
IsSystemMessage = true;
SystemColor = color;
}
}
[HarmonyPatch(/*Could not decode attribute arguments.*/)]
internal static class ModalDialogController_IsShowing_Patch
{
private static void Postfix(ref bool __result)
{
if (ChatModPlugin.chatOpen)
{
__result = true;
}
}
}
[HarmonyPatch(typeof(Platform), "GetKeyDown")]
internal static class Platform_GetKeyDown_Patch
{
private static bool Prefix(KeyCode code, ref bool __result)
{
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Invalid comparison between Unknown and I4
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Invalid comparison between Unknown and I4
if (ChatModPlugin.chatOpen)
{
__result = false;
return false;
}
if (ChatModPlugin.IsInMultiplayerLobby() && ((int)code == 13 || (int)code == 271))
{
__result = false;
return false;
}
return true;
}
}
[HarmonyPatch(typeof(Input), "GetKeyDown", new Type[] { typeof(KeyCode) })]
internal static class Input_GetKeyDown_Patch
{
private static bool Prefix(KeyCode key, ref bool __result)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Invalid comparison between Unknown and I4
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: Invalid comparison between Unknown and I4
if (ChatModPlugin.IsInMultiplayerLobby() && ((int)key == 13 || (int)key == 271))
{
__result = false;
return false;
}
return true;
}
}
[HarmonyPatch(typeof(Input), "GetKey", new Type[] { typeof(KeyCode) })]
internal static class Input_GetKey_Patch
{
private static bool Prefix(KeyCode key, ref bool __result)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Invalid comparison between Unknown and I4
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: Invalid comparison between Unknown and I4
if (ChatModPlugin.IsInMultiplayerLobby() && ((int)key == 13 || (int)key == 271))
{
__result = false;
return false;
}
return true;
}
}
[HarmonyPatch(typeof(Input), "GetKeyDown", new Type[] { typeof(string) })]
internal static class Input_GetKeyDown_String_Patch
{
private static bool Prefix(string name, ref bool __result)
{
if (ChatModPlugin.IsInMultiplayerLobby() && (name == "return" || name == "enter"))
{
__result = false;
return false;
}
return true;
}
}
[HarmonyPatch(typeof(Input), "GetKey", new Type[] { typeof(string) })]
internal static class Input_GetKey_String_Patch
{
private static bool Prefix(string name, ref bool __result)
{
if (ChatModPlugin.IsInMultiplayerLobby() && (name == "return" || name == "enter"))
{
__result = false;
return false;
}
return true;
}
}
[HarmonyPatch(typeof(Input), "GetButtonDown", new Type[] { typeof(string) })]
internal static class Input_GetButtonDown_Patch
{
private static bool Prefix(string buttonName, ref bool __result)
{
if (ChatModPlugin.IsInMultiplayerLobby() && buttonName == "Submit")
{
__result = false;
return false;
}
return true;
}
}
[HarmonyPatch(typeof(RxResurrect), "Activate")]
internal static class RxResurrect_Activate_Patch
{
private static void Prefix(RxResurrect __instance, bool val)
{
//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
//IL_0175: Unknown result type (might be due to invalid IL or missing references)
//IL_0180: Unknown result type (might be due to invalid IL or missing references)
if (!val || (Object)(object)__instance.actor == (Object)null || __instance.actor.IsAlive)
{
return;
}
try
{
if (!LazySingletonBehavior<NetworkManager>.HasInstance)
{
return;
}
NetworkManager instance = LazySingletonBehavior<NetworkManager>.Instance;
Actor lastReviver = null;
float num = float.MaxValue;
if (ThirdPersonCameraControl.HasInstance && (Object)(object)ThirdPersonCameraControl.Instance.CharacterActor != (Object)null)
{
Actor characterActor = ThirdPersonCameraControl.Instance.CharacterActor;
if (characterActor.IsAlive && (Object)(object)characterActor != (Object)(object)__instance.actor)
{
float num2 = Vector3.Distance(characterActor.Position, __instance.actor.Position);
if (num2 < num && num2 < 5f)
{
num = num2;
lastReviver = characterActor;
}
}
}
if (instance.VirtualCouch != null)
{
foreach (VirtualCouchSeat item in instance.VirtualCouch)
{
if (item != null && !((Object)(object)item.actor == (Object)null) && item.actor.IsAlive && !((Object)(object)item.actor == (Object)(object)__instance.actor))
{
float num2 = Vector3.Distance(item.actor.Position, __instance.actor.Position);
if (num2 < num && num2 < 5f)
{
num = num2;
lastReviver = item.actor;
}
}
}
}
ChatModPlugin.lastReviver = lastReviver;
}
catch
{
}
}
}
[HarmonyPatch(typeof(Actor), "SpawnReset", new Type[]
{
typeof(Vector3),
typeof(Quaternion)
})]
internal static class Actor_SpawnReset_Patch
{
private static void Prefix(Actor __instance)
{
if ((Object)(object)__instance != (Object)null && __instance.IsPlayer)
{
ChatModPlugin.OnActorSpawnReset(__instance);
}
}
}
[HarmonyPatch(typeof(ConsoleCommands), "ToastRandomConvo")]
internal static class ConsoleCommands_ToastRandomConvo_Patch
{
private static void Postfix(string convoID)
{
if (convoID == "OneHitKillProtection" && ThirdPersonCameraControl.HasInstance && (Object)(object)ThirdPersonCameraControl.Instance.CharacterActor != (Object)null)
{
ChatModPlugin.OnOneHitProtection(ThirdPersonCameraControl.Instance.CharacterActor);
}
}
}