using 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("[[TSD_SYNC_V1]]", StringComparison.Ordinal))
{
return true;
}
string text = message.Substring("[[TSD_SYNC_V1]]".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 = "[[TSD_SYNC_V1]]";
private const string RoomMessageKey = "TSD_Message";
private const string RoomPlayerNameKey = "TSD_PlayerName";
private static Plugin instance;
private ConfigEntry toggleKey;
private ConfigEntry maxCharacters;
private ConfigEntry sendAsPlayer;
private ConfigEntry permanentDisplay;
private ConfigEntry chineseUi;
private ConfigEntry vanillaClientRebroadcast;
private ConfigEntry savedMessage;
private ConfigEntry 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("Input", "ToggleKey", (KeyCode)278, "Open or close the truck screen text UI. Use Home or F1-F12.");
maxCharacters = ((BaseUnityPlugin)this).Config.Bind("Text", "MaxCharacters", 300, "Maximum characters allowed per message.");
sendAsPlayer = ((BaseUnityPlugin)this).Config.Bind("Text", "SendAsPlayer", true, "Show the local player name before the message when possible.");
permanentDisplay = ((BaseUnityPlugin)this).Config.Bind("Text", "PermanentDisplay", true, "Keep the last mod message permanently visible on the truck screen.");
vanillaClientRebroadcast = ((BaseUnityPlugin)this).Config.Bind("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("Saved", "Message", "", "Last confirmed truck screen text. Restored on game restart.");
savedPlayerName = ((BaseUnityPlugin)this).Config.Bind("Saved", "PlayerName", "", "Player name used with the last confirmed truck screen text.");
chineseUi = ((BaseUnityPlugin)this).Config.Bind("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());
GUILayout.Label(string.Format(T("Open key: {0} Esc: close", "打开键: {0} Esc: 关闭"), toggleKey.Value), Array.Empty());
GUILayout.BeginHorizontal(Array.Empty());
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());
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()) != permanentDisplay.Value)
{
permanentDisplay.Value = !permanentDisplay.Value;
((BaseUnityPlugin)this).Config.Save();
}
if (GUILayout.Toggle(sendAsPlayer.Value, T("Show player name", "显示玩家名"), Array.Empty()) != sendAsPlayer.Value)
{
sendAsPlayer.Value = !sendAsPlayer.Value;
((BaseUnityPlugin)this).Config.Save();
}
if (GUILayout.Toggle(vanillaClientRebroadcast.Value, T("Vanilla clients", "原版客机"), Array.Empty()) != vanillaClientRebroadcast.Value)
{
vanillaClientRebroadcast.Value = !vanillaClientRebroadcast.Value;
((BaseUnityPlugin)this).Config.Save();
}
GUILayout.EndHorizontal();
GUILayout.Space(4f);
GUILayout.Label(T("Shortcut", "快捷键"), Array.Empty());
GUILayout.BeginHorizontal(Array.Empty());
DrawShortcutButton((KeyCode)278);
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal(Array.Empty());
for (int i = 1; i <= 6; i++)
{
DrawShortcutButton((KeyCode)Enum.Parse(typeof(KeyCode), "F" + i));
}
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal(Array.Empty());
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());
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());
GUILayout.Label(T("Press Confirm to display the current text.", "点击确认显示当前文本。"), Array.Empty());
GUILayout.BeginHorizontal(Array.Empty());
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, "[[TSD_SYNC_V1]]" + 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