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 SpectatorMode v1.0.0
SpectatorMode.dll
Decompiled 16 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using Unity.Collections; using Unity.Netcode; using UnityEngine; using UnityEngine.AI; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.InputSystem.LowLevel; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("SpectatorMode")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("SpectatorMode")] [assembly: AssemblyTitle("SpectatorMode")] [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 SpectatorMode { internal class AutoTestDriver : MonoBehaviour { private readonly List<string> errors = new List<string>(); private string dir; private string logFile; private void Log(string s) { Plugin.Log.LogInfo((object)("[AutoTest] " + s)); try { File.AppendAllText(logFile, s + Environment.NewLine); } catch { } } private void OnEnable() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown Application.logMessageReceived += new LogCallback(OnLog); } private void OnDisable() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown Application.logMessageReceived -= new LogCallback(OnLog); } private void OnLog(string m, string st, LogType t) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_0004: Unknown result type (might be due to invalid IL or missing references) if ((int)t == 4 || (int)t == 0) { errors.Add(m.Split('\n')[0] + " @ " + (st ?? "").Split('\n')[0]); } } private void Check(bool ok, string what) { Log((ok ? "OK : " : "ÉCHEC : ") + what); if (!ok) { errors.Add("check: " + what); } } private IEnumerator Start() { dir = Path.Combine(Paths.ConfigPath, "SpectatorMode", "autotest"); Directory.CreateDirectory(dir); string[] files = Directory.GetFiles(dir); for (int i = 0; i < files.Length; i++) { File.Delete(files[i]); } logFile = Path.Combine(dir, "log.txt"); Log("Démarrage du test automatique."); yield return WaitFor(() => (Object)(object)Object.FindObjectOfType<PreInitSceneScript>() != (Object)null || (Object)(object)MainMenu() != (Object)null, 90f); PreInitSceneScript pre = Object.FindObjectOfType<PreInitSceneScript>(); if ((Object)(object)pre != (Object)null) { yield return (object)new WaitForSeconds(2f); pre.ChooseLaunchOption(false); } MenuManager menu = null; yield return WaitFor(() => (Object)(object)(menu = MainMenu()) != (Object)null, 120f); if ((Object)(object)menu == (Object)null) { Finish("menu introuvable"); yield break; } yield return (object)new WaitForSeconds(3f); GameNetworkManager.Instance.currentSaveFileName = "LCSpectatorAutoTest"; menu.ClickHostButton(); yield return (object)new WaitForSeconds(1f); menu.lobbyNameInputField.text = "SpectatorAutoTest"; menu.ConfirmHostButton(); yield return WaitFor(() => (Object)(object)StartOfRound.Instance != (Object)null && (Object)(object)StartOfRound.Instance.localPlayerController != (Object)null && StartOfRound.Instance.inShipPhase && StartOfRound.Instance.fullyLoadedPlayers.Count > 0, 120f); StartOfRound sor = StartOfRound.Instance; if ((Object)(object)sor == (Object)null) { Finish("partie non chargée"); yield break; } yield return (object)new WaitForSeconds(4f); if (sor.currentLevelID != 0) { sor.ChangeLevel(0); sor.ArriveAtLevel(); yield return (object)new WaitForSeconds(2f); } sor.currentLevel.currentWeather = (LevelWeatherType)(-1); StartMatchLever obj = Object.FindObjectOfType<StartMatchLever>(); obj.singlePlayerEnabled = true; obj.leverHasBeenPulled = true; obj.StartGame(); yield return WaitFor(() => sor.shipHasLanded && RoundManager.Instance.dungeonCompletedGenerating, 240f); if (!sor.shipHasLanded) { Finish("pas d'atterrissage"); yield break; } yield return (object)new WaitForSeconds(3f); PlayerControllerB me = sor.localPlayerController; int idx = (int)me.playerClientId; Vector3 bodyPos = ((Component)me).transform.position; yield return PressKey(Settings.ToggleKey.Value); yield return (object)new WaitForSeconds(1f); Camera cam = sor.freeCinematicCamera; Check(Spectator.Active && Net.IsSpectator(idx), "touche F6 : mode spectateur activé"); Check((Object)(object)sor.activeCamera == (Object)(object)cam && ((Behaviour)cam).enabled && !((Behaviour)me.gameplayCamera).enabled, "caméra libre active, caméra du joueur coupée"); Check((Object)(object)sor.audioListener != (Object)null && (Object)(object)((Component)sor.audioListener).transform.parent == (Object)(object)((Component)cam).transform, "le son suit la caméra libre"); Check(!((Renderer)me.thisPlayerModel).enabled, "corps caché"); Check(HUDManager.Instance.hudHidden, "interface du jeu cachée"); yield return Capture("01_entree"); Vector3 p0 = ((Component)cam).transform.position; yield return HoldKey((Key)37, 1f); Vector3 p1 = ((Component)cam).transform.position; Check(Vector3.Distance(p0, p1) > 5f, $"vol avec W : {Vector3.Distance(p0, p1):0.0} m"); Check(Vector3.Distance(((Component)me).transform.position, bodyPos) < 0.5f, "le corps n'a pas bougé"); yield return HoldKey((Key)1, 1f); Check(((Component)cam).transform.position.y - p1.y > 5f, $"monter avec Espace : +{((Component)cam).transform.position.y - p1.y:0.0} m"); ((Component)cam).transform.position = sor.middleOfShipNode.position + Vector3.up * 1f; yield return (object)new WaitForSeconds(0.3f); yield return Capture("02_dans_le_vaisseau"); SetCam(cam, sor.elevatorTransform.position + new Vector3(-25f, 30f, -25f), sor.elevatorTransform.position); yield return (object)new WaitForSeconds(0.5f); yield return Capture("03_vue_aerienne"); yield return PressKey(Settings.LightKey.Value); Light val = ((IEnumerable<Light>)((Component)cam).GetComponentsInChildren<Light>(true)).FirstOrDefault((Func<Light, bool>)((Light l) => ((Object)l).name == "SpectatorLight")); Check((Object)(object)val != (Object)null && ((Component)val).gameObject.activeInHierarchy, "touche L : lumière allumée"); int hp = me.health; me.DamagePlayer(60, true, true, (CauseOfDeath)1, 0, false, default(Vector3)); yield return (object)new WaitForSeconds(0.3f); Check(me.health == hp && !me.isPlayerDead, $"invulnérable ({me.health} PV)"); Vector3 val2 = sor.elevatorTransform.position + new Vector3(-20f, 3f, 0f); SetCam(cam, val2, val2 + Vector3.forward); Check(Spectator.TryFindSpot(((Component)cam).transform.position, out var spot), $"endroit libre trouvé sous la caméra ({spot})"); yield return PressKey(Settings.ToggleKey.Value); yield return (object)new WaitForSeconds(1f); Check(!Spectator.Active && !Net.IsSpectator(idx), "touche F6 : sortie du mode spectateur"); Check(Vector3.Distance(((Component)me).transform.position, spot) < 1.5f, $"réapparition sur place ({((Component)me).transform.position})"); Check((Object)(object)sor.activeCamera == (Object)(object)me.gameplayCamera && ((Behaviour)me.gameplayCamera).enabled && !((Behaviour)cam).enabled, "caméra du joueur rendue"); Check(!HUDManager.Instance.hudHidden, "interface du jeu rendue"); Check(!me.disableMoveInput && !me.disableLookInput && !me.disableInteract, "contrôles rendus"); yield return Capture("04_sortie"); Vector3 body2 = ((Component)me).transform.position; yield return PressKey(Settings.ToggleKey.Value); yield return (object)new WaitForSeconds(0.8f); SetCam(cam, new Vector3(0f, 400f, 0f), Vector3.zero); yield return PressKey(Settings.ToggleKey.Value); yield return (object)new WaitForSeconds(0.8f); Check(!Spectator.Active && Vector3.Distance(((Component)me).transform.position, body2) < 1f, "endroit impossible : retour au corps"); Finish(null); } private static void SetCam(Camera cam, Vector3 pos, Vector3 look) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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_0028: 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) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) ((Component)cam).transform.position = pos; Vector3 val = look - pos; Quaternion val2 = Quaternion.LookRotation(((Vector3)(ref val)).normalized); Vector3 eulerAngles = ((Quaternion)(ref val2)).eulerAngles; FieldInfo field = typeof(Spectator).GetField("_yaw", BindingFlags.Static | BindingFlags.NonPublic); FieldInfo? field2 = typeof(Spectator).GetField("_pitch", BindingFlags.Static | BindingFlags.NonPublic); field.SetValue(null, eulerAngles.y); field2.SetValue(null, (eulerAngles.x > 180f) ? (eulerAngles.x - 360f) : eulerAngles.x); } private static IEnumerator PressKey(Key key) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) Keyboard kb = Keyboard.current; InputSystem.QueueStateEvent<KeyboardState>((InputDevice)(object)kb, new KeyboardState((Key[])(object)new Key[1] { (Key)(int)key }), -1.0); yield return null; yield return null; InputSystem.QueueStateEvent<KeyboardState>((InputDevice)(object)kb, default(KeyboardState), -1.0); yield return null; } private static IEnumerator HoldKey(Key key, float seconds) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) Keyboard kb = Keyboard.current; float t = 0f; while (t < seconds) { InputSystem.QueueStateEvent<KeyboardState>((InputDevice)(object)kb, new KeyboardState((Key[])(object)new Key[1] { (Key)(int)key }), -1.0); t += Time.unscaledDeltaTime; yield return null; } InputSystem.QueueStateEvent<KeyboardState>((InputDevice)(object)kb, default(KeyboardState), -1.0); yield return null; } private void Finish(string fail) { if (fail != null) { Log("ÉCHEC : " + fail); } Log("===== RÉSUMÉ ====="); Log((errors.Count == 0 && fail == null) ? "Aucune erreur." : string.Format("{0} erreur(s) : {1}", errors.Count, string.Join(" | ", errors.Distinct().Take(20)))); Application.Quit(); } private IEnumerator Capture(string name) { yield return (object)new WaitForEndOfFrame(); ScreenCapture.CaptureScreenshot(Path.Combine(dir, name + ".png")); Log("Capture : " + name); yield return (object)new WaitForSeconds(0.4f); } private static MenuManager MainMenu() { return ((IEnumerable<MenuManager>)Object.FindObjectsOfType<MenuManager>()).FirstOrDefault((Func<MenuManager, bool>)((MenuManager m) => !m.isInitScene && (Object)(object)m.lobbyNameInputField != (Object)null)); } private static IEnumerator WaitFor(Func<bool> cond, float timeout) { float t = 0f; while (t < timeout) { bool flag = false; try { flag = cond(); } catch { } if (flag) { break; } t += 0.25f; yield return (object)new WaitForSeconds(0.25f); } } } internal static class Net { [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnRequest; public static HandleNamedMessageDelegate <1>__OnRequestSync; public static HandleNamedMessageDelegate <2>__OnState; public static HandleNamedMessageDelegate <3>__OnConfig; public static HandleNamedMessageDelegate <4>__OnDenied; } private const string P = "SpectatorMode_"; private const string MsgRequest = "SpectatorMode_Request"; private const string MsgRequestSync = "SpectatorMode_Sync"; private const string MsgState = "SpectatorMode_State"; private const string MsgConfig = "SpectatorMode_Config"; private const string MsgDenied = "SpectatorMode_Denied"; public static readonly HashSet<int> Spectators = new HashSet<int>(); private static CustomMessagingManager _registeredOn; private static NetworkManager NM => NetworkManager.Singleton; public static bool IsServer { get { if ((Object)(object)NM != (Object)null) { return NM.IsServer; } return false; } } public static int LocalIndex { get { StartOfRound instance = StartOfRound.Instance; if (!((Object)(object)instance != (Object)null) || !((Object)(object)instance.localPlayerController != (Object)null)) { return -1; } return (int)instance.localPlayerController.playerClientId; } } public static void EnsureRegistered() { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Expected O, but got Unknown //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Expected O, but got Unknown //IL_0101: 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_010c: Expected O, but got Unknown if (!((Object)(object)NM == (Object)null) && NM.CustomMessagingManager != null && _registeredOn != NM.CustomMessagingManager) { _registeredOn = NM.CustomMessagingManager; Spectators.Clear(); Settings.ClearHostValues(); CustomMessagingManager customMessagingManager = NM.CustomMessagingManager; object obj = <>O.<0>__OnRequest; if (obj == null) { HandleNamedMessageDelegate val = OnRequest; <>O.<0>__OnRequest = val; obj = (object)val; } customMessagingManager.RegisterNamedMessageHandler("SpectatorMode_Request", (HandleNamedMessageDelegate)obj); object obj2 = <>O.<1>__OnRequestSync; if (obj2 == null) { HandleNamedMessageDelegate val2 = OnRequestSync; <>O.<1>__OnRequestSync = val2; obj2 = (object)val2; } customMessagingManager.RegisterNamedMessageHandler("SpectatorMode_Sync", (HandleNamedMessageDelegate)obj2); object obj3 = <>O.<2>__OnState; if (obj3 == null) { HandleNamedMessageDelegate val3 = OnState; <>O.<2>__OnState = val3; obj3 = (object)val3; } customMessagingManager.RegisterNamedMessageHandler("SpectatorMode_State", (HandleNamedMessageDelegate)obj3); object obj4 = <>O.<3>__OnConfig; if (obj4 == null) { HandleNamedMessageDelegate val4 = OnConfig; <>O.<3>__OnConfig = val4; obj4 = (object)val4; } customMessagingManager.RegisterNamedMessageHandler("SpectatorMode_Config", (HandleNamedMessageDelegate)obj4); object obj5 = <>O.<4>__OnDenied; if (obj5 == null) { HandleNamedMessageDelegate val5 = OnDenied; <>O.<4>__OnDenied = val5; obj5 = (object)val5; } customMessagingManager.RegisterNamedMessageHandler("SpectatorMode_Denied", (HandleNamedMessageDelegate)obj5); } } public static bool IsSpectator(int idx) { return Spectators.Contains(idx); } public static bool IsSpectator(PlayerControllerB p) { if ((Object)(object)p != (Object)null) { return Spectators.Contains((int)p.playerClientId); } return false; } public static void RequestSpectator(bool on) { int localIndex = LocalIndex; if (localIndex < 0) { return; } if (IsServer) { ServerSet(localIndex, on, 0uL); return; } SendTo(0uL, "SpectatorMode_Request", 8, delegate(FastBufferWriter w) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) ((FastBufferWriter)(ref w)).WriteValueSafe<bool>(ref on, default(ForPrimitives)); }); } public static void RequestSync() { if (!IsServer) { SendTo(0uL, "SpectatorMode_Sync", 8, delegate { }); } } public static string Refusal(int idx) { StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance == (Object)null || idx < 0 || idx >= instance.allPlayerScripts.Length) { return "joueur inconnu"; } switch ((Who)Settings.AllowedWho.Value) { case Who.HoteSeulement: if (idx != 0) { return "Seul l'hôte peut passer en spectateur."; } return null; case Who.MortsSeulement: if (!instance.allPlayerScripts[idx].isPlayerDead) { return "Seuls les joueurs morts peuvent passer en spectateur."; } return null; default: return null; } } private static void ServerSet(int idx, bool on, ulong requester) { if (on) { string text = Refusal(idx); if (text != null) { Deny(requester, text); return; } if (!Spectators.Add(idx)) { return; } } else if (!Spectators.Remove(idx)) { return; } Spectator.OnStateChanged(); BroadcastState(); } public static void ServerForget(int idx) { if (Spectators.Remove(idx)) { Spectator.OnStateChanged(); BroadcastState(); } } public static void BroadcastState() { if (!IsServer) { return; } foreach (ulong connectedClientsId in NM.ConnectedClientsIds) { if (connectedClientsId != 0L) { SendState(connectedClientsId); } } } public static void BroadcastConfig() { if (!IsServer || _registeredOn == null) { return; } foreach (ulong connectedClientsId in NM.ConnectedClientsIds) { if (connectedClientsId != 0L) { SendConfig(connectedClientsId); } } } private static void SendState(ulong clientId) { List<int> list = new List<int>(Spectators); SendTo(clientId, "SpectatorMode_State", 8 + list.Count * 4, delegate(FastBufferWriter w) { //IL_0012: 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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) int count = list.Count; ((FastBufferWriter)(ref w)).WriteValueSafe<int>(ref count, default(ForPrimitives)); foreach (int item in list) { int current = item; ((FastBufferWriter)(ref w)).WriteValueSafe<int>(ref current, default(ForPrimitives)); } }); } private static void SendConfig(ulong clientId) { SendTo(clientId, "SpectatorMode_Config", 8 + Settings.All.Count * 4, delegate(FastBufferWriter w) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) int count = Settings.All.Count; ((FastBufferWriter)(ref w)).WriteValueSafe<int>(ref count, default(ForPrimitives)); foreach (ISynced item in Settings.All) { float local = item.Local; ((FastBufferWriter)(ref w)).WriteValueSafe<float>(ref local, default(ForPrimitives)); } }); } private static void Deny(ulong clientId, string why) { if (clientId == 0L) { Spectator.OnDenied(why); return; } SendTo(clientId, "SpectatorMode_Denied", 64 + why.Length * 4, delegate(FastBufferWriter w) { ((FastBufferWriter)(ref w)).WriteValueSafe(why, false); }); } private static void OnRequest(ulong sender, FastBufferReader r) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (IsServer) { bool flag = default(bool); ((FastBufferReader)(ref r)).ReadValueSafe<bool>(ref flag, default(ForPrimitives)); int num = PlayerIndexOf(sender); if (num >= 0) { ServerSet(num, flag, sender); } } } private static void OnRequestSync(ulong sender, FastBufferReader r) { if (IsServer) { SendConfig(sender); SendState(sender); } } private static void OnState(ulong sender, FastBufferReader r) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) if (!IsServer) { int num = default(int); ((FastBufferReader)(ref r)).ReadValueSafe<int>(ref num, default(ForPrimitives)); Spectators.Clear(); int item = default(int); for (int i = 0; i < num; i++) { ((FastBufferReader)(ref r)).ReadValueSafe<int>(ref item, default(ForPrimitives)); Spectators.Add(item); } Spectator.OnStateChanged(); } } private static void OnConfig(ulong sender, FastBufferReader r) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) if (IsServer) { return; } int num = default(int); ((FastBufferReader)(ref r)).ReadValueSafe<int>(ref num, default(ForPrimitives)); float host = default(float); for (int i = 0; i < num; i++) { ((FastBufferReader)(ref r)).ReadValueSafe<float>(ref host, default(ForPrimitives)); if (i < Settings.All.Count) { Settings.All[i].SetHost(host); } } } private static void OnDenied(ulong sender, FastBufferReader r) { string why = default(string); ((FastBufferReader)(ref r)).ReadValueSafe(ref why, false); Spectator.OnDenied(why); } private static int PlayerIndexOf(ulong clientId) { StartOfRound instance = StartOfRound.Instance; if (!((Object)(object)instance != (Object)null) || !instance.ClientPlayerList.TryGetValue(clientId, out var value)) { return -1; } return value; } private unsafe static void SendTo(ulong clientId, string name, int size, Action<FastBufferWriter> write) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)NM == (Object)null || NM.CustomMessagingManager == null) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(Math.Max(size, 64), (Allocator)2, 8000); try { write(val); NM.CustomMessagingManager.SendNamedMessage(name, clientId, val, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } } [BepInPlugin("emeric.spectatormode", "SpectatorMode", "1.0.0")] public class Plugin : BaseUnityPlugin { public const string Guid = "emeric.spectatormode"; public const string Name = "SpectatorMode"; public const string Version = "1.0.0"; internal static ManualLogSource Log; private void Awake() { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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_0062: Expected O, but got Unknown //IL_009b: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; Settings.Init(((BaseUnityPlugin)this).Config); ((BaseUnityPlugin)this).Config.SettingChanged += delegate { Net.BroadcastConfig(); }; new Harmony("emeric.spectatormode").PatchAll(); GameObject val = new GameObject("SpectatorModeRunner") { hideFlags = (HideFlags)61 }; Object.DontDestroyOnLoad((Object)(object)val); val.AddComponent<Runner>(); if (Settings.AutoTest.Value) { val.AddComponent<AutoTestDriver>(); } Log.LogInfo((object)string.Format("{0} {1} chargé. [{2}] pour passer en spectateur.", "SpectatorMode", "1.0.0", Settings.ToggleKey.Value)); } } internal class Runner : MonoBehaviour { private float _inGameSince = -1f; private bool _autoDone; private void LateUpdate() { //IL_00f5: Unknown result type (might be due to invalid IL or missing references) try { NetworkManager singleton = NetworkManager.Singleton; StartOfRound instance = StartOfRound.Instance; if ((Object)(object)singleton == (Object)null || !singleton.IsListening || (Object)(object)instance == (Object)null || (Object)(object)instance.localPlayerController == (Object)null || !instance.localPlayerController.isPlayerControlled) { _inGameSince = -1f; _autoDone = false; return; } PlayerControllerB localPlayerController = instance.localPlayerController; if (_inGameSince < 0f) { _inGameSince = Time.unscaledTime; } if (!_autoDone && Settings.StartAsSpectator.Value && Time.unscaledTime - _inGameSince > 3f) { _autoDone = true; if (!Spectator.Active) { Spectator.Toggle(); } } Keyboard current = Keyboard.current; bool flag = localPlayerController.isTypingChat || localPlayerController.inTerminalMenu || ((Object)(object)localPlayerController.quickMenuManager != (Object)null && localPlayerController.quickMenuManager.isMenuOpen); if (current != null && !flag && ((ButtonControl)current[Settings.ToggleKey.Value]).wasPressedThisFrame) { Spectator.Toggle(); } Spectator.Tick(); } catch (Exception ex) { Plugin.Log.LogError((object)("SpectatorMode : " + ex)); } } } [HarmonyPatch] internal static class Patches { private static bool LocalSpectating(PlayerControllerB p) { if (Spectator.Active) { return (Object)(object)p == (Object)(object)StartOfRound.Instance?.localPlayerController; } return false; } [HarmonyPatch(typeof(StartOfRound), "Start")] [HarmonyPostfix] private static void SorStart() { Net.EnsureRegistered(); } [HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] [HarmonyPostfix] private static void Connect() { Net.EnsureRegistered(); Net.RequestSync(); } [HarmonyPatch(typeof(StartOfRound), "OnPlayerDC")] [HarmonyPostfix] private static void PlayerLeft(int playerObjectNumber) { if (Net.IsServer) { Net.ServerForget(playerObjectNumber); } } [HarmonyPatch(typeof(StartOfRound), "OnLocalDisconnect")] [HarmonyPrefix] private static void LocalDisconnect() { Spectator.ForceReset(); Visibility.ShowAll(); Net.Spectators.Clear(); } [HarmonyPatch(typeof(ElevatorAnimationEvents), "ElevatorFullyRunning")] [HarmonyPrefix] private static void ShipLeaving() { PlayerControllerB val = StartOfRound.Instance?.localPlayerController; if (!((Object)(object)val == (Object)null) && Spectator.Active) { Spectator.Exit(val, teleport: false); Net.RequestSpectator(on: false); if (!val.isPlayerDead) { val.isInElevator = true; val.isInHangarShipRoom = false; } } } [HarmonyPatch(typeof(StartOfRound), "ReviveDeadPlayers")] [HarmonyPrefix] private static void NewDay() { PlayerControllerB val = StartOfRound.Instance?.localPlayerController; if (!((Object)(object)val == (Object)null) && Spectator.Active) { Spectator.Exit(val, teleport: false); Net.RequestSpectator(on: false); } } [HarmonyPatch(typeof(PlayerControllerB), "Jump_performed")] [HarmonyPrefix] private static bool Jump(PlayerControllerB __instance) { return !LocalSpectating(__instance); } [HarmonyPatch(typeof(PlayerControllerB), "Crouch_performed")] [HarmonyPrefix] private static bool Crouch(PlayerControllerB __instance) { return !LocalSpectating(__instance); } [HarmonyPatch(typeof(PlayerControllerB), "ScrollMouse_performed")] [HarmonyPrefix] private static bool Scroll(PlayerControllerB __instance) { return !LocalSpectating(__instance); } [HarmonyPatch(typeof(PlayerControllerB), "ActivateItem_performed")] [HarmonyPrefix] private static bool Use(PlayerControllerB __instance) { return !LocalSpectating(__instance); } [HarmonyPatch(typeof(PlayerControllerB), "ItemSecondaryUse_performed")] [HarmonyPrefix] private static bool Use2(PlayerControllerB __instance) { return !LocalSpectating(__instance); } [HarmonyPatch(typeof(PlayerControllerB), "ItemTertiaryUse_performed")] [HarmonyPrefix] private static bool Use3(PlayerControllerB __instance) { return !LocalSpectating(__instance); } [HarmonyPatch(typeof(PlayerControllerB), "Discard_performed")] [HarmonyPrefix] private static bool Drop(PlayerControllerB __instance) { return !LocalSpectating(__instance); } [HarmonyPatch(typeof(PlayerControllerB), "InspectItem_performed")] [HarmonyPrefix] private static bool Inspect(PlayerControllerB __instance) { return !LocalSpectating(__instance); } [HarmonyPatch(typeof(PlayerControllerB), "Emote1_performed")] [HarmonyPrefix] private static bool Emote1(PlayerControllerB __instance) { return !LocalSpectating(__instance); } [HarmonyPatch(typeof(PlayerControllerB), "Emote2_performed")] [HarmonyPrefix] private static bool Emote2(PlayerControllerB __instance) { return !LocalSpectating(__instance); } [HarmonyPatch(typeof(PlayerControllerB), "DamagePlayer")] [HarmonyPrefix] private static bool Damage(PlayerControllerB __instance) { return !Net.IsSpectator(__instance); } [HarmonyPatch(typeof(PlayerControllerB), "KillPlayer")] [HarmonyPrefix] private static bool Kill(PlayerControllerB __instance, CauseOfDeath causeOfDeath) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 if (Net.IsSpectator(__instance)) { return (int)causeOfDeath == 10; } return true; } [HarmonyPatch(typeof(EnemyAI), "PlayerIsTargetable")] [HarmonyPostfix] private static void Targetable(PlayerControllerB playerScript, ref bool __result) { if (__result && Net.IsSpectator(playerScript)) { __result = false; } } [HarmonyPatch(typeof(EnemyAI), "MeetsStandardPlayerCollisionConditions")] [HarmonyPostfix] private static void Touch(ref PlayerControllerB __result) { if ((Object)(object)__result != (Object)null && Net.IsSpectator(__result)) { __result = null; } } [HarmonyPatch(typeof(HUDManager), "SubmitChat_performed")] [HarmonyPrefix] private static void Chat(HUDManager __instance) { string text = (__instance.chatTextField.text ?? "").Trim(); if (!text.StartsWith("/gamemode", StringComparison.OrdinalIgnoreCase) && !text.StartsWith("/gm ", StringComparison.OrdinalIgnoreCase)) { return; } __instance.chatTextField.text = ""; string[] array = text.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries); string text2 = ((array.Length > 1) ? array[1].ToLowerInvariant() : ""); bool? flag = null; if (text2 != null) { switch (text2.Length) { case 1: { char c = text2[0]; if (c != '0') { if (c == '3') { goto IL_0133; } if (c != 's') { break; } } goto IL_013d; } case 9: if (!(text2 == "spectator")) { break; } goto IL_0133; case 10: if (!(text2 == "spectateur")) { break; } goto IL_0133; case 4: if (!(text2 == "spec")) { break; } goto IL_0133; case 2: if (!(text2 == "sp")) { break; } goto IL_0133; case 8: if (!(text2 == "survival")) { break; } goto IL_013d; case 6: { if (!(text2 == "survie")) { break; } goto IL_013d; } IL_0133: flag = true; break; IL_013d: flag = false; break; } } if (!flag.HasValue) { Spectator.Tip("Commande", "/gamemode spectator ou /gamemode survival", warning: false); } else if (flag.Value != (Spectator.Active || Net.IsSpectator(Net.LocalIndex))) { Spectator.Toggle(); } } [HarmonyPatch(typeof(StartOfRound), "UpdatePlayerVoiceEffects")] [HarmonyPostfix] private static void Voices(StartOfRound __instance) { if (!Settings.MuteForLiving.Value) { return; } PlayerControllerB localPlayerController = __instance.localPlayerController; if ((Object)(object)localPlayerController == (Object)null || localPlayerController.isPlayerDead || Spectator.Active) { return; } PlayerControllerB[] allPlayerScripts = __instance.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)localPlayerController) && Net.IsSpectator(val) && val.voicePlayerState != null) { val.voicePlayerState.Volume = 0f; } } } } internal interface ISynced { float Local { get; } void SetHost(float value); void ClearHost(); } internal sealed class Synced<T> : ISynced where T : IConvertible { private readonly ConfigEntry<T> _entry; private T _host; private bool _hasHost; public T Value { get { if (!_hasHost) { return _entry.Value; } return _host; } } public float Local => Convert.ToSingle(_entry.Value); public Synced(ConfigEntry<T> entry) { _entry = entry; } public void SetHost(float value) { _host = (T)Convert.ChangeType(value, typeof(T)); _hasHost = true; } public void ClearHost() { _hasHost = false; } public static implicit operator T(Synced<T> s) { return s.Value; } } internal enum Who { Tous, HoteSeulement, MortsSeulement } internal static class Settings { public static readonly List<ISynced> All = new List<ISynced>(); public static ConfigEntry<Key> ToggleKey; public static ConfigEntry<Key> LightKey; public static ConfigEntry<float> StartSpeed; public static ConfigEntry<bool> ShowHelp; public static ConfigEntry<bool> HideGameHud; public static ConfigEntry<bool> StartAsSpectator; public static Synced<int> AllowedWho; public static Synced<bool> StayWhereYouAre; public static Synced<bool> MuteForLiving; public static ConfigEntry<bool> AutoTest; public static void Init(ConfigFile cfg) { ToggleKey = cfg.Bind<Key>("Touches", "Spectateur", (Key)99, "Entrer / sortir du mode spectateur."); LightKey = cfg.Bind<Key>("Touches", "Vision", (Key)26, "En spectateur : allumer / éteindre la lumière (toi seul la vois)."); StartSpeed = cfg.Bind<float>("Spectateur", "Vitesse", 10f, "Vitesse de vol de départ (m/s). La molette la change en jeu."); ShowHelp = cfg.Bind<bool>("Spectateur", "AfficherAide", true, "Affiche les commandes en haut de l'écran en mode spectateur."); StartAsSpectator = cfg.Bind<bool>("Spectateur", "DemarrerEnSpectateur", false, "Passe automatiquement en spectateur en arrivant dans une partie."); HideGameHud = cfg.Bind<bool>("Spectateur", "CacherInterfaceDuJeu", true, "Cache l'interface du jeu (vie, inventaire…) en mode spectateur."); AllowedWho = S<int>(cfg.Bind<int>("Partie", "QuiPeut", 0, "[Hôte] Qui peut passer en spectateur : 0 = tout le monde, 1 = l'hôte seulement, 2 = seulement les joueurs morts.")); StayWhereYouAre = S<bool>(cfg.Bind<bool>("Partie", "SortieSurPlace", true, "[Hôte] En quittant le mode spectateur, le joueur réapparaît là où il est (si l'endroit est libre), sinon il revient à son corps.")); MuteForLiving = S<bool>(cfg.Bind<bool>("Partie", "VoixCacheeAuxVivants", true, "[Hôte] Les joueurs vivants n'entendent pas la voix des spectateurs.")); AutoTest = cfg.Bind<bool>("Test", "AutoTest", false, "Développeur : lance tout seul une partie de test."); } private static Synced<T> S<T>(ConfigEntry<T> e) where T : IConvertible { Synced<T> synced = new Synced<T>(e); All.Add(synced); return synced; } public static void ClearHostValues() { foreach (ISynced item in All) { item.ClearHost(); } } } internal static class Spectator { public static bool Active; private static Camera _cam; private static float _yaw; private static float _pitch; private static float _speed; private static GameObject _light; private static bool _lightOn; private static bool _savedInside; private static bool _requested; private static bool _hidHud; private static float _nextVisibility; private const int SolidMask = 318769409; private static GameObject _hud; private static TextMeshProUGUI _hudText; private static PlayerControllerB Local { get { if (!((Object)(object)StartOfRound.Instance != (Object)null)) { return null; } return StartOfRound.Instance.localPlayerController; } } public static void Toggle() { PlayerControllerB local = Local; if (!((Object)(object)local == (Object)null)) { if (Active || Net.IsSpectator(local)) { Net.RequestSpectator(on: false); return; } _requested = true; Net.RequestSpectator(on: true); } } public static void OnDenied(string why) { _requested = false; Tip("Mode spectateur", why, warning: true); } public static void OnStateChanged() { PlayerControllerB local = Local; if ((Object)(object)local != (Object)null) { bool flag = Net.IsSpectator(local); if (flag && !Active) { Enter(local); } else if (!flag && Active) { Exit(local, teleport: true); } } _nextVisibility = 0f; try { StartOfRound instance = StartOfRound.Instance; if (instance != null) { instance.UpdatePlayerVoiceEffects(); } } catch { } } private static void Enter(PlayerControllerB p) { //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: 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_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) StartOfRound instance = StartOfRound.Instance; _cam = instance.freeCinematicCamera; if ((Object)(object)_cam == (Object)null) { Plugin.Log.LogError((object)"Caméra libre introuvable : mode spectateur impossible."); Net.RequestSpectator(on: false); return; } Active = true; _requested = false; _speed = Mathf.Clamp(Settings.StartSpeed.Value, 1f, 80f); Transform val = ((p.isPlayerDead && (Object)(object)instance.spectateCamera != (Object)null) ? ((Component)instance.spectateCamera).transform : ((Component)p.gameplayCamera).transform); ((Component)_cam).transform.SetParent((Transform)null, true); ((Component)_cam).transform.SetPositionAndRotation(val.position, Quaternion.Euler(val.eulerAngles.x, val.eulerAngles.y, 0f)); _yaw = val.eulerAngles.y; _pitch = ((val.eulerAngles.x > 180f) ? (val.eulerAngles.x - 360f) : val.eulerAngles.x); _savedInside = p.isInsideFactory; UseCamera(p); Lock(p, on: true); if ((Object)(object)p.currentlyHeldObjectServer != (Object)null && !p.isPlayerDead) { p.currentlyHeldObjectServer.EnableItemMeshes(false); } _hidHud = false; if (Settings.HideGameHud.Value && (Object)(object)HUDManager.Instance != (Object)null && !HUDManager.Instance.hudHidden) { HUDManager.Instance.HideHUD(true); _hidHud = true; } Plugin.Log.LogInfo((object)"Mode spectateur activé."); } private static void UseCamera(PlayerControllerB p) { StartOfRound instance = StartOfRound.Instance; if ((Object)(object)p.gameplayCamera != (Object)null) { ((Behaviour)p.gameplayCamera).enabled = false; } instance.SwitchCamera(_cam); ((Behaviour)_cam).enabled = true; p.ChangeAudioListenerToObject(((Component)_cam).gameObject); } public static void Exit(PlayerControllerB p, bool teleport) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) if (!Active) { return; } Active = false; StartOfRound instance = StartOfRound.Instance; Vector3 val = (((Object)(object)_cam != (Object)null) ? ((Component)_cam).transform.position : ((Component)p).transform.position); float yaw = _yaw; if ((Object)(object)_light != (Object)null) { _light.SetActive(false); } _lightOn = false; Lock(p, on: false); if ((Object)(object)_cam != (Object)null) { ((Behaviour)_cam).enabled = false; } if (_hidHud && (Object)(object)HUDManager.Instance != (Object)null) { HUDManager.Instance.HideHUD(false); } _hidHud = false; if (p.isPlayerDead) { if ((Object)(object)instance.spectateCamera != (Object)null) { instance.SwitchCamera(instance.spectateCamera); p.ChangeAudioListenerToObject(((Component)instance.spectateCamera).gameObject); } } else { ((Behaviour)p.gameplayCamera).enabled = true; instance.SwitchCamera(p.gameplayCamera); p.ChangeAudioListenerToObject(((Component)p.gameplayCamera).gameObject); bool flag = false; if (teleport && Settings.StayWhereYouAre.Value && TryFindSpot(val, out var spot)) { bool inside = spot.y < -80f; p.TeleportPlayer(spot, false, 0f, false, true); Bounds bounds = instance.shipBounds.bounds; p.isInElevator = ((Bounds)(ref bounds)).Contains(spot); bounds = instance.shipInnerRoomBounds.bounds; p.isInHangarShipRoom = ((Bounds)(ref bounds)).Contains(spot); SetInside(p, inside); p.thisPlayerBody.rotation = Quaternion.Euler(0f, yaw, 0f); flag = true; } if (!flag) { SetInside(p, _savedInside); } if ((Object)(object)p.currentlyHeldObjectServer != (Object)null) { p.currentlyHeldObjectServer.EnableItemMeshes(true); } if (teleport && !flag && Settings.StayWhereYouAre.Value) { Tip("Mode spectateur", "Endroit bloqué : retour à ton corps.", warning: false); } } Plugin.Log.LogInfo((object)"Mode spectateur désactivé."); } public static void ForceReset() { PlayerControllerB local = Local; if (Active && (Object)(object)local != (Object)null) { Exit(local, teleport: false); } Active = false; _requested = false; } private static void SetInside(PlayerControllerB p, bool inside) { if (p.isInsideFactory == inside) { return; } p.isInsideFactory = inside; try { StartOfRound.Instance.SwitchIsInsideFactoryRpc((int)p.playerClientId, inside); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Synchro intérieur/extérieur : " + ex.Message)); } } private static void Lock(PlayerControllerB p, bool on) { p.disableMoveInput = on; p.disableLookInput = on; p.disableInteract = on; if (on) { ((TMP_Text)p.cursorTip).text = ""; ((Behaviour)p.cursorIcon).enabled = false; } } public static bool TryFindSpot(Vector3 from, out Vector3 spot) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: 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_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0048: 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) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: 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) spot = from; RaycastHit val = default(RaycastHit); if (!Physics.Raycast(from + Vector3.up * 0.2f, Vector3.down, ref val, 60f, 318769409, (QueryTriggerInteraction)1)) { return false; } Vector3 val2 = ((RaycastHit)(ref val)).point + Vector3.up * 0.05f; if (Physics.CheckCapsule(val2 + Vector3.up * 0.45f, val2 + Vector3.up * 1.95f, 0.35f, 318769409, (QueryTriggerInteraction)1)) { return false; } NavMeshHit val3 = default(NavMeshHit); if (!NavMesh.SamplePosition(val2, ref val3, 2.5f, -1)) { return false; } if (Mathf.Abs(((NavMeshHit)(ref val3)).position.y - val2.y) > 1.5f) { return false; } spot = val2; return true; } public static void Tick() { //IL_00f9: Unknown result type (might be due to invalid IL or missing references) StartOfRound instance = StartOfRound.Instance; PlayerControllerB local = Local; if ((Object)(object)local == (Object)null) { return; } if (Time.unscaledTime >= _nextVisibility) { _nextVisibility = Time.unscaledTime + 0.5f; Visibility.Refresh(); } if (Active && !Net.IsSpectator(local) && !_requested) { Exit(local, teleport: true); } if (!Active) { Hud(show: false); return; } if ((Object)(object)instance.activeCamera != (Object)(object)_cam || !((Behaviour)_cam).enabled) { UseCamera(local); } if (((Behaviour)local.gameplayCamera).enabled) { ((Behaviour)local.gameplayCamera).enabled = false; } Lock(local, on: true); local.ResetFallGravity(); if ((!((Object)(object)local.quickMenuManager != (Object)null) || !local.quickMenuManager.isMenuOpen) && !local.isTypingChat && !local.inTerminalMenu) { Fly(local); } Hud(Settings.ShowHelp.Value); bool flag = ((Component)_cam).transform.position.y < -80f; if (local.isInsideFactory != flag && !local.isPlayerDead) { local.isInsideFactory = flag; } } private static void Fly(PlayerControllerB p) { //IL_0033: 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) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_007a: 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_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_020e: 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_021c: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) Keyboard current = Keyboard.current; Mouse current2 = Mouse.current; float num = (((Object)(object)IngamePlayerSettings.Instance != (Object)null) ? IngamePlayerSettings.Instance.settings.lookSensitivity : 10); Vector2 val = ReadAction("Look") * 0.008f * num; if ((Object)(object)IngamePlayerSettings.Instance != (Object)null && IngamePlayerSettings.Instance.settings.invertYAxis) { val.y = 0f - val.y; } _yaw += val.x; _pitch = Mathf.Clamp(_pitch - val.y, -89f, 89f); ((Component)_cam).transform.rotation = Quaternion.Euler(_pitch, _yaw, 0f); if (current2 != null) { float y = ((InputControl<Vector2>)(object)current2.scroll).ReadValue().y; if (y > 0.1f) { _speed = Mathf.Min(80f, _speed * 1.2f); } else if (y < -0.1f) { _speed = Mathf.Max(1f, _speed / 1.2f); } } Vector2 val2 = ReadAction("Move"); float num2 = 0f; if (current != null) { if (((ButtonControl)current.spaceKey).isPressed) { num2 += 1f; } if (((ButtonControl)current.leftCtrlKey).isPressed || ((ButtonControl)current.cKey).isPressed) { num2 -= 1f; } } float num3 = _speed * ((current != null && ((ButtonControl)current.leftShiftKey).isPressed) ? 3f : 1f); Vector3 val3 = ((Component)_cam).transform.forward * val2.y + ((Component)_cam).transform.right * val2.x + Vector3.up * num2; if (((Vector3)(ref val3)).sqrMagnitude > 1f) { ((Vector3)(ref val3)).Normalize(); } Transform transform = ((Component)_cam).transform; transform.position += val3 * num3 * Time.unscaledDeltaTime; if (current != null && ((ButtonControl)current[Settings.LightKey.Value]).wasPressedThisFrame) { ToggleLight(p); } } private static Vector2 ReadAction(string name) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) try { InputAction val = (((Object)(object)InputSystem.actions != (Object)null) ? InputSystem.actions.FindAction(name, false) : null); return (val != null) ? val.ReadValue<Vector2>() : Vector2.zero; } catch { return Vector2.zero; } } private static void ToggleLight(PlayerControllerB p) { //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_light == (Object)null) { Light val = ((p.allHelmetLights != null && p.allHelmetLights.Length != 0) ? p.allHelmetLights[0] : p.helmetLight); if ((Object)(object)val == (Object)null) { return; } _light = Object.Instantiate<GameObject>(((Component)val).gameObject); ((Object)_light).name = "SpectatorLight"; foreach (Transform item in _light.transform) { Object.Destroy((Object)(object)((Component)item).gameObject); } Light component = _light.GetComponent<Light>(); ((Behaviour)component).enabled = true; component.range = 70f; component.spotAngle = 110f; component.innerSpotAngle = 70f; component.intensity *= 2.5f; component.shadows = (LightShadows)0; } _lightOn = !_lightOn; _light.transform.SetParent(((Component)_cam).transform, false); _light.transform.localPosition = Vector3.zero; _light.transform.localRotation = Quaternion.identity; _light.SetActive(_lightOn); } private static void Hud(bool show) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) if (!show) { if ((Object)(object)_hud != (Object)null && _hud.activeSelf) { _hud.SetActive(false); } return; } if ((Object)(object)_hud == (Object)null) { BuildHud(); } if (!((Object)(object)_hud == (Object)null)) { if (!_hud.activeSelf) { _hud.SetActive(true); } string text = ((object)Settings.ToggleKey.Value/*cast due to .constrained prefix*/).ToString(); ((TMP_Text)_hudText).text = "<color=#ff8c26><b>SPECTATEUR</b></color> [" + text + "] quitter · ZQSD voler · Espace / Ctrl : monter / descendre · Maj : plus vite\n" + string.Format("<size=85%>Molette : vitesse <b>{0:0}</b> m/s · [{1}] lumière {2} · Invisible, invulnérable, ignoré des monstres</size>", _speed, Settings.LightKey.Value, _lightOn ? "allumée" : "éteinte"); } } private static void BuildHud() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Expected O, but got Unknown //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) _hud = new GameObject("SpectatorMode_Hud"); Object.DontDestroyOnLoad((Object)(object)_hud); Canvas obj = _hud.AddComponent<Canvas>(); obj.renderMode = (RenderMode)0; obj.sortingOrder = 45; CanvasScaler obj2 = _hud.AddComponent<CanvasScaler>(); obj2.uiScaleMode = (ScaleMode)1; obj2.referenceResolution = new Vector2(1920f, 1080f); obj2.matchWidthOrHeight = 0.5f; GameObject val = new GameObject("Text", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(_hud.transform, false); _hudText = val.AddComponent<TextMeshProUGUI>(); TMP_FontAsset val2 = ((IEnumerable<TMP_FontAsset>)Resources.FindObjectsOfTypeAll<TMP_FontAsset>()).FirstOrDefault((Func<TMP_FontAsset, bool>)((TMP_FontAsset f) => ((Object)f).name == "LiberationSans SDF")); if ((Object)(object)val2 != (Object)null) { ((TMP_Text)_hudText).font = val2; } ((TMP_Text)_hudText).fontSize = 22f; ((TMP_Text)_hudText).alignment = (TextAlignmentOptions)258; ((TMP_Text)_hudText).enableWordWrapping = false; ((TMP_Text)_hudText).richText = true; ((Graphic)_hudText).raycastTarget = false; ((TMP_Text)_hudText).outlineWidth = 0.18f; ((TMP_Text)_hudText).outlineColor = new Color32((byte)0, (byte)0, (byte)0, (byte)220); RectTransform rectTransform = ((TMP_Text)_hudText).rectTransform; Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(0.5f, 1f); rectTransform.pivot = val3; Vector2 anchorMin = (rectTransform.anchorMax = val3); rectTransform.anchorMin = anchorMin; rectTransform.anchoredPosition = new Vector2(0f, -16f); rectTransform.sizeDelta = new Vector2(1800f, 70f); } public static void Tip(string header, string body, bool warning) { try { HUDManager instance = HUDManager.Instance; if (instance != null) { instance.DisplayTip(Plain(header), Plain(body), warning, false, ""); } } catch { } } private static string Plain(string s) { string text = (s ?? "").Normalize(NormalizationForm.FormD); StringBuilder stringBuilder = new StringBuilder(text.Length); string text2 = text; foreach (char c in text2) { if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark) { stringBuilder.Append(c); } } return stringBuilder.ToString(); } } internal static class Visibility { private static readonly Dictionary<int, List<Renderer>> Hidden = new Dictionary<int, List<Renderer>>(); public static void Refresh() { StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance == (Object)null) { return; } for (int i = 0; i < instance.allPlayerScripts.Length; i++) { PlayerControllerB val = instance.allPlayerScripts[i]; if (!((Object)(object)val == (Object)null)) { if (Net.IsSpectator(i) && !val.isPlayerDead) { Hide(i, val); } else if (Hidden.ContainsKey(i)) { Show(i, val); } } } } private static void Hide(int i, PlayerControllerB p) { if (!Hidden.TryGetValue(i, out var value)) { value = (Hidden[i] = new List<Renderer>()); } Renderer[] componentsInChildren = ((Component)p).GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && val.enabled) { val.enabled = false; if (!value.Contains(val)) { value.Add(val); } } } if ((Object)(object)p.usernameCanvas != (Object)null) { ((Behaviour)p.usernameCanvas).enabled = false; } if ((Object)(object)p.currentlyHeldObjectServer != (Object)null) { p.currentlyHeldObjectServer.EnableItemMeshes(false); } } private static void Show(int i, PlayerControllerB p) { foreach (Renderer item in Hidden[i]) { if ((Object)(object)item != (Object)null) { item.enabled = true; } } Hidden.Remove(i); if ((Object)(object)p.usernameCanvas != (Object)null) { ((Behaviour)p.usernameCanvas).enabled = true; } if ((Object)(object)p.currentlyHeldObjectServer != (Object)null && !p.isPlayerDead) { p.currentlyHeldObjectServer.EnableItemMeshes(true); } } public static void ShowAll() { StartOfRound instance = StartOfRound.Instance; foreach (int item in Hidden.Keys.ToList()) { if ((Object)(object)instance != (Object)null && item < instance.allPlayerScripts.Length) { Show(item, instance.allPlayerScripts[item]); } else { Hidden.Remove(item); } } } } }