Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of TruckScreenDisplay v1.1.0
BepInEx\plugins\TruckScreenDisplay\TruckScreenDisplay.dll
Decompiled 6 days agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using ExitGames.Client.Photon; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using TMPro; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("TruckScreenDisplay")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("TruckScreenDisplay")] [assembly: AssemblyTitle("TruckScreenDisplay")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace TruckScreenDisplay { [BepInPlugin("repo.truck.screen.display", "Truck Screen Display", "1.1.0")] public sealed class Plugin : BaseUnityPlugin { [HarmonyPatch(typeof(TruckScreenText), "MessageSendCustomRPC")] private static class TruckScreenTextMessagePatch { private static bool Prefix(string playerName, string message) { if (message == null || !message.StartsWith("<size=0>[[TSD_SYNC_V1]]</size>", StringComparison.Ordinal)) { return true; } string text = message.Substring("<size=0>[[TSD_SYNC_V1]]</size>".Length); instance?.SetActiveMessage(playerName, text, resetVanillaBroadcast: false); return false; } } [HarmonyPatch(typeof(CameraAim), "Update")] private static class CameraAimPatch { private static bool Prefix() { return !IsEditorBlockingInput(); } } private const string PluginGuid = "repo.truck.screen.display"; private const string PluginName = "Truck Screen Display"; private const string PluginVersion = "1.1.0"; private const string SyncPrefix = "<size=0>[[TSD_SYNC_V1]]</size>"; private const string RoomMessageKey = "TSD_Message"; private const string RoomPlayerNameKey = "TSD_PlayerName"; private static Plugin instance; private ConfigEntry<KeyCode> toggleKey; private ConfigEntry<int> maxCharacters; private ConfigEntry<bool> sendAsPlayer; private ConfigEntry<bool> permanentDisplay; private ConfigEntry<bool> chineseUi; private ConfigEntry<bool> vanillaClientRebroadcast; private ConfigEntry<string> savedMessage; private ConfigEntry<string> savedPlayerName; private bool editorOpen; private string draftMessage = ""; private string activeMessage = ""; private string activePlayerName = ""; private Rect windowRect = new Rect(40f, 40f, 620f, 430f); private Vector2 scroll; private TruckScreenText lastBroadcastScreen; private TruckScreenText pendingVanillaBroadcastScreen; private int pendingVanillaBroadcastStep; private float nextVanillaBroadcastTime; private readonly float[] vanillaBroadcastDelays = new float[6] { 1f, 3f, 5f, 10f, 20f, 30f }; private bool savedCursorState; private bool previousCursorVisible; private CursorLockMode previousCursorLockState; private Harmony harmony; private void Awake() { //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Expected O, but got Unknown //IL_01b1: Unknown result type (might be due to invalid IL or missing references) instance = this; toggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Input", "ToggleKey", (KeyCode)278, "Open or close the truck screen text UI. Use Home or F1-F12."); maxCharacters = ((BaseUnityPlugin)this).Config.Bind<int>("Text", "MaxCharacters", 300, "Maximum characters allowed per message."); sendAsPlayer = ((BaseUnityPlugin)this).Config.Bind<bool>("Text", "SendAsPlayer", true, "Show the local player name before the message when possible."); permanentDisplay = ((BaseUnityPlugin)this).Config.Bind<bool>("Text", "PermanentDisplay", true, "Keep the last mod message permanently visible on the truck screen."); vanillaClientRebroadcast = ((BaseUnityPlugin)this).Config.Bind<bool>("Text", "VanillaClientRebroadcast", true, "Rebroadcast text through vanilla truck screen RPC so clients without this mod can see it after level transitions."); savedMessage = ((BaseUnityPlugin)this).Config.Bind<string>("Saved", "Message", "", "Last confirmed truck screen text. Restored on game restart."); savedPlayerName = ((BaseUnityPlugin)this).Config.Bind<string>("Saved", "PlayerName", "", "Player name used with the last confirmed truck screen text."); chineseUi = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "ChineseUi", false, "Use Chinese labels in the in-game UI."); if (!string.IsNullOrWhiteSpace(savedMessage.Value)) { activePlayerName = savedPlayerName.Value ?? ""; activeMessage = savedMessage.Value; draftMessage = savedMessage.Value; } harmony = new Harmony("repo.truck.screen.display"); harmony.PatchAll(typeof(Plugin).Assembly); ((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("{0} {1} loaded. Press {2} to open the UI.", "Truck Screen Display", "1.1.0", toggleKey.Value)); } private void OnDestroy() { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } if ((Object)(object)instance == (Object)(object)this) { instance = null; } } private void Update() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) if (Input.GetKeyDown(toggleKey.Value)) { SetEditorOpen(!editorOpen); return; } if (editorOpen) { BlockGameInputWhileEditing(); if (Input.GetKeyDown((KeyCode)27)) { SetEditorOpen(open: false); } } if (permanentDisplay.Value) { RestoreFromRoomProperties(); ApplyPermanentDisplay(); RebroadcastForVanillaClientsIfNeeded(); } } private void LateUpdate() { if (editorOpen) { ForceCursorForUi(); } } private void OnGUI() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) if (editorOpen) { ForceCursorForUi(); windowRect = GUI.Window(((Object)this).GetInstanceID(), windowRect, new WindowFunction(DrawWindow), T("Truck Screen Display UI", "卡车屏幕显示 UI")); } } private void DrawWindow(int windowId) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_029b: Unknown result type (might be due to invalid IL or missing references) //IL_02e1: Unknown result type (might be due to invalid IL or missing references) //IL_031f: Unknown result type (might be due to invalid IL or missing references) //IL_0337: Unknown result type (might be due to invalid IL or missing references) //IL_033c: Unknown result type (might be due to invalid IL or missing references) //IL_049b: Unknown result type (might be due to invalid IL or missing references) GUILayout.Label(T("Truck screen text UI", "卡车屏幕文字 UI"), Array.Empty<GUILayoutOption>()); GUILayout.Label(string.Format(T("Open key: {0} Esc: close", "打开键: {0} Esc: 关闭"), toggleKey.Value), Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (GUILayout.Button(T("CONFIRM DISPLAY", "确认显示"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(42f) })) { ConfirmAndSyncMessage(); } if (GUILayout.Button(T("CLOSE UI", "关闭 UI"), (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Height(42f), GUILayout.Width(160f) })) { SetEditorOpen(open: false); } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (GUILayout.Button(chineseUi.Value ? "English" : "中文", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(26f) })) { chineseUi.Value = !chineseUi.Value; ((BaseUnityPlugin)this).Config.Save(); } if (GUILayout.Toggle(permanentDisplay.Value, T("Permanent display", "永久显示"), Array.Empty<GUILayoutOption>()) != permanentDisplay.Value) { permanentDisplay.Value = !permanentDisplay.Value; ((BaseUnityPlugin)this).Config.Save(); } if (GUILayout.Toggle(sendAsPlayer.Value, T("Show player name", "显示玩家名"), Array.Empty<GUILayoutOption>()) != sendAsPlayer.Value) { sendAsPlayer.Value = !sendAsPlayer.Value; ((BaseUnityPlugin)this).Config.Save(); } if (GUILayout.Toggle(vanillaClientRebroadcast.Value, T("Vanilla clients", "原版客机"), Array.Empty<GUILayoutOption>()) != vanillaClientRebroadcast.Value) { vanillaClientRebroadcast.Value = !vanillaClientRebroadcast.Value; ((BaseUnityPlugin)this).Config.Save(); } GUILayout.EndHorizontal(); GUILayout.Space(4f); GUILayout.Label(T("Shortcut", "快捷键"), Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); DrawShortcutButton((KeyCode)278); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); for (int i = 1; i <= 6; i++) { DrawShortcutButton((KeyCode)Enum.Parse(typeof(KeyCode), "F" + i)); } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); for (int j = 7; j <= 12; j++) { DrawShortcutButton((KeyCode)Enum.Parse(typeof(KeyCode), "F" + j)); } GUILayout.EndHorizontal(); GUILayout.Space(4f); GUILayout.Label(T("Text. English and Chinese input are supported.", "文本。支持英文和中文输入。"), Array.Empty<GUILayoutOption>()); scroll = GUILayout.BeginScrollView(scroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(120f) }); GUI.SetNextControlName("TruckScreenDisplayTextArea"); string text = GUILayout.TextArea(draftMessage, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandHeight(true) }); draftMessage = ((text.Length <= maxCharacters.Value) ? text : text.Substring(0, maxCharacters.Value)); GUILayout.EndScrollView(); GUILayout.Label($"{draftMessage.Length}/{maxCharacters.Value}", Array.Empty<GUILayoutOption>()); GUILayout.Label(T("Press Confirm to display the current text.", "点击确认显示当前文本。"), Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (GUILayout.Button(T("Confirm display", "确认显示"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(36f) })) { ConfirmAndSyncMessage(); } if (GUILayout.Button(T("Clear screen", "清除屏幕"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(32f) })) { ClearAndSyncMessage(); } if (GUILayout.Button(T("Close", "关闭"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(32f) })) { SetEditorOpen(open: false); } GUILayout.EndHorizontal(); GUI.DragWindow(new Rect(0f, 0f, 10000f, 24f)); GUI.FocusControl("TruckScreenDisplayTextArea"); } private unsafe void DrawShortcutButton(KeyCode key) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) bool num = toggleKey.Value == key; GUI.enabled = !num; if (GUILayout.Button(num ? $"[{key}]" : ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString(), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(26f) })) { toggleKey.Value = key; ((BaseUnityPlugin)this).Config.Save(); } GUI.enabled = true; } private void ConfirmAndSyncMessage() { string text = draftMessage.Trim(); if (text.Length == 0) { ClearAndSyncMessage(); return; } string playerName = (sendAsPlayer.Value ? TryGetLocalPlayerName() : ""); ConfirmAndSyncText(playerName, text); } private void ConfirmAndSyncText(string playerName, string text) { ConfirmAndSyncText(playerName, text, resetVanillaBroadcast: true); } private void ConfirmAndSyncText(string playerName, string text, bool resetVanillaBroadcast) { if (!string.IsNullOrWhiteSpace(text)) { SetActiveMessage(playerName, text, resetVanillaBroadcast); SaveLocalText(playerName, text); SaveRoomProperties(playerName, text); BroadcastSync(playerName, text); if (resetVanillaBroadcast) { lastBroadcastScreen = TruckScreenText.instance; } } } private void ClearAndSyncMessage() { SetActiveMessage("", "", resetVanillaBroadcast: true); SaveLocalText("", ""); SaveRoomProperties("", ""); BroadcastSync("", ""); lastBroadcastScreen = null; } private void BroadcastSync(string playerName, string text) { if ((Object)(object)TruckScreenText.instance == (Object)null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"TruckScreenText.instance was not found. Enter a level/truck scene before sending text."); } else { TruckScreenText.instance.MessageSendCustom(playerName, "<size=0>[[TSD_SYNC_V1]]</size>" + text, 0); } } private void SetActiveMessage(string playerName, string text, bool resetVanillaBroadcast) { activePlayerName = playerName ?? ""; activeMessage = text ?? ""; if (resetVanillaBroadcast) { lastBroadcastScreen = null; } ApplyPermanentDisplay(); } private void RebroadcastForVanillaClientsIfNeeded() { if (!vanillaClientRebroadcast.Value || string.IsNullOrWhiteSpace(activeMessage) || (Object)(object)TruckScreenText.instance == (Object)null) { return; } if ((Object)(object)lastBroadcastScreen != (Object)(object)TruckScreenText.instance) { lastBroadcastScreen = TruckScreenText.instance; pendingVanillaBroadcastScreen = TruckScreenText.instance; pendingVanillaBroadcastStep = 0; nextVanillaBroadcastTime = Time.time + vanillaBroadcastDelays[0]; } else if (!((Object)(object)pendingVanillaBroadcastScreen != (Object)(object)TruckScreenText.instance) && pendingVanillaBroadcastStep >= 0 && !(Time.time < nextVanillaBroadcastTime)) { ConfirmAndSyncText(TryGetLocalPlayerName(), activeMessage, resetVanillaBroadcast: false); BroadcastVanilla("", activeMessage); pendingVanillaBroadcastStep++; if (pendingVanillaBroadcastStep < vanillaBroadcastDelays.Length) { nextVanillaBroadcastTime = Time.time + (vanillaBroadcastDelays[pendingVanillaBroadcastStep] - vanillaBroadcastDelays[pendingVanillaBroadcastStep - 1]); return; } pendingVanillaBroadcastStep = -1; pendingVanillaBroadcastScreen = null; } } private void BroadcastVanilla(string playerName, string text) { if (!((Object)(object)TruckScreenText.instance == (Object)null)) { TruckScreenText.instance.MessageSendCustom(playerName ?? "", text ?? "", 0); } } private void SaveRoomProperties(string playerName, string text) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown if (PhotonNetwork.InRoom && PhotonNetwork.CurrentRoom != null) { Hashtable val = new Hashtable { [(object)"TSD_PlayerName"] = playerName ?? "", [(object)"TSD_Message"] = text ?? "" }; PhotonNetwork.CurrentRoom.SetCustomProperties(val, (Hashtable)null, (WebFlags)null); } } private void SaveLocalText(string playerName, string text) { savedPlayerName.Value = playerName ?? ""; savedMessage.Value = text ?? ""; ((BaseUnityPlugin)this).Config.Save(); } private void RestoreFromRoomProperties() { if (!string.IsNullOrWhiteSpace(activeMessage) || !PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null || !((Dictionary<object, object>)(object)((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties).TryGetValue((object)"TSD_Message", out object value)) { return; } string text = value as string; if (!string.IsNullOrWhiteSpace(text)) { string playerName = ""; if (((Dictionary<object, object>)(object)((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties).TryGetValue((object)"TSD_PlayerName", out object value2)) { playerName = (value2 as string) ?? ""; } SetActiveMessage(playerName, text, resetVanillaBroadcast: true); } } private void ApplyPermanentDisplay() { if (!((Object)(object)TruckScreenText.instance == (Object)null) && !((Object)(object)TruckScreenText.instance.textMesh == (Object)null) && !string.IsNullOrWhiteSpace(activeMessage)) { string text = (string.IsNullOrWhiteSpace(activePlayerName) ? activeMessage : ("<b>" + activePlayerName + ":</b>\n" + activeMessage)); ((TMP_Text)TruckScreenText.instance.textMesh).text = SemiFunc.EmojiText(text); } } private void SetEditorOpen(bool open) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) if (open && !editorOpen) { previousCursorVisible = Cursor.visible; previousCursorLockState = Cursor.lockState; savedCursorState = true; } editorOpen = open; Input.imeCompositionMode = (IMECompositionMode)(open ? 1 : 0); if (open) { ForceCursorForUi(); } else if (savedCursorState) { Cursor.visible = previousCursorVisible; Cursor.lockState = previousCursorLockState; savedCursorState = false; } } private void ForceCursorForUi() { Cursor.visible = true; Cursor.lockState = (CursorLockMode)0; } private void BlockGameInputWhileEditing() { MenuManager obj = MenuManager.instance; if (obj != null) { obj.TextInputActive(); } GameDirector obj2 = GameDirector.instance; if (obj2 != null) { obj2.SetDisableInput(0.1f); } PlayerController obj3 = PlayerController.instance; if (obj3 != null) { obj3.InputDisable(0.1f); } if ((Object)(object)InputManager.instance != (Object)null) { SemiFunc.InputDisableMovement(); SemiFunc.InputDisableAiming(); } } private static bool IsEditorBlockingInput() { if ((Object)(object)instance != (Object)null) { return instance.editorOpen; } return false; } private string T(string english, string chinese) { if (!chineseUi.Value) { return english; } return chinese; } private static string TryGetLocalPlayerName() { try { Type typeFromHandle = typeof(PlayerController); object obj = typeFromHandle.GetField("instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null); if (obj == null) { return ""; } return (typeFromHandle.GetField("playerName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj) as string) ?? ""; } catch (Exception) { return ""; } } } }