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 EnhancedSpectator v0.4.6
BepInEx/plugins/EnhancedSpectator/EnhancedSpectator.dll
Decompiled 3 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Buffers.Binary; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Serialization.Json; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using System.Threading.Tasks; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using Dissonance; using Dissonance.Integrations.Unity_NFGO; using DunGen; using EnhancedSpectator.CameraRuntime.Cinemachine; using EnhancedSpectator.Config; using EnhancedSpectator.Features; using EnhancedSpectator.Features.FearMode; using EnhancedSpectator.Features.FloatingHead; using EnhancedSpectator.Features.ModelInspection; using EnhancedSpectator.Features.PlayerStateSync; using EnhancedSpectator.Features.Social; using EnhancedSpectator.Features.Spectator; using EnhancedSpectator.Features.SpectatorPresence; using EnhancedSpectator.Features.SplitScreen; using EnhancedSpectator.Features.VoiceActivity; using EnhancedSpectator.Features.VoiceDiagnostics; using EnhancedSpectator.Features.VoiceRouting; using EnhancedSpectator.GameInterop; using EnhancedSpectator.Logging; using EnhancedSpectator.Networking; using EnhancedSpectator.Patching; using EnhancedSpectator.Runtime; using GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; using MoreCompany.Cosmetics; using Steamworks; using Steamworks.Data; using TMPro; using Unity.AI.Navigation; using Unity.Collections; using Unity.Netcode; using UnityEngine; using UnityEngine.AI; using UnityEngine.Animations.Rigging; using UnityEngine.Audio; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.Experimental.Rendering.RenderGraphModule; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.InputSystem.LowLevel; using UnityEngine.LowLevel; using UnityEngine.Networking; using UnityEngine.Playables; using UnityEngine.PlayerLoop; using UnityEngine.Rendering; using UnityEngine.Rendering.HighDefinition; using UnityEngine.Rendering.RendererUtils; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Runtime")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("EnhancedSpectator")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.4.6.0")] [assembly: AssemblyInformationalVersion("0.4.6+bda9a5516936fcdec79138d285ec3647c87bb46c")] [assembly: AssemblyProduct("EnhancedSpectator")] [assembly: AssemblyTitle("EnhancedSpectator")] [assembly: InternalsVisibleTo("EnhancedSpectator.Tests")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.4.6.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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 EnhancedSpectator { [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("Auuueser.EnhancedSpectator", "Enhanced Spectator", "0.4.6")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { private FeatureBootstrapper? _featureBootstrapper; private PatchBootstrapper? _patchBootstrapper; private DiagnosticLoggingBinding? _diagnosticLogging; private bool _applicationQuitting; private bool _shutdownComplete; private void Awake() { RuntimeConnectionState.Reset(); ModLog.Initialize(((BaseUnityPlugin)this).Logger); ModLog.Info("Enhanced Spectator 0.4.6 starting."); Application.quitting += OnApplicationQuitting; EnhancedSpectatorConfig config = EnhancedSpectatorConfig.Bind(((BaseUnityPlugin)this).Config); NativeFadePass.Configure(config.Camera); LethalCompanySpectatorPresentation.Configure(config); SpectatorEnemyVisibility.Configure(config); config.Camera.FadeRadius.SettingChanged += delegate { LogFadeConfiguration(config); }; config.Camera.FadeModelsWhileSpectating.SettingChanged += delegate { LogFadeConfiguration(config); }; config.Camera.FadeModelsNearby.SettingChanged += delegate { LogFadeConfiguration(config); }; _diagnosticLogging = new DiagnosticLoggingBinding(config.EnableDebugLogging, delegate { LogFadeConfiguration(config); PluginDiagnostics.LogPluginBinaryHash(((BaseUnityPlugin)this).Info.Location); }); _featureBootstrapper = new FeatureBootstrapper(config); _featureBootstrapper.Initialize(); _patchBootstrapper = new PatchBootstrapper(); _patchBootstrapper.Register(); EnhancedSpectatorRuntimeDriver.Install(_featureBootstrapper, Shutdown); ModLog.Debug("Local spectator freecam initialized."); } private static void LogFadeConfiguration(EnhancedSpectatorConfig config) { ModLog.Debug(string.Format("Fade configuration: build={0}, enabled={1}, whileSpectating={2}, radius={3:F2}, backend=native-whole-model. Camera preparation and draw submission are reported separately.", "whole-model-r11-active-view-owner-20260927", config.Camera.FadeModelsNearby.Value, config.Camera.FadeModelsWhileSpectating.Value, config.Camera.FadeRadius.Value)); } private void OnDestroy() { if (!_applicationQuitting) { EnhancedSpectatorRuntimeDriver.EnsureInstalled(); ModLog.Warning("Plugin component destroyed before application quit; preserving runtime driver and patches.", "D:\\111\\game\\lethal company mod\\test mods\\codex\\Enhanced-Spectator-0.4.6-release-candidate\\src\\EnhancedSpectator\\Plugin.cs", 64); } else { Shutdown(); } } private void OnApplicationQuitting() { _applicationQuitting = true; RuntimeConnectionState.MarkApplicationQuitting(); Shutdown(); } private void Shutdown() { if (!_shutdownComplete) { _shutdownComplete = true; RuntimeConnectionState.MarkPluginShuttingDown(); Application.quitting -= OnApplicationQuitting; EnhancedSpectatorRuntimeDriver.BeginShutdown(); _patchBootstrapper?.Dispose(); SpectatorEnemyVisibility.Shutdown(); _featureBootstrapper?.Dispose(); NativeFadePass.Shutdown(); ModLog.Debug("Local spectator freecam shut down."); _diagnosticLogging?.Dispose(); _diagnosticLogging = null; } } } public static class PluginMetadata { public const string Guid = "Auuueser.EnhancedSpectator"; public const string Name = "Enhanced Spectator"; public const string Version = "0.4.6"; } } namespace EnhancedSpectator.Runtime { internal sealed class EnhancedSpectatorGuiDriver : MonoBehaviour { private void Awake() { ((MonoBehaviour)this).useGUILayout = false; } private void OnGUI() { EnhancedSpectatorRuntimeDriver.GuiTick(); } } public sealed class EnhancedSpectatorRuntimeDriver : MonoBehaviour { [StructLayout(LayoutKind.Sequential, Size = 1)] private struct AfterLateUpdateStep { } [CompilerGenerated] private static class <>O { public static UnityAction<Scene, LoadSceneMode> <0>__OnSceneLoaded; public static UnityAction<Scene> <1>__OnSceneUnloaded; public static CameraCallback <2>__OnCameraPreCull; public static CameraCallback <3>__OnCameraPostRender; public static Action<ScriptableRenderContext, Camera> <4>__OnEndCameraRendering; public static Action<ScriptableRenderContext, Camera> <5>__OnBeginCameraRendering; public static UpdateFunction <6>__AfterLateUpdate; } private static FeatureBootstrapper? _featureBootstrapper; private static Action? _shutdown; private static EnhancedSpectatorRuntimeDriver? _instance; private static bool _applicationQuitting; private static bool _sceneHookRegistered; private static int _lastCameraTickFrame = -1; private static int _lastCameraTickInstanceId = int.MinValue; private bool _intentionalDestroy; private EnhancedSpectatorGuiDriver? _gui; public static void Install(FeatureBootstrapper featureBootstrapper, Action shutdown) { //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Expected O, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Expected O, but got Unknown //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Expected O, but got Unknown //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Expected O, but got Unknown _featureBootstrapper = featureBootstrapper ?? throw new ArgumentNullException("featureBootstrapper"); _shutdown = shutdown ?? throw new ArgumentNullException("shutdown"); _applicationQuitting = false; if (!_sceneHookRegistered) { SceneManager.sceneLoaded += OnSceneLoaded; SceneManager.sceneUnloaded += OnSceneUnloaded; CameraCallback onPreCull = Camera.onPreCull; object obj = <>O.<2>__OnCameraPreCull; if (obj == null) { CameraCallback val = OnCameraPreCull; <>O.<2>__OnCameraPreCull = val; obj = (object)val; } Camera.onPreCull = (CameraCallback)Delegate.Combine((Delegate?)(object)onPreCull, (Delegate?)obj); CameraCallback onPostRender = Camera.onPostRender; object obj2 = <>O.<3>__OnCameraPostRender; if (obj2 == null) { CameraCallback val2 = OnCameraPostRender; <>O.<3>__OnCameraPostRender = val2; obj2 = (object)val2; } Camera.onPostRender = (CameraCallback)Delegate.Combine((Delegate?)(object)onPostRender, (Delegate?)obj2); RenderPipelineManager.endCameraRendering += OnEndCameraRendering; RenderPipelineManager.beginCameraRendering += OnBeginCameraRendering; PlaceAfterLateUpdate(place: true); _sceneHookRegistered = true; } EnsureInstalled(); } public static void EnsureInstalled() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown if (!_applicationQuitting && _featureBootstrapper != null && !((Object)(object)_instance != (Object)null)) { GameObject val = new GameObject("Enhanced Spectator Runtime"); Object.DontDestroyOnLoad((Object)val); _instance = val.AddComponent<EnhancedSpectatorRuntimeDriver>(); } } public static void BeginShutdown() { //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Expected O, but got Unknown //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_0084: Expected O, but got Unknown //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Expected O, but got Unknown //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown LethalCompanySpectatorUiVisibility.Clear(); LethalCompanySpectatorPresentation.Clear(); _applicationQuitting = true; LethalCompanyFirstPersonVisibility.Clear(); RuntimeConnectionState.MarkPluginShuttingDown(); if (_sceneHookRegistered) { SceneManager.sceneLoaded -= OnSceneLoaded; SceneManager.sceneUnloaded -= OnSceneUnloaded; CameraCallback onPreCull = Camera.onPreCull; object obj = <>O.<2>__OnCameraPreCull; if (obj == null) { CameraCallback val = OnCameraPreCull; <>O.<2>__OnCameraPreCull = val; obj = (object)val; } Camera.onPreCull = (CameraCallback)Delegate.Remove((Delegate?)(object)onPreCull, (Delegate?)obj); CameraCallback onPostRender = Camera.onPostRender; object obj2 = <>O.<3>__OnCameraPostRender; if (obj2 == null) { CameraCallback val2 = OnCameraPostRender; <>O.<3>__OnCameraPostRender = val2; obj2 = (object)val2; } Camera.onPostRender = (CameraCallback)Delegate.Remove((Delegate?)(object)onPostRender, (Delegate?)obj2); RenderPipelineManager.endCameraRendering -= OnEndCameraRendering; RenderPipelineManager.beginCameraRendering -= OnBeginCameraRendering; PlaceAfterLateUpdate(place: false); _sceneHookRegistered = false; } if ((Object)(object)_instance != (Object)null) { _instance._intentionalDestroy = true; Object.Destroy((Object)(object)((Component)_instance).gameObject); _instance = null; } _featureBootstrapper = null; _shutdown = null; _lastCameraTickFrame = -1; _lastCameraTickInstanceId = int.MinValue; } private void Update() { bool flag = _featureBootstrapper?.WantsGui ?? false; if (flag && (Object)(object)_gui == (Object)null) { _gui = ((Component)this).gameObject.AddComponent<EnhancedSpectatorGuiDriver>(); } else if (!flag && (Object)(object)_gui != (Object)null) { Object.Destroy((Object)(object)_gui); _gui = null; } LethalCompanySpectatorUiVisibility.RestoreRenderers(); LethalCompanyFirstPersonVisibility.Restore(); _featureBootstrapper?.Tick(); LethalCompanySpectatorPresentation.Tick(); } private void LateUpdate() { _featureBootstrapper?.LateTick(); } private static void PlaceAfterLateUpdate(bool place) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Expected O, but got Unknown PlayerLoopSystem currentPlayerLoop = PlayerLoop.GetCurrentPlayerLoop(); PlayerLoopSystem[] subSystemList = currentPlayerLoop.subSystemList; for (int i = 0; i < subSystemList.Length; i++) { if (subSystemList[i].type != typeof(PreLateUpdate)) { continue; } List<PlayerLoopSystem> list = new List<PlayerLoopSystem>(subSystemList[i].subSystemList); list.RemoveAll((PlayerLoopSystem step) => step.type == typeof(AfterLateUpdateStep)); if (place) { int index = list.FindIndex((PlayerLoopSystem step) => step.type == typeof(ScriptRunBehaviourLateUpdate)) + 1; PlayerLoopSystem item = new PlayerLoopSystem { type = typeof(AfterLateUpdateStep) }; object obj = <>O.<6>__AfterLateUpdate; if (obj == null) { UpdateFunction val = AfterLateUpdate; <>O.<6>__AfterLateUpdate = val; obj = (object)val; } item.updateDelegate = (UpdateFunction)obj; list.Insert(index, item); } subSystemList[i].subSystemList = list.ToArray(); } PlayerLoop.SetPlayerLoop(currentPlayerLoop); } private static void AfterLateUpdate() { if ((Object)(object)_instance != (Object)null) { _featureBootstrapper?.AfterLateTick(); } } internal static void GuiTick() { _featureBootstrapper?.GuiTick(); } private void OnApplicationQuit() { _applicationQuitting = true; RuntimeConnectionState.MarkApplicationQuitting(); _shutdown?.Invoke(); _shutdown = null; } private void OnDestroy() { if ((Object)(object)_instance == (Object)(object)this) { _instance = null; } if (!_applicationQuitting && !_intentionalDestroy) { ModLog.Warning("Runtime driver destroyed before application quit; it will be recreated on the next plugin or scene lifecycle event.", "D:\\111\\game\\lethal company mod\\test mods\\codex\\Enhanced-Spectator-0.4.6-release-candidate\\src\\EnhancedSpectator\\Runtime\\EnhancedSpectatorRuntimeDriver.cs", 168); } } private static void OnSceneLoaded(Scene scene, LoadSceneMode mode) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) if (!MonitorDoorGeometry.OwnsScene(scene)) { LethalCompanySpectatorUiVisibility.Clear(); LethalCompanySpectatorPresentation.Clear(); LethalCompanyFirstPersonVisibility.Clear(); RuntimeConnectionState.MarkSceneTransition(); EnsureInstalled(); } } private static void OnSceneUnloaded(Scene scene) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) if (!MonitorDoorGeometry.OwnsScene(scene)) { LethalCompanySpectatorUiVisibility.Clear(); LethalCompanySpectatorPresentation.Clear(); LethalCompanyFirstPersonVisibility.Clear(); RuntimeConnectionState.MarkSceneTransition(); } } private static void OnCameraPostRender(Camera camera) { LethalCompanyFirstPersonVisibility.Restore(); } private static void OnEndCameraRendering(ScriptableRenderContext context, Camera camera) { LethalCompanyFirstPersonVisibility.Restore(); LethalCompanySpectatorPresentation.EndCamera(camera); } private static void OnCameraPreCull(Camera camera) { NativeFadeDiagnostics.CameraEvent("builtin-pre-cull", camera); TryCameraPreCullTick(camera); } private static void OnBeginCameraRendering(ScriptableRenderContext context, Camera camera) { NativeFadeDiagnostics.CameraEvent("SRP-begin", camera); TryCameraPreCullTick(camera); } private static void TryCameraPreCullTick(Camera camera) { if (_featureBootstrapper != null && !((Object)(object)camera == (Object)null)) { int frameCount = Time.frameCount; int instanceID = ((Object)camera).GetInstanceID(); if (_lastCameraTickFrame != frameCount || _lastCameraTickInstanceId != instanceID) { _lastCameraTickFrame = frameCount; _lastCameraTickInstanceId = instanceID; LethalCompanyFirstPersonVisibility.Restore(); _featureBootstrapper.CameraPreCullTick(camera); } } } } public interface IRuntimeAfterLateTickable { void AfterLateTick(); } public interface IRuntimeCameraPreCullTickable { void CameraPreCullTick(Camera camera); } public interface IRuntimeGuiTickable { void GuiTick(); } public interface IRuntimeLateTickable { void LateTick(); } public interface IRuntimeTickable { void Tick(); } public static class RuntimeConnectionState { private const float SceneTransitionUnsafeSeconds = 0.5f; private static bool _applicationQuitting; private static bool _pluginShuttingDown; private static float _unsafeUntilRealtime; public static void Reset() { _applicationQuitting = false; _pluginShuttingDown = false; _unsafeUntilRealtime = 0f; } public static void MarkApplicationQuitting() { _applicationQuitting = true; MarkUnsafeWindow(); } public static void MarkPluginShuttingDown() { _pluginShuttingDown = true; MarkUnsafeWindow(); } public static void MarkSceneTransition() { MarkUnsafeWindow(); } public static bool CanUseModNetworking(out string reason) { if (IsLifecycleUnsafe(out reason)) { return false; } NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null) { reason = "NetworkManager unavailable"; return false; } if (singleton.ShutdownInProgress) { reason = "NetworkManager shutdown in progress"; return false; } if (!singleton.IsListening) { reason = "NetworkManager is not listening"; return false; } if (!singleton.IsClient && !singleton.IsHost) { reason = "not connected as client or host"; return false; } if (!singleton.IsConnectedClient && !singleton.IsHost) { reason = "local client is not connected"; return false; } if (singleton.CustomMessagingManager == null) { reason = "CustomMessagingManager unavailable"; return false; } reason = string.Empty; return true; } public static bool CanRunLocalDiagnostics(out string reason) { if (IsLifecycleUnsafe(out reason)) { return false; } NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton != (Object)null && singleton.ShutdownInProgress) { reason = "NetworkManager shutdown in progress"; return false; } reason = string.Empty; return true; } public static bool CanRepairVanillaPlayerState(out string reason) { if (IsLifecycleUnsafe(out reason)) { return false; } NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton != (Object)null && singleton.ShutdownInProgress) { reason = "NetworkManager shutdown in progress"; return false; } reason = string.Empty; return true; } public static bool ShouldSkipVanillaSpectatorTargetSwitch(out string reason) { if (IsLifecycleUnsafe(out reason)) { return true; } NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null) { reason = "NetworkManager unavailable"; return true; } if (singleton.ShutdownInProgress) { reason = "NetworkManager shutdown in progress"; return true; } if (!singleton.IsListening || (!singleton.IsClient && !singleton.IsHost)) { reason = "network is disconnected"; return true; } reason = string.Empty; return false; } private static bool IsLifecycleUnsafe(out string reason) { if (_applicationQuitting) { reason = "application is quitting"; return true; } if (_pluginShuttingDown) { reason = "plugin is shutting down"; return true; } if (Time.realtimeSinceStartup < _unsafeUntilRealtime) { reason = "scene transition unsafe window"; return true; } reason = string.Empty; return false; } private static void MarkUnsafeWindow() { float num = Time.realtimeSinceStartup + 0.5f; if (num > _unsafeUntilRealtime) { _unsafeUntilRealtime = num; } } } } namespace EnhancedSpectator.Patching { public interface IPatchModule { void Register(Harmony harmony); void Unregister(Harmony harmony); } [HarmonyPatch(typeof(HDCamera), "Update")] internal static class NativeFadeCameraPatch { [HarmonyPrefix] [HarmonyPriority(0)] private static void Prefix(HDCamera __instance, ref FrameSettings currentFrameSettings) { NativeFadePass.PrepareCamera(__instance, ref currentFrameSettings); } } [HarmonyPatch(typeof(CustomPass), "WillBeExecuted")] internal static class NativeFadeOtherPassPatch { [HarmonyPrefix] [HarmonyPriority(0)] private static bool Prefix(CustomPass __instance, HDCamera hdCamera, ref bool __result) { if (!NativeFadePass.SuppressOtherPass(__instance, hdCamera)) { return true; } __result = false; return false; } } [HarmonyPatch(typeof(HDRenderPipeline), "RenderForwardOpaque")] internal static class NativeFadeLightingCapturePatch { [HarmonyPrefix] private static void Prefix(HDCamera hdCamera, in BuildGPULightListOutput lightLists, in LightingBuffers lightingBuffers, in PrepassOutput prepassOutput, ShadowResult shadowResult) { NativeFadePass.CaptureLighting(hdCamera, in lightLists, in lightingBuffers, in prepassOutput, in shadowResult); } } [HarmonyPatch(typeof(CustomPass), "ReadRenderTargets")] internal static class NativeFadeLightingRetentionPatch { [HarmonyPrefix] private static void Prefix(CustomPass __instance, in RenderGraphBuilder builder) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (__instance is NativeFadePass nativeFadePass) { nativeFadePass.RetainLighting(builder); } } } public sealed class PatchBootstrapper : IDisposable { private readonly Harmony _harmony = new Harmony("Auuueser.EnhancedSpectator"); private readonly List<IPatchModule> _modules = new List<IPatchModule> { new SpectatorLifecyclePatchModule(), new SpectatePreviousPlayerCompatPatchModule(), new PlayerStatusBarsCompatPatchModule() }; private bool _registered; public void Register() { if (_registered) { return; } foreach (IPatchModule module in _modules) { module.Register(_harmony); } _registered = true; ModLog.Debug("Patch modules registered."); } public void Dispose() { if (_registered) { for (int num = _modules.Count - 1; num >= 0; num--) { _modules[num].Unregister(_harmony); } _harmony.UnpatchSelf(); _registered = false; ModLog.Debug("Patch modules unregistered."); } } } internal sealed class PlayerStatusBarsCompatPatchModule : IPatchModule { private const string AssemblyName = "PlayerStatusBars"; private const string TypeName = "OtherPlayerStatusBars.PlayerStatusBarView"; private const string MethodName = "ShouldShowForDistance"; private const string PluginGuid = "playerstatusbars"; private static ConfigEntry<float>? _distance; private Harmony? _harmony; public void Register(Harmony harmony) { _harmony = harmony; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { if (TryPatch(assembly)) { return; } } AppDomain.CurrentDomain.AssemblyLoad += OnAssemblyLoad; } public void Unregister(Harmony harmony) { AppDomain.CurrentDomain.AssemblyLoad -= OnAssemblyLoad; } private void OnAssemblyLoad(object sender, AssemblyLoadEventArgs args) { if (TryPatch(args.LoadedAssembly)) { AppDomain.CurrentDomain.AssemblyLoad -= OnAssemblyLoad; } } private bool TryPatch(Assembly assembly) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown if (assembly.GetName().Name != "PlayerStatusBars") { return false; } MethodInfo methodInfo = assembly.GetType("OtherPlayerStatusBars.PlayerStatusBarView")?.GetMethod("ShouldShowForDistance", BindingFlags.Instance | BindingFlags.NonPublic); if (methodInfo == null) { ModLog.Warning("Player_Status_Bars is installed without its known distance check; in split-screen its bars keep to the large view's distance.", "D:\\111\\game\\lethal company mod\\test mods\\codex\\Enhanced-Spectator-0.4.6-release-candidate\\src\\EnhancedSpectator\\Patching\\PlayerStatusBarsCompatPatchModule.cs", 50); return true; } _harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(PlayerStatusBarsCompatPatchModule).GetMethod("NearestSplitCamera", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); SplitScreenForeignBillboards.MaxDistance = () => (!TryDistance(out var distance)) ? float.PositiveInfinity : distance; ModLog.Info("Player_Status_Bars found: in split-screen each view shows the bars near its own camera."); return true; } private static bool TryDistance(out float distance) { if (_distance == null && Chainloader.PluginInfos.TryGetValue("playerstatusbars", out var value) && (Object)(object)value.Instance != (Object)null) { value.Instance.Config.TryGetEntry<float>("General", "Max Display Distance", ref _distance); } distance = _distance?.Value ?? 0f; return _distance != null; } private static bool NearestSplitCamera(PlayerControllerB ___targetPlayer, ref float distanceSqr, ref bool __result) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) if (!SpectatorVanillaInputGuard.SplitScreenActive || !TryDistance(out var distance) || !SplitScreenForeignBillboards.TryNearestCamera(((Component)___targetPlayer).transform.position, out var distanceSqr2)) { return true; } distanceSqr = distanceSqr2; __result = distanceSqr2 <= distance * distance; return false; } } internal sealed class SpectatePreviousPlayerCompatPatchModule : IPatchModule { private const string AssemblyName = "SpectatePreviousPlayer"; private const string TypeName = "SPP.patch.Patch"; private const string MethodName = "SpectatePreviousPlayer"; private Harmony? _harmony; public void Register(Harmony harmony) { _harmony = harmony; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { if (TryPatch(assembly)) { return; } } AppDomain.CurrentDomain.AssemblyLoad += OnAssemblyLoad; } public void Unregister(Harmony harmony) { AppDomain.CurrentDomain.AssemblyLoad -= OnAssemblyLoad; } private void OnAssemblyLoad(object sender, AssemblyLoadEventArgs args) { if (TryPatch(args.LoadedAssembly)) { AppDomain.CurrentDomain.AssemblyLoad -= OnAssemblyLoad; } } private bool TryPatch(Assembly assembly) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown if (assembly.GetName().Name != "SpectatePreviousPlayer") { return false; } MethodInfo methodInfo = assembly.GetType("SPP.patch.Patch")?.GetMethod("SpectatePreviousPlayer", BindingFlags.Static | BindingFlags.NonPublic); if (methodInfo == null) { ModLog.Warning("SpectatePreviousPlayer is installed without its known right-click switch; in split-screen its right-click may still change the large view.", "D:\\111\\game\\lethal company mod\\test mods\\codex\\Enhanced-Spectator-0.4.6-release-candidate\\src\\EnhancedSpectator\\Patching\\SpectatePreviousPlayerCompatPatchModule.cs", 43); return true; } _harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(SpectatePreviousPlayerCompatPatchModule).GetMethod("SkipInSplitScreen", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ModLog.Info("SpectatePreviousPlayer found: its right-click switch is left to the early-leave vote in split-screen."); return true; } private static bool SkipInSplitScreen() { return !SpectatorVanillaInputGuard.SplitScreenActive; } } [HarmonyPatch(typeof(Canvas), "SendWillRenderCanvases")] internal static class SpectatorCanvasSubmissionPatch { private static int _nextWarning; [HarmonyPrefix] [HarmonyPriority(800)] private static void Prefix() { LethalCompanySplitScreenUiPresentation.Restore(); LethalCompanySpectatorUiVisibility.RestoreRenderers(); } [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix() { try { LethalCompanySpectatorHudAdapter.BeforeSubmit(); LethalCompanySpectatorUiVisibility.BeforeSubmit(); LethalCompanySplitScreenUiPresentation.BeforeSubmit(); } catch (Exception ex) { LethalCompanySplitScreenUiPresentation.Restore(); LethalCompanySpectatorUiVisibility.Clear(); if (Time.frameCount >= _nextWarning) { _nextWarning = Time.frameCount + 300; ModLog.Warning("Spectator HUD render boundary restored after failure: " + ex.Message, "D:\\111\\game\\lethal company mod\\test mods\\codex\\Enhanced-Spectator-0.4.6-release-candidate\\src\\EnhancedSpectator\\Patching\\SpectatorCanvasSubmissionPatch.cs", 34); } } } } [HarmonyPatch(typeof(HUDManager), "SubmitChat_performed")] internal static class SpectatorChatSubmitPatch { [HarmonyPrefix] [HarmonyPriority(200)] private static bool Prefix(HUDManager __instance, CallbackContext context, bool __runOriginal, out bool __state) { __state = ((CallbackContext)(ref context)).performed && __instance.chatTextField.text.Trim().Length > 0; if (__runOriginal) { if (((CallbackContext)(ref context)).performed) { return !LethalCompanyChat.SubmitToGroup(__instance); } return true; } return false; } [HarmonyPostfix] private static void Postfix(HUDManager __instance, CallbackContext context, bool __runOriginal, bool __state) { if (__runOriginal && ((CallbackContext)(ref context)).performed) { LethalCompanyChat.AfterSubmit(__instance, __state); } } } [HarmonyPatch(typeof(HUDManager), "EnableChat_performed")] internal static class SpectatorChatOpenPatch { [HarmonyPostfix] [HarmonyBefore(new string[] { "Aueser.LCChineseProject" })] private static void Postfix(CallbackContext context, bool __runOriginal) { if (__runOriginal && ((CallbackContext)(ref context)).performed) { LethalCompanyChat.OpenForDead(); } } } [HarmonyPatch(typeof(HUDManager), "AddPlayerChatMessageClientRpc")] internal static class SpectatorChatHearPatch { [HarmonyPrefix] private static void Prefix(HUDManager __instance, int playerId, out LethalCompanyChat.Heard __state) { __state = LethalCompanyChat.BeforeHeard(__instance, playerId); } [HarmonyPostfix] private static void Postfix(HUDManager __instance, string chatMessage, int playerId, bool __runOriginal, LethalCompanyChat.Heard __state) { if (__runOriginal) { LethalCompanyChat.AfterHeard(__instance, chatMessage, playerId, __state); } } } [HarmonyPatch(typeof(PlayerControllerB), "IsInSpecialAnimationClientRpc")] internal static class SpectatorToolPosePatch { [HarmonyPrefix] private static void Prefix(PlayerControllerB __instance, bool specialAnimation, float timed, bool climbingLadder) { LethalCompanyFirstPersonPose.ObserveTool(__instance, specialAnimation, timed, climbingLadder); } } [HarmonyPatch(typeof(PlayerControllerB), "UpdatePlayerRotationClientRpc")] internal static class SpectatorLookPosePatch { [HarmonyPrefix] private static void Prefix(PlayerControllerB __instance, short newRot) { LethalCompanyFirstPersonPose.ObserveRotation(__instance, newRot); } } public sealed class SpectatorLifecyclePatchModule : IPatchModule { [HarmonyPatch(typeof(HUDManager), "FillEndGameStats")] private static class EndGameStatsPatch { private static void Postfix(int scrapCollected) { LethalCompanyRoundResults.StatsFilled(scrapCollected); } } [HarmonyPatch(typeof(HUDManager), "ApplyPenalty")] private static class EndGamePenaltyPatch { private static void Postfix() { LethalCompanyRoundResults.PenaltyApplied(); } } [HarmonyPatch(typeof(HUDManager), "SetPlayerLevel")] private static class EndGameLevelPatch { private static void Postfix() { LethalCompanyRoundResults.LevelShown(); } } [HarmonyPatch(typeof(HUDManager), "HideHUD")] private static class EndGameHudPatch { private static void Postfix(bool hide) { if (!hide) { LethalCompanyRoundResults.HudShown(); } } } [HarmonyPatch(typeof(Animator), "SetTrigger", new Type[] { typeof(string) })] private static class EndGameReportTriggerPatch { [HarmonyPrefix] private static void Prefix(Animator __instance, string name) { LethalCompanyRoundResults.ReportTriggered(__instance, name); } } [HarmonyPatch(typeof(StartOfRound), "PassTimeToNextDay")] private static class EndGameDayPassedPatch { private static void Postfix() { LethalCompanyRoundResults.DayPassed(); } } [HarmonyPatch(typeof(PlayerControllerB), "PlayerLookInput")] private static class SpectatorPointerLookPatch { private static bool Prefix(PlayerControllerB __instance) { return !LethalCompanySpectatorRosterCursor.BlocksLook(__instance); } } [HarmonyPatch(typeof(AdjacentRoomCullingModified), "LateUpdate")] private static class SpectatorInteriorCullingPatch { private static void Postfix(AdjacentRoomCullingModified __instance) { SpectatorInteriorVisibility.Refresh(__instance); } } [HarmonyPatch(typeof(AdjacentRoomCullingModified), "RefreshVisibility")] private static class SpectatorInteriorRefreshPatch { private static void Postfix(AdjacentRoomCullingModified __instance) { SpectatorInteriorVisibility.AfterVanillaRefresh(__instance); } } [HarmonyPatch(typeof(StartOfRound), "SetPlayerSafeInShip")] private static class SpectatorEnemyShipRulePatch { private static bool Prefix() { return !SpectatorEnemyVisibility.ShowAllWhileDead(); } } [HarmonyPatch(typeof(EnemyAI), "Start")] private static class SpectatorEnemyStartPatch { private static void Postfix(EnemyAI __instance) { SpectatorEnemyVisibility.Started(__instance); } } [HarmonyPatch(typeof(MaskedPlayerEnemy), "Start")] private static class SpectatorMaskedStartPatch { private static void Postfix(MaskedPlayerEnemy __instance) { SpectatorEnemyVisibility.MaskedStarted(__instance); } } [HarmonyPatch(typeof(LungProp), "Start")] private static class ThermalApparatusPatch { private static void Postfix(LungProp __instance) { SpectatorThermalSources.ApparatusStarted(__instance); } } [HarmonyPatch(typeof(ShotgunItem), "ShootGun")] private static class ThermalShotgunPatch { private static void Postfix(ShotgunItem __instance) { SpectatorThermalSources.GunFired(((Component)__instance.gunShootParticle).transform, __instance.shotgunRayPoint); } } [HarmonyPatch(typeof(PlayerControllerB), "RaycastSpectateCameraAroundPivot")] private static class SpectatorCollisionPatch { private static int _nextDiagnosticFrame; private static bool Prefix(PlayerControllerB __instance) { SpectatorFreecamController? current = SpectatorFreecamController.Current; string reason; bool flag = current != null && current.OwnsCamera && IsLocalSpectatorContext(__instance) && RuntimeConnectionState.CanRunLocalDiagnostics(out reason) && (Object)(object)StartOfRound.Instance != (Object)null && !StartOfRound.Instance.overrideSpectateCamera && __instance.isInGameOverAnimation <= 0f; if (flag && ModLog.IsDebugEnabled && Time.frameCount >= _nextDiagnosticFrame) { _nextDiagnosticFrame = Time.frameCount + 300; ModLog.Debug("Enhanced camera owns pose; skipped vanilla obstacle camera write."); } if (!flag && RuntimeConnectionState.CanRunLocalDiagnostics(out reason)) { SpectatorFreecamController? current2 = SpectatorFreecamController.Current; if (current2 != null && current2.TryGetVanillaDistance(out var distance) && LethalCompanyVanillaDistance.TryApply(__instance, distance)) { return false; } } return !flag; } } [HarmonyPatch(typeof(PlayerControllerB), "KillPlayer", new Type[] { typeof(Vector3), typeof(bool), typeof(CauseOfDeath), typeof(int), typeof(Vector3), typeof(bool) })] private static class PlayerKillPatch { private static void Postfix(PlayerControllerB __instance) { if (IsLocalPlayerOrOwner(__instance)) { SpectatorEnemyVisibility.LocalLifeChanged(); SpectatorLifecycleEvents.Raise(SpectatorLifecycleEventKind.PlayerDied); } } } [HarmonyPatch(typeof(PlayerControllerB), "SetSpectatedPlayerEffects", new Type[] { typeof(bool) })] private static class SpectatedPlayerEffectsPatch { private static void Postfix(PlayerControllerB __instance) { if (IsLocalSpectatorContext(__instance)) { SpectatorInteriorVisibility.TargetChanged(); SpectatorLifecycleEvents.Raise(SpectatorLifecycleEventKind.SpectatedPlayerEffectsApplied); } } } [HarmonyPatch(typeof(StartOfRound), "SwitchCamera", new Type[] { typeof(Camera) })] private static class SwitchCameraPatch { private static void Postfix() { SpectatorLifecycleEvents.Raise(SpectatorLifecycleEventKind.CameraSwitched); } } [HarmonyPatch(typeof(StartOfRound), "SetSpectateCameraToGameOverMode", new Type[] { typeof(bool), typeof(PlayerControllerB) })] private static class GameOverSpectateModePatch { private static void Postfix() { SpectatorLifecycleEvents.Raise(SpectatorLifecycleEventKind.GameOverOverrideChanged); } } [HarmonyPatch(typeof(StartOfRound), "ReviveDeadPlayers")] private static class ReviveDeadPlayersPatch { private static void Postfix() { SpectatorEnemyVisibility.LocalLifeChanged(); SpectatorLifecycleEvents.Raise(SpectatorLifecycleEventKind.Revived); } } [HarmonyPatch(typeof(StartOfRound), "OnPlayerConnectedClientRpc", new Type[] { typeof(ulong), typeof(int), typeof(ulong[]), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(bool) })] private static class PlayerConnectedPatch { private static int _nextDebugFrame; private static void Postfix() { RestoreLocalDeadSpectatorStateAfterPlayerJoin(); } private static void RestoreLocalDeadSpectatorStateAfterPlayerJoin() { if (!RuntimeConnectionState.CanRepairVanillaPlayerState(out string reason)) { LogDebug("Skipped local spectator state restore after player connect: " + reason + "."); return; } StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance == (Object)null) { return; } PlayerControllerB localPlayerController = instance.localPlayerController; if (!((Object)(object)localPlayerController == (Object)null) && IsLocalPlayerOrOwner(localPlayerController) && localPlayerController.isPlayerDead && localPlayerController.isPlayerControlled) { localPlayerController.isPlayerControlled = false; Camera spectateCamera = instance.spectateCamera; if ((Object)(object)spectateCamera != (Object)null && (Object)(object)instance.activeCamera != (Object)(object)spectateCamera) { instance.SwitchCamera(spectateCamera); } LogDebug("Restored local dead spectator state after vanilla player-connect sync."); } } private static void LogDebug(string message) { if (Time.frameCount >= _nextDebugFrame) { _nextDebugFrame = Time.frameCount + 120; ModLog.Debug(message); } } } [HarmonyPatch(typeof(PlayerControllerB), "SpectateNextPlayer", new Type[] { typeof(bool) })] private static class SpectateNextPlayerPatch { private static int _nextSuppressDebugFrame; private static int _nextUnsafeDebugFrame; private static bool Prefix(PlayerControllerB __instance, bool __0, out bool __state) { __state = false; if (!TryGetLocalDeadSpectatorContext(__instance, out string reason)) { if (reason.Length > 0 && Time.frameCount >= _nextUnsafeDebugFrame) { _nextUnsafeDebugFrame = Time.frameCount + 120; ModLog.Debug("Vanilla spectator target switch suppression skipped: " + reason + "."); } return true; } if (RuntimeConnectionState.ShouldSkipVanillaSpectatorTargetSwitch(out string reason2)) { if (Time.frameCount >= _nextUnsafeDebugFrame) { _nextUnsafeDebugFrame = Time.frameCount + 120; ModLog.Debug("Skipped vanilla spectator target switch during unsafe lifecycle: " + reason2 + "."); } return false; } string reason3; bool num = TryGetLocalSpectatorContext(__instance, out reason3); if (!num && reason3.Length > 0 && Time.frameCount >= _nextUnsafeDebugFrame) { _nextUnsafeDebugFrame = Time.frameCount + 120; ModLog.Debug("Vanilla spectator target switch suppression skipped: " + reason3 + "."); } if (num && SpectatorVanillaInputGuard.ShouldSuppressTargetSwitchInput(out string reason4, (Object)(object)__instance.spectatedPlayerScript == (Object)null || __instance.spectatedPlayerScript.isPlayerDead)) { if (Time.frameCount >= _nextSuppressDebugFrame) { _nextSuppressDebugFrame = Time.frameCount + 120; ModLog.Debug("Suppressed vanilla spectator target switch while " + ((reason4.Length > 0) ? reason4 : "quick menu is open") + "."); } return false; } SpectatorFreecamController.Current?.BeginVanillaTargetSwitch(__0); __state = true; return true; } private static void Postfix(bool __0, bool __state) { if (__state) { SpectatorFreecamController.Current?.EndVanillaTargetSwitch(__0); } } private static bool TryGetLocalDeadSpectatorContext(PlayerControllerB player, out string reason) { reason = string.Empty; if ((Object)(object)player == (Object)null) { reason = "patch instance unavailable"; return false; } StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance == (Object)null) { reason = "round unavailable"; return false; } PlayerControllerB localPlayerController = instance.localPlayerController; if ((Object)(object)localPlayerController == (Object)null) { reason = "local player unavailable"; return false; } if (!IsLocalPlayerOrOwner(player, localPlayerController)) { return false; } if (!localPlayerController.isPlayerDead) { return false; } return true; } private static bool TryGetLocalSpectatorContext(PlayerControllerB player, out string reason) { reason = string.Empty; if ((Object)(object)player == (Object)null) { reason = "patch instance unavailable"; return false; } StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance == (Object)null) { reason = "round unavailable"; return false; } PlayerControllerB localPlayerController = instance.localPlayerController; if ((Object)(object)localPlayerController == (Object)null) { reason = "local player unavailable"; return false; } if (!IsLocalPlayerOrOwner(player, localPlayerController)) { return false; } if (!localPlayerController.isPlayerDead) { return false; } if ((Object)(object)instance.spectateCamera == (Object)null || (Object)(object)localPlayerController.spectatedPlayerScript == (Object)null) { reason = "spectator camera or target unavailable"; return false; } return true; } } [HarmonyPatch(typeof(PlayerControllerB), "Interact_performed", new Type[] { typeof(CallbackContext) })] private static class InteractPerformedPatch { private static int _nextSuppressDebugFrame; private static bool Prefix(PlayerControllerB __instance) { if (!ShouldSuppressQuickMenuGameplayInput(__instance, out string reason)) { return true; } LogQuickMenuGameplaySuppression("interact", reason, ref _nextSuppressDebugFrame); return false; } } [HarmonyPatch(typeof(PlayerControllerB), "ActivateItem_performed", new Type[] { typeof(CallbackContext) })] private static class ActivateItemPerformedPatch { private static int _nextSuppressDebugFrame; private static bool Prefix(PlayerControllerB __instance) { if (!ShouldSuppressQuickMenuGameplayInput(__instance, out string reason)) { return true; } LogQuickMenuGameplaySuppression("activate item", reason, ref _nextSuppressDebugFrame); return false; } } public void Register(Harmony harmony) { harmony.CreateClassProcessor(typeof(NativeFadeCameraPatch)).Patch(); harmony.CreateClassProcessor(typeof(SpectatorPresentationPatch)).Patch(); harmony.CreateClassProcessor(typeof(SpectatorPresentationFramesPatch)).Patch(); harmony.CreateClassProcessor(typeof(NativeFadeOtherPassPatch)).Patch(); harmony.CreateClassProcessor(typeof(NativeFadeLightingCapturePatch)).Patch(); harmony.CreateClassProcessor(typeof(NativeFadeLightingRetentionPatch)).Patch(); harmony.CreateClassProcessor(typeof(SpectatorCanvasSubmissionPatch)).Patch(); harmony.CreateClassProcessor(typeof(SpectatorToolPosePatch)).Patch(); harmony.CreateClassProcessor(typeof(SpectatorLookPosePatch)).Patch(); harmony.CreateClassProcessor(typeof(SpectatorCollisionPatch)).Patch(); harmony.CreateClassProcessor(typeof(PlayerKillPatch)).Patch(); harmony.CreateClassProcessor(typeof(SpectatedPlayerEffectsPatch)).Patch(); harmony.CreateClassProcessor(typeof(SpectatorInteriorCullingPatch)).Patch(); harmony.CreateClassProcessor(typeof(SpectatorInteriorRefreshPatch)).Patch(); harmony.CreateClassProcessor(typeof(SpectatorEnemyShipRulePatch)).Patch(); harmony.CreateClassProcessor(typeof(SpectatorEnemyStartPatch)).Patch(); harmony.CreateClassProcessor(typeof(SpectatorMaskedStartPatch)).Patch(); harmony.CreateClassProcessor(typeof(ThermalApparatusPatch)).Patch(); harmony.CreateClassProcessor(typeof(ThermalShotgunPatch)).Patch(); harmony.CreateClassProcessor(typeof(SwitchCameraPatch)).Patch(); harmony.CreateClassProcessor(typeof(GameOverSpectateModePatch)).Patch(); harmony.CreateClassProcessor(typeof(ReviveDeadPlayersPatch)).Patch(); harmony.CreateClassProcessor(typeof(PlayerConnectedPatch)).Patch(); harmony.CreateClassProcessor(typeof(SpectateNextPlayerPatch)).Patch(); harmony.CreateClassProcessor(typeof(InteractPerformedPatch)).Patch(); harmony.CreateClassProcessor(typeof(ActivateItemPerformedPatch)).Patch(); harmony.CreateClassProcessor(typeof(SpectatorPointerLookPatch)).Patch(); harmony.CreateClassProcessor(typeof(EndGameStatsPatch)).Patch(); harmony.CreateClassProcessor(typeof(EndGamePenaltyPatch)).Patch(); harmony.CreateClassProcessor(typeof(EndGameLevelPatch)).Patch(); harmony.CreateClassProcessor(typeof(EndGameHudPatch)).Patch(); harmony.CreateClassProcessor(typeof(EndGameReportTriggerPatch)).Patch(); harmony.CreateClassProcessor(typeof(EndGameDayPassedPatch)).Patch(); harmony.CreateClassProcessor(typeof(SpectatorChatSubmitPatch)).Patch(); harmony.CreateClassProcessor(typeof(SpectatorChatOpenPatch)).Patch(); harmony.CreateClassProcessor(typeof(SpectatorChatHearPatch)).Patch(); } public void Unregister(Harmony harmony) { } private static bool IsLocalSpectatorContext(PlayerControllerB player) { if (IsLocalPlayerOrOwner(player)) { return true; } PlayerControllerB localPlayer = GetLocalPlayer(); if ((Object)(object)localPlayer != (Object)null && localPlayer.isPlayerDead) { return (Object)(object)localPlayer.spectatedPlayerScript == (Object)(object)player; } return false; } private static bool IsLocalPlayerOrOwner(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return false; } if ((Object)(object)GetLocalPlayer() == (Object)(object)player) { return true; } if (!((NetworkBehaviour)player).IsOwner) { return ((NetworkBehaviour)player).IsLocalPlayer; } return true; } private static bool IsLocalPlayerOrOwner(PlayerControllerB player, PlayerControllerB localPlayer) { if ((Object)(object)player == (Object)null) { return false; } if ((Object)(object)localPlayer == (Object)(object)player) { return true; } if (!((NetworkBehaviour)player).IsOwner) { return ((NetworkBehaviour)player).IsLocalPlayer; } return true; } private static PlayerControllerB? GetLocalPlayer() { StartOfRound instance = StartOfRound.Instance; if (!((Object)(object)instance != (Object)null)) { return null; } return instance.localPlayerController; } private static bool ShouldSuppressQuickMenuGameplayInput(PlayerControllerB player, out string reason) { reason = string.Empty; if (!SpectatorVanillaInputGuard.ShouldSuppressGameplayInteractInput() && !IsLocalQuickMenuOpen()) { return false; } PlayerControllerB localPlayer = GetLocalPlayer(); if ((Object)(object)localPlayer == (Object)null) { reason = "local player unavailable"; return false; } if (!IsLocalPlayerOrOwner(player, localPlayer)) { return false; } reason = (SpectatorPointerCapture.IsActive ? "viewer-list pointer is active" : "quick menu is open"); return true; } private static bool IsLocalQuickMenuOpen() { PlayerControllerB localPlayer = GetLocalPlayer(); if ((Object)(object)localPlayer != (Object)null && (Object)(object)localPlayer.quickMenuManager != (Object)null) { return localPlayer.quickMenuManager.isMenuOpen; } return false; } private static void LogQuickMenuGameplaySuppression(string inputName, string reason, ref int nextSuppressDebugFrame) { if (Time.frameCount >= nextSuppressDebugFrame) { nextSuppressDebugFrame = Time.frameCount + 120; ModLog.Debug("Suppressed local " + inputName + " input while " + reason + "."); } } } [HarmonyPatch(typeof(HDCamera), "UpdateVolumeAndPhysicalParameters")] internal static class SpectatorPresentationPatch { [HarmonyPrefix] [HarmonyPriority(800)] private static void Prefix(HDCamera __instance) { LethalCompanySpectatorPresentation.BeforeVolumeUpdate(__instance); } [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(HDCamera __instance) { LethalCompanySpectatorPresentation.AfterVolumeUpdate(__instance); } } [HarmonyPatch(typeof(HDCamera), "Update")] internal static class SpectatorPresentationFramesPatch { [HarmonyPrefix] [HarmonyPriority(0)] private static void Prefix(HDCamera __instance, ref FrameSettings currentFrameSettings) { LethalCompanySpectatorPresentation.Prepare(__instance, ref currentFrameSettings); } } } namespace EnhancedSpectator.Networking { public sealed class EnhancedSpectatorNetworkService : IEnhancedSpectatorNetworkService { private const float CapabilityStableDelaySeconds = 0.35f; private const int CapabilityStableDelayFrames = 3; private const float CompatiblePeerProbeTimeoutSeconds = 2.5f; private const float CapabilityProbeRetryIntervalSeconds = 2.5f; private const float SpectatorPoseHeartbeatIntervalSeconds = 0.5f; private readonly EnhancedSpectatorConfig _config; private readonly ISpectatorTargetStateProvider _spectatorTargetStateProvider; private readonly ISpectatorPoseStateProvider _spectatorPoseStateProvider; private readonly IPeerIdentityStateProvider _peerIdentityStateProvider; private readonly IVoiceActivityProvider _voiceActivityProvider; private readonly IModNetworkTransport _transport; private readonly INetworkRuntimeState _runtimeState; private readonly RemotePeerRegistry _peerRegistry = new RemotePeerRegistry(); private readonly RemoteSpectatorTargetRegistry _remoteTargetRegistry = new RemoteSpectatorTargetRegistry(); private readonly RemoteSpectatorPoseRegistry _remotePoseRegistry = new RemoteSpectatorPoseRegistry(); private readonly RemotePeerIdentityRegistry _remoteIdentityRegistry = new RemotePeerIdentityRegistry(); private readonly RemoteVoiceActivityRegistry _remoteVoiceActivityRegistry = new RemoteVoiceActivityRegistry(); private readonly VoiceActivityDebugLimiter _voiceDebugLimiter = new VoiceActivityDebugLimiter(); private SpectatorTargetState? _lastObservedTargetState; private SpectatorTargetState? _lastSentTargetState; private SpectatorTargetState? _pendingTargetState; private SpectatorPoseState? _lastObservedPoseState; private SpectatorPoseState? _lastSentPoseState; private SpectatorPoseState? _pendingPoseState; private bool _pendingPoseRefresh; private VoiceActivityState? _lastObservedVoiceActivityState; private VoiceActivityState? _lastSentVoiceActivityState; private VoiceActivityState? _pendingVoiceActivityState; private PeerIdentityState? _lastSentIdentityState; private bool _pendingVoiceActivityRefresh; private bool _initialized; private bool _networkAvailable; private bool _targetSyncReady; private bool _hasCompatibleModPeer; private bool _noCompatiblePeerLocalOnly; private bool _capabilitySent; private float _capabilityProbeSentRealtime = -1f; private ulong? _lastLocalClientId; private float _nextTargetSyncTime; private float _nextPoseSyncTime; private float _nextVoiceActivitySyncTime; private float _nextTargetSampleTime; private float _nextPoseSampleTime; private float _lastPoseSampleTime = -1f; private float _nextPoseRefreshTime; private float _nextVoiceActivitySampleTime; private float _nextVoiceActivityRefreshTime; private float _nextPeerPruneTime; private float _transportRegisteredRealtime; private int _transportRegisteredFrame = -1; private int _nextLifecycleDebugFrame; private int _nextCapabilityDelayDebugFrame; private string? _lastDegradationReason; private string? _lastTargetSyncWaitReason; private NetworkLifecycleState _lifecycleState; private readonly Dictionary<ulong, float> _streamBroadcastAt = new Dictionary<ulong, float>(); private readonly List<ulong> _streamRecipients = new List<ulong>(); public bool IsNetworkAvailable => _networkAvailable; public bool IsTargetSyncEnabled => _targetSyncReady; public bool HasCompatibleModPeer => _hasCompatibleModPeer; public NetworkLifecycleState LifecycleState => _lifecycleState; public int RemotePeerIdentityRevision => _remoteIdentityRegistry.Revision; public int RemoteSpectatorTargetRevision => _remoteTargetRegistry.Revision; public EnhancedSpectatorNetworkService(EnhancedSpectatorConfig config, SpectatorModule spectatorModule) : this(config, spectatorModule, spectatorModule, spectatorModule, new LethalCompanyVoiceActivityProvider(), new UnityNetcodeMessagingTransport(() => config.DebugNetworkMessages.Value), UnityNetworkRuntimeState.Instance) { } public EnhancedSpectatorNetworkService(EnhancedSpectatorConfig config, ISpectatorTargetStateProvider spectatorTargetStateProvider, ISpectatorPoseStateProvider spectatorPoseStateProvider, IPeerIdentityStateProvider peerIdentityStateProvider, IVoiceActivityProvider voiceActivityProvider, IModNetworkTransport transport) : this(config, spectatorTargetStateProvider, spectatorPoseStateProvider, peerIdentityStateProvider, voiceActivityProvider, transport, UnityNetworkRuntimeState.Instance) { } public EnhancedSpectatorNetworkService(EnhancedSpectatorConfig config, ISpectatorTargetStateProvider spectatorTargetStateProvider, ISpectatorPoseStateProvider spectatorPoseStateProvider, IPeerIdentityStateProvider peerIdentityStateProvider, IVoiceActivityProvider voiceActivityProvider, IModNetworkTransport transport, INetworkRuntimeState runtimeState) { _config = config ?? throw new ArgumentNullException("config"); _spectatorTargetStateProvider = spectatorTargetStateProvider ?? throw new ArgumentNullException("spectatorTargetStateProvider"); _spectatorPoseStateProvider = spectatorPoseStateProvider ?? throw new ArgumentNullException("spectatorPoseStateProvider"); _peerIdentityStateProvider = peerIdentityStateProvider ?? throw new ArgumentNullException("peerIdentityStateProvider"); _voiceActivityProvider = voiceActivityProvider ?? throw new ArgumentNullException("voiceActivityProvider"); _transport = transport ?? throw new ArgumentNullException("transport"); _runtimeState = runtimeState ?? throw new ArgumentNullException("runtimeState"); } public void Initialize() { if (!_initialized) { _initialized = true; _lifecycleState = NetworkLifecycleState.LocalOnly; ModLog.Debug("Networking service initialized."); } } public void Tick() { if (!_initialized) { return; } try { string reason; if (!_config.EnableNetworking.Value) { Degrade("networking config disabled"); } else if (!_runtimeState.CanUseModNetworking(out reason)) { StopNetworkingForLifecycle(reason); } else if (EnsureTransportRegistered()) { _networkAvailable = true; _lifecycleState = NetworkLifecycleState.TransportRegistered; RegisterLocalCapability(); PruneDisconnectedPeers(); SendLocalCapabilityIfNeeded(); UpdateTargetSyncReadiness(); UpdateCompatiblePeerProbeState(); if (!NetworkCompatibilityPolicy.ShouldRunBusinessSync(_lifecycleState, _targetSyncReady)) { ClearBusinessSyncState(); return; } UpdateAndSendLocalPeerIdentity(); UpdateLocalSpectatorTargetIfDue(); UpdateLocalSpectatorPoseIfDue(); UpdateLocalVoiceActivityIfDue(); UpdateTargetSyncReadiness(); TrySendPendingTargetState(); TrySendPendingPoseState(); TrySendPendingVoiceActivityState(); } } catch (Exception ex) { Degrade("networking exception: " + ex.GetType().Name); ModLog.Error($"Enhanced Spectator networking failed and degraded to local-only mode: {ex}", "D:\\111\\game\\lethal company mod\\test mods\\codex\\Enhanced-Spectator-0.4.6-release-candidate\\src\\EnhancedSpectator\\Networking\\EnhancedSpectatorNetworkService.cs", 217); } } public void Dispose() { _transport.Dispose(); ClearNetworkState(); _initialized = false; _lifecycleState = NetworkLifecycleState.Disposed; ModLog.Debug("Networking service disposed."); } public bool TryGetPeerCapability(ulong clientId, out ModPeerCapability capability) { return _peerRegistry.TryGetCapability(clientId, out capability); } public bool TryGetRemoteSpectatorTarget(ulong clientId, out SpectatorTargetState state) { return _remoteTargetRegistry.TryGet(clientId, out state); } public bool TryGetRemoteSpectatorPose(ulong clientId, out SpectatorPoseState state) { return _remotePoseRegistry.TryGet(clientId, out state); } internal double CameraReceivedAt(ulong clientId) { return _remotePoseRegistry.ReceivedAt(clientId); } public bool TryGetRemotePeerIdentity(ulong clientId, out PeerIdentityState state) { return _remoteIdentityRegistry.TryGet(clientId, out state); } public bool TryGetRemoteVoiceActivity(ulong clientId, out VoiceActivityState state) { if (!_remoteVoiceActivityRegistry.TryGet(clientId, out state, out var receivedAtTicks)) { return false; } long ticks = TimeSpan.FromSeconds(Mathf.Max(0f, _config.VoiceActivityStaleSeconds.Value)).Ticks; if (VoiceActivitySyncRules.IsFresh(receivedAtTicks, _runtimeState.UtcNowTicks, ticks)) { return true; } DebugVoice($"Remote voice activity expired: peer={clientId}."); _remoteVoiceActivityRegistry.Remove(clientId); state = VoiceActivityState.NoData; return false; } public IReadOnlyList<SpectatorTargetState> GetRemoteSpectatorTargets() { return _remoteTargetRegistry.GetSnapshot().AsReadOnly(); } public void CopyRemoteSpectatorTargetsTo(List<SpectatorTargetState> destination) { if (destination == null) { throw new ArgumentNullException("destination"); } _remoteTargetRegistry.CopySnapshotTo(destination); } public IReadOnlyList<SpectatorPoseState> GetRemoteSpectatorPoses() { return _remotePoseRegistry.GetSnapshot().AsReadOnly(); } public IReadOnlyList<PeerIdentityState> GetRemotePeerIdentities() { return _remoteIdentityRegistry.GetSnapshot().AsReadOnly(); } public void CopyRemotePeerIdentitiesTo(List<PeerIdentityState> destination) { if (destination == null) { throw new ArgumentNullException("destination"); } _remoteIdentityRegistry.CopySnapshotTo(destination); } public IReadOnlyList<VoiceActivityState> GetRemoteVoiceActivities() { return _remoteVoiceActivityRegistry.GetSnapshot().AsReadOnly(); } public IReadOnlyList<ModPeerCapability> GetKnownModdedPeers() { return _peerRegistry.GetCapabilitiesSnapshot().AsReadOnly(); } private bool EnsureTransportRegistered() { if (_transport.IsRegistered) { if (!_transport.IsNetworkAvailable) { Degrade("custom messaging transport no longer available"); return false; } return true; } if (!_transport.TryRegister(OnCapabilityReceived, OnSpectatorTargetReceived, OnSpectatorPoseReceived, OnPeerIdentityReceived, OnVoiceActivityReceived, out string reason)) { Degrade(reason); return false; } _capabilitySent = false; _capabilityProbeSentRealtime = -1f; _noCompatiblePeerLocalOnly = false; _lastLocalClientId = _transport.LocalClientId; _transportRegisteredFrame = _runtimeState.FrameCount; _transportRegisteredRealtime = _runtimeState.RealtimeSinceStartup; _lastDegradationReason = null; Debug("Custom messaging transport registered."); return true; } private void RegisterLocalCapability() { ulong localClientId = _transport.LocalClientId; if (_lastLocalClientId.HasValue && _lastLocalClientId.Value != localClientId) { _peerRegistry.Clear(); _remoteTargetRegistry.Clear(); _remotePoseRegistry.Clear(); _remoteIdentityRegistry.Clear(); _remoteVoiceActivityRegistry.Clear(); _lastObservedTargetState = null; _lastSentTargetState = null; _pendingTargetState = null; _lastObservedPoseState = null; _lastSentPoseState = null; _pendingPoseState = null; _pendingPoseRefresh = false; _lastObservedVoiceActivityState = null; _lastSentVoiceActivityState = null; _pendingVoiceActivityState = null; _pendingVoiceActivityRefresh = false; _lastSentIdentityState = null; _nextTargetSyncTime = 0f; _nextPoseSyncTime = 0f; _nextVoiceActivitySyncTime = 0f; _nextTargetSampleTime = 0f; _nextPoseSampleTime = 0f; _lastPoseSampleTime = -1f; _nextPoseRefreshTime = 0f; _nextVoiceActivitySampleTime = 0f; _nextVoiceActivityRefreshTime = 0f; _capabilitySent = false; _capabilityProbeSentRealtime = -1f; _noCompatiblePeerLocalOnly = false; _transportRegisteredFrame = _runtimeState.FrameCount; _transportRegisteredRealtime = _runtimeState.RealtimeSinceStartup; Debug($"Local Netcode client id changed from {_lastLocalClientId.Value} to {localClientId}; reset network state."); } _lastLocalClientId = localClientId; _peerRegistry.RegisterLocal(CreateLocalCapability(localClientId)); } private void SendLocalCapabilityIfNeeded() { if (!_config.EnableCapabilityHandshake.Value) { _capabilitySent = false; } else { if (_capabilitySent && !NetworkCompatibilityPolicy.ShouldRetryCapabilityProbe(_targetSyncReady, _capabilitySent, _capabilityProbeSentRealtime, _runtimeState.RealtimeSinceStartup, 2.5f)) { return; } if (!_runtimeState.CanUseModNetworking(out string reason)) { StopNetworkingForLifecycle(reason); return; } if (!IsTransportStableForCapability(out string reason2)) { DebugCapabilityDelay(reason2); return; } ModPeerCapability modPeerCapability = CreateLocalCapability(_transport.LocalClientId); _peerRegistry.RegisterLocal(modPeerCapability); if (_transport.SendCapability(modPeerCapability, null, out string reason3)) { _capabilitySent = true; _capabilityProbeSentRealtime = _runtimeState.RealtimeSinceStartup; _noCompatiblePeerLocalOnly = false; _lifecycleState = NetworkLifecycleState.TransportRegistered; Debug($"Capability sent: client={modPeerCapability.ClientId}, targetSync={modPeerCapability.SupportsSpectatorTargetSync}, voiceSync={modPeerCapability.SupportsVoiceActivitySync}, voiceRoute={modPeerCapability.SupportsSpectatorVoiceToTarget}."); } else { Degrade("capability send failed: " + reason3); } } } private bool IsTransportStableForCapability(out string reason) { int num = _runtimeState.FrameCount - _transportRegisteredFrame; if (_transportRegisteredFrame < 0 || num < 3) { reason = $"transport registered {Mathf.Max(0, num)} frame(s) ago"; return false; } float num2 = _runtimeState.RealtimeSinceStartup - _transportRegisteredRealtime; if (num2 < 0.35f) { reason = $"transport registered {num2:0.00}s ago"; return false; } reason = string.Empty; return true; } private void UpdateAndSendLocalPeerIdentity() { if (!_capabilitySent || !_targetSyncReady || !_peerIdentityStateProvider.TryGetLocalPeerIdentity(out PeerIdentityState state) || string.IsNullOrWhiteSpace(state.DisplayName) || IdentityEquals(_lastSentIdentityState, state)) { return; } List<ulong> spectatorTargetSyncPeerIds = _peerRegistry.GetSpectatorTargetSyncPeerIds(_transport.LocalClientId); if (spectatorTargetSyncPeerIds.Count != 0) { if (_transport.SendPeerIdentity(state, spectatorTargetSyncPeerIds, out string reason)) { _lastSentIdentityState = state; Debug($"Peer identity sent: client={state.ClientId}, slot={state.PlayerSlotId}, name={state.DisplayName}, voiceName={FormatVoiceName(state.VoicePlayerName)}."); } else { Degrade("peer identity send failed: " + reason); } } } private void PruneDisconnectedPeers(bool force = false) { if (!force && _runtimeState.UnscaledTime < _nextPeerPruneTime) { return; } _nextPeerPruneTime = _runtimeState.UnscaledTime + 1f; if (!_lastLocalClientId.HasValue) { return; } foreach (ulong remotePeerId in _peerRegistry.GetRemotePeerIds(_lastLocalClientId.Value)) { if ((_transport.IsHost || !_peerRegistry.IsRelayedPeer(remotePeerId)) && !_transport.IsPeerConnected(remotePeerId)) { RelayDisconnectedPeerCleanup(remotePeerId); _peerRegistry.Remove(remotePeerId); _remoteTargetRegistry.Remove(remotePeerId); _remotePoseRegistry.Remove(remotePeerId); _remoteIdentityRegistry.Remove(remotePeerId); _remoteVoiceActivityRegistry.Remove(remotePeerId); Debug($"Removed disconnected network peer state: peer={remotePeerId}."); } } } private void UpdateTargetSyncReadiness() { string text = null; if (!_config.EnableCapabilityHandshake.Value) { text = "capability handshake disabled"; } else if (!_config.EnableSpectatorTargetSync.Value) { text = "spectator target sync disabled"; } else if (!_transport.IsRegistered) { text = "custom messaging transport not registered"; } else if (!_peerRegistry.HasSpectatorTargetSyncPeer(_transport.LocalClientId)) { text = "waiting for compatible remote peer capability"; } _targetSyncReady = text == null; _hasCompatibleModPeer = _targetSyncReady; if (_config.DebugNetworkMessages.Value && _lastTargetSyncWaitReason != text) { _lastTargetSyncWaitReason = text; if (text == null) { ModLog.Debug("Spectator target sync is ready."); } else { ModLog.Debug("Spectator target sync is not ready: " + text + "."); } } } private void UpdateCompatiblePeerProbeState() { _lifecycleState = NetworkCompatibilityPolicy.ResolveLifecycleState(_targetSyncReady, _capabilitySent, _capabilityProbeSentRealtime, _runtimeState.RealtimeSinceStartup, 2.5f); _noCompatiblePeerLocalOnly = _lifecycleState == NetworkLifecycleState.NoCompatiblePeerLocalOnly; if (_noCompatiblePeerLocalOnly && _lastDegradationReason != "no compatible Enhanced Spectator peer capability received") { _lastDegradationReason = "no compatible Enhanced Spectator peer capability received"; Debug("Networking remains local-only because no compatible Enhanced Spectator peer answered the capability probe."); } } private void ClearBusinessSyncState() { _lastObservedTargetState = null; _lastSentTargetState = null; _pendingTargetState = null; _lastObservedPoseState = null; _lastSentPoseState = null; _pendingPoseState = null; _pendingPoseRefresh = false; _lastObservedVoiceActivityState = null; _lastSentVoiceActivityState = null; _pendingVoiceActivityState = null; _pendingVoiceActivityRefresh = false; _lastSentIdentityState = null; _nextTargetSampleTime = 0f; _nextPoseSampleTime = 0f; _lastPoseSampleTime = -1f; _nextPoseRefreshTime = 0f; _nextVoiceActivitySampleTime = 0f; } private void UpdateLocalSpectatorTargetIfDue() { if (!_config.EnableSpectatorTargetSync.Value) { _lastObservedTargetState = null; _lastSentTargetState = null; _pendingTargetState = null; } else if (NetworkSyncSamplingRules.ShouldSample(_lastObservedTargetState != null, _runtimeState.UnscaledTime, _nextTargetSampleTime)) { UpdateLocalSpectatorTarget(); _nextTargetSampleTime = NetworkSyncSamplingRules.ResolveNextSampleTime(_runtimeState.UnscaledTime, 0.1f); } } private void UpdateLocalSpectatorTarget() { if (!_spectatorTargetStateProvider.TryGetCurrentSpectatorTarget(out SpectatorTargetState state)) { state = new SpectatorTargetState(isSpectating: false, _transport.LocalClientId, 0uL, null, null, _runtimeState.UtcNowTicks); } if (_lastObservedTargetState == null || !_lastObservedTargetState.Equals(state)) { _lastObservedTargetState = state; if (_lastSentTargetState != null && _lastSentTargetState.Equals(state)) { _pendingTargetState = null; } else { _pendingTargetState = state; } Debug($"Observed spectator target change: spectating={state.IsSpectating}, localClient={state.LocalClientId}, localSlot={state.LocalPlayerSlotId}, targetClient={FormatNullable(state.TargetClientId)}, targetSlot={FormatNullable(state.TargetPlayerSlotId)}."); } } private void UpdateLocalSpectatorPoseIfDue() { if (!_config.EnableSpectatorPoseSync.Value) { _lastObservedPoseState = null; _lastSentPoseState = null; _pendingPoseState = null; _pendingPoseRefresh = false; _lastPoseSampleTime = -1f; } else if (NetworkSyncSamplingRules.ShouldSample(_lastObservedPoseState != null, _runtimeState.UnscaledTime, _nextPoseSampleTime)) { float unscaledTime = _runtimeState.UnscaledTime; float sampleDeltaTime = ((_lastPoseSampleTime >= 0f) ? (unscaledTime - _lastPoseSampleTime) : 0f); bool num = UpdateLocalSpectatorPose(sampleDeltaTime); _lastPoseSampleTime = unscaledTime; _nextPoseSampleTime = NetworkSyncSamplingRules.ResolveNextSampleTime(unscaledTime, RemoteSpectatorPoseNetworkRateRules.ResolveSamplingInterval(GetPoseSyncInterval())); if (num) { _nextPoseSyncTime = Mathf.Min(_nextPoseSyncTime, unscaledTime); } } } private void TrySendPendingTargetState() { if (!_targetSyncReady || _pendingTargetState == null) { return; } string reason; if (!_transport.IsRegistered || !_transport.IsNetworkAvailable) { StopNetworkingForLifecycle("custom messaging transport unavailable before target send"); } else if (!_runtimeState.CanUseModNetworking(out reason)) { StopNetworkingForLifecycle(reason); } else if (_lastSentTargetState != null && _lastSentTargetState.Equals(_pendingTargetState)) { _pendingTargetState = null; } else { if (_runtimeState.UnscaledTime < _nextTargetSyncTime) { return; } List<ulong> spectatorTargetSyncPeerIds = _peerRegistry.GetSpectatorTargetSyncPeerIds(_transport.LocalClientId); if (spectatorTargetSyncPeerIds.Count == 0) { UpdateTargetSyncReadiness(); return; } SpectatorTargetSyncMessage spectatorTargetSyncMessage = new SpectatorTargetSyncMessage(1, _pendingTargetState, _runtimeState.UtcNowTicks); if (_transport.SendSpectatorTarget(spectatorTargetSyncMessage, spectatorTargetSyncPeerIds, out string reason2)) { _lastSentTargetState = _pendingTargetState; _pendingTargetState = null; _nextTargetSyncTime = _runtimeState.UnscaledTime + 0.1f; Debug($"Spectator target sent to {spectatorTargetSyncPeerIds.Count} peer(s): spectating={spectatorTargetSyncMessage.State.IsSpectating}, targetClient={FormatNullable(spectatorTargetSyncMessage.State.TargetClientId)}, targetSlot={FormatNullable(spectatorTargetSyncMessage.State.TargetPlayerSlotId)}."); } else { Degrade("spectator target send failed: " + reason2); } } } private bool UpdateLocalSpectatorPose(float sampleDeltaTime) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: 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_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) if (!_config.EnableSpectatorPoseSync.Value) { _lastObservedPoseState = null; _lastSentPoseState = null; _pendingPoseState = null; _pendingPoseRefresh = false; return false; } if (!_spectatorPoseStateProvider.TryGetCurrentSpectatorPose(out SpectatorPoseState state)) { state = new SpectatorPoseState(isSpectating: false, _transport.LocalClientId, 0uL, null, null, Vector3.zero, Quaternion.identity, _runtimeState.UtcNowTicks, hasMotionReference: false, default(Vector3), default(Quaternion), hasTargetMotionReference: false, default(Vector3), default(Quaternion), modelStowed: false, autoCentering: false, SpectatorSplitView.None, null, firstPersonView: false, 0, 0); } bool result = RemoteSpectatorPoseNetworkRateRules.ShouldUseBurstRate(_lastObservedPoseState, state, sampleDeltaTime); if (StreamsCamera(state)) { SpectatorPoseState? lastObservedPoseState = _lastObservedPoseState; if (lastObservedPoseState == null || !lastObservedPoseState.CameraTimeline) { _nextPoseSyncTime = _runtimeState.UnscaledTime; } _lastObservedPoseState = (_pendingPoseState = state.AsCameraTimeline()); _pendingPoseRefresh = true; return false; } if (_lastObservedPoseState != null && _lastObservedPoseState.ApproximatelyEquals(state)) { if (NetworkSyncSamplingRules.ShouldRefreshUnchangedState(state.IsSpectating, _lastSentPoseState != null && _lastSentPoseState.IsSpectating, _runtimeState.UnscaledTime, _nextPoseRefreshTime)) { _pendingPoseState = state; _pendingPoseRefresh = true; } return result; } _lastObservedPoseState = state; if (_lastSentPoseState != null && _lastSentPoseState.ApproximatelyEquals(state)) { _pendingPoseState = null; _pendingPoseRefresh = false; } else { _pendingPoseState = state; _pendingPoseRefresh = false; } if (IsPoseDebugEnabled()) { ModLog.Debug($"Observed spectator pose change: spectating={state.IsSpectating}, localClient={state.LocalClientId}, targetClient={FormatNullable(state.TargetClientId)}, position={FormatVector(state.Position)}."); } return result; } private void UpdateLocalVoiceActivityIfDue() { if (!_config.EnableVoiceActivitySync.Value) { _lastObservedVoiceActivityState = null; _lastSentVoiceActivityState = null; _pendingVoiceActivityState = null; _pendingVoiceActivityRefresh = false; } else if (NetworkSyncSamplingRules.ShouldSample(_lastObservedVoiceActivityState != null, _runtimeState.UnscaledTime, _nextVoiceActivitySampleTime)) { UpdateLocalVoiceActivity(); _nextVoiceActivitySampleTime = NetworkSyncSamplingRules.ResolveNextSampleTime(_runtimeState.UnscaledTime, GetVoiceActivitySyncInterval()); } } private void TrySendPendingPoseState() { //IL_01a0: Unknown result type (might be due to invalid IL or missing references) if (!_targetSyncReady || !_config.EnableSpectatorPoseSync.Value || _pendingPoseState == null) { return; } string reason; if (!_transport.IsRegistered || !_transport.IsNetworkAvailable) { StopNetworkingForLifecycle("custom messaging transport unavailable before pose send"); } else if (!_runtimeState.CanUseModNetworking(out reason)) { StopNetworkingForLifecycle(reason); } else if (!_pendingPoseRefresh && _lastSentPoseState != null && _lastSentPoseState.ApproximatelyEquals(_pendingPoseState)) { _pendingPoseState = null; } else { if (_runtimeState.UnscaledTime < _nextPoseSyncTime) { return; } List<ulong> spectatorTargetSyncPeerIds = _peerRegistry.GetSpectatorTargetSyncPeerIds(_transport.LocalClientId); if (spectatorTargetSyncPeerIds.Count == 0) { UpdateTargetSyncReadiness(); return; } SpectatorPoseSyncMessage spectatorPoseSyncMessage = new SpectatorPoseSyncMessage(1, _pendingPoseState, _runtimeState.UtcNowTicks); IReadOnlyList<ulong> readOnlyList = CameraStreamRecipients(_pendingPoseState, spectatorTargetSyncPeerIds); if (readOnlyList.Count == 0 || _transport.SendSpectatorPose(spectatorPoseSyncMessage, readOnlyList, out string reason2)) { _lastSentPoseState = _pendingPoseState; _pendingPoseState = null; _pendingPoseRefresh = false; _nextPoseSyncTime = _runtimeState.UnscaledTime + GetPoseSyncInterval(); _nextPoseRefreshTime = _runtimeState.UnscaledTime + GetPoseHeartbeatInterval(); if (IsPoseDebugEnabled()) { ModLog.Debug($"Spectator pose sent to {spectatorTargetSyncPeerIds.Count} peer(s): spectating={spectatorPoseSyncMessage.State.IsSpectating}, targetClient={FormatNullable(spectatorPoseSyncMessage.State.TargetClientId)}, position={FormatVector(spectatorPoseSyncMessage.State.Position)}."); } } else { Degrade("spectator pose send failed: " + reason2); } } } private void UpdateLocalVoiceActivity() { if (!_config.EnableVoiceActivitySync.Value) { _lastObservedVoiceActivityState = null; _lastSentVoiceActivityState = null; _pendingVoiceActivityState = null; _pendingVoiceActivityRefresh = false; } else { if (!TryGetLocalVoiceIdentity(out var clientId, out var slotId)) { return; } if (!_voiceActivityProvider.TryGetVoiceActivity(clientId, slotId, out VoiceActivityState state) || !state.HasData) { state = new VoiceActivityState(hasData: false, isSpeaking: false, 0f, 0f, clientId, slotId, _runtimeState.UtcNowTicks); } if (_lastObservedVoiceActivityState == null && !state.HasData) { _lastObservedVoiceActivityState = state; return; } if (VoiceActivitySyncRules.ApproximatelyEquals(_lastObservedVoiceActivityState, state)) { if (ShouldRefreshVoiceActivity(state)) { _pendingVoiceActivityState = state; _pendingVoiceActivityRefresh = true; } return; } _lastObservedVoiceActivityState = state; if (VoiceActivitySyncRules.ApproximatelyEquals(_lastSentVoiceActivityState, state)) { _pendingVoiceActivityState = null; _pendingVoiceActivityRefresh = false; } else { _pendingVoiceActivityState = state; _pendingVoiceActivityRefresh = false; } DebugObservedVoiceActivity(state); } } private void TrySendPendingVoiceActivityState() { if (!_targetSyncReady || !_config.EnableVoiceActivitySync.Value || _pendingVoiceActivityState == null) { return; } string reason; if (!_transport.IsRegistered || !_transport.IsNetworkAvailable) { StopNetworkingForLifecycle("custom messaging transport unavailable before voice activity send"); } else if (!_runtimeState.CanUseModNetworking(out reason)) { StopNetworkingForLifecycle(reason); } else if (!_pendingVoiceActivityRefresh && VoiceActivitySyncRules.ApproximatelyEquals(_lastSentVoiceActivityState, _pendingVoiceActivityState)) { _pendingVoiceActivityState = null; } else if (!_pendingVoiceActivityState.HasData && (_lastSentVoiceActivityState == null || !_lastSentVoiceActivityState.HasData)) { _pendingVoiceActivityState = null; } else { if (_runtimeState.UnscaledTime < _nextVoiceActivitySyncTime) { return; } List<ulong> voiceActivitySyncPeerIds = _peerRegistry.GetVoiceActivitySyncPeerIds(_transport.LocalClientId); if (voiceActivitySyncPeerIds.Count == 0) { UpdateTargetSyncReadiness(); return; } VoiceActivitySyncMessage voiceActivitySyncMessage = new VoiceActivitySyncMessage(1, _pendingVoiceActivityState, _runtimeState.UtcNowTicks); if (_transport.SendVoiceActivity(voiceActivitySyncMessage, voiceActivitySyncPeerIds, out string reason2)) { _lastSentVoiceActivityState = _pendingVoiceActivityState; _pendingVoiceActivityState = null; _pendingVoiceActivityRefresh = false; _nextVoiceActivitySyncTime = _runtimeState.UnscaledTime + GetVoiceActivitySyncInterval(); _nextVoiceActivityRefreshTime = _runtimeState.UnscaledTime + GetVoiceActivityRefreshInterval(); DebugSentVoiceActivity(voiceActivitySyncMessage.State, voiceActivitySyncPeerIds.Count); } else { Degrade("voice activity send failed: " + reason2); } } } private void OnCapabilityReceived(ulong senderClientId, ModPeerCapability capability) { if (!_initialized || !_config.EnableNetworking.Value || !_config.EnableCapabilityHandshake.Value) { return; } if (!_runtimeState.CanUseModNetworking(out string reason)) { Debug($"Dropped capability from sender={senderClientId}: {reason}."); return; } if (capability.ClientId == _transport.LocalClientId) { _peerRegistry.RegisterLocal(CreateLocalCapability(_transport.LocalClientId)); return; } if (_transport.IsHost && capability.ClientId != senderClientId) { Debug($"Dropped capability with mismatched sender and peer id: sender={senderClientId}, peer={capability.ClientId}."); return; } if (!_transport.IsHost && senderClientId != capability.ClientId && senderClientId != _transport.ServerClientId) { Debug($"Dropped relayed capability from non-server sender={senderClientId}, peer={capability.ClientId}."); return; } bool flag = !_transport.IsHost && senderClientId != capability.ClientId; if (!ModPeerCapabilityRules.SupportsCurrentSpectatorTargetSync(capability)) { RemoveRemotePeerState(capability.ClientId, $"capability no longer compatible: sender={senderClientId}, targetSync={capability.SupportsSpectatorTargetSync}, voiceSync={capability.SupportsVoiceActivitySync}, voiceRoute={capability.SupportsSpectatorVoiceToTarget}, relayed={flag}"); return; } bool flag2 = _peerRegistry.RegisterRemote(capability, flag); if (flag2) { _noCompatiblePeerLocalOnly = false; _lifecycleState = NetworkLifecycleState.TransportRegistered; } Debug($"Capability received from sender={senderClientId}, peer={capability.ClientId}, protocol={capability.ProtocolVersion}, targetSync={capability.SupportsSpectatorTargetSync}, voiceSync={capability.SupportsVoiceActivitySync}, voiceRoute={capability.SupportsSpectatorVoiceToTarget}, compatible={flag2}, relayed={flag}."); if (flag2 && _transport.IsHost) { ModPeerCapability capability2 = CreateLocalCapability(_transport.LocalClientId); _peerRegistry.RegisterLocal(capability2); if (_transport.SendCapability(capability2, new ulong[1] { capability.ClientId }, out string reason2)) { Debug($"Capability reply sent to peer={capability.ClientId}."); } else { Debug($"Capability reply to peer={capability.ClientId} failed: {reason2}."); } SendLocalPeerIdentityToRecipients(new ulong[1] { capability.ClientId }); SendLocalSpectatorStateToPeer(capability.ClientId); PruneDisconnectedPeers(force: true); RelayCapabilityToCompatiblePeers(capability); RelayKnownCapabilitiesToPeer(capability.ClientId); RelayKnownSpectatorStatesToPeer(capability.ClientId); RelayKnownPeerIdentitiesToPeer(capability.ClientId); RelayKnownVoiceActivitiesToPeer(capability.ClientId); } } private void RemoveRemotePeerState(ulong peerId, string reason) { if (!_transport.IsRegistered || peerId != _transport.LocalClientId) { ModPeerCapability capability; SpectatorTargetState state; SpectatorPoseState state2; PeerIdentityState state3; VoiceActivityState state4; bool num = _peerRegistry.TryGetCapability(peerId, out capability) || _remoteTargetRegistry.TryGet(peerId, out state) || _remotePoseRegistry.TryGet(peerId, out state2) || _remoteIdentityRegistry.TryGet(peerId, out state3) || _remoteVoiceActivityRegistry.TryGet(peerId, out state4); _peerRegistry.Remove(peerId); _remoteTargetRegistry.Remove(peerId); _remotePoseRegistry.Remove(peerId); _remoteIdentityRegistry.Remove(peerId); _remoteVoiceActivityRegistry.Remove(peerId); if (num) { Debug($"Removed remote peer state for peer={peerId}: {reason}."); } else { Debug($"Ignored incompatible remote peer capability for peer={peerId}: {reason}."); } } } private void OnSpectatorTargetReceived(ulong senderClientId, SpectatorTargetState state) { if (!_initialized || !_config.EnableNetworking.Value || !_config.EnableSpectatorTargetSync.Value) { return; } if (!_runtimeState.CanUseModNetworking(out string reason)) { Debug($"Dropped spectator target from sender={senderClientId}: {reason}."); } else if (state.LocalClientId != _transport.LocalClientId) { if (!HostRelayPlanner.CanAcceptSpectatorState(_transport.IsHost, _transport.LocalClientId, _transport.ServerClientId, senderClientId, state.LocalClientId, _peerRegistry, out string reason2)) { Debug($"Dropped spectator target from sender={senderClientId}, peer={state.LocalClientId}: {reason2}."); return; } _remoteTargetRegistry.Update(state); Debug($"Spectator target received from peer={state.LocalClientId}: spectating={state.IsSpectating}, targetClient={FormatNullable(state.TargetClientId)}, targetSlot={FormatNullable(state.TargetPlayerSlotId)}."); RelaySpectatorTargetState(senderClientId, state); } } private void OnSpectatorPoseReceived(ulong senderClientId, SpectatorPoseState state) { //IL_011a: Unknown result type (might be due to invalid IL or missing references) if (!_initialized || !_config.EnableNetworking.Value || !_config.EnableSpectatorPoseSync.Value) { return; } if (!_runtimeState.CanUseModNetworking(out string reason)) { Debug($"Dropped spectator pose from sender={senderClientId}: {reason}."); } else { if (state.LocalClientId == _transport.LocalClientId) { return; } if (!HostRelayPlanner.CanAcceptSpectatorState(_transport.IsHost, _transport.LocalClientId, _transport.ServerClientId, senderClientId, state.LocalClientId, _peerRegistry, out string reason2)) { Debug($"Dropped spectator pose from sender={senderClientId}, peer={state.LocalClientId}: {reason2}."); return; } _remotePoseRegistry.Update(state, _runtimeState.UnscaledTime); if (IsPoseDebugEnabled()) { ModLog.Debug($"Spectator pose received from peer={state.LocalClientId}: spectating={state.IsSpectating}, targetClient={FormatNullable(state.TargetClientId)}, position={FormatVector(state.Position)}."); } RelaySpectatorPoseState(senderClientId, state); } } private void OnPeerIdentityReceived(ulong senderClientId, PeerIdentityState state) { if (!_initialized || !_config.EnableNetworking.Value || !_config.EnableCapabilityHandshake.Value) { return; } if (!_runtimeState.CanUseModNetworking(out string reason)) { Debug($"Dropped peer identity from sender={senderClientId}: {reason}."); } else if (state.ClientId != _transport.LocalClientId) { if (!HostRelayPlanner.CanAcceptSpectatorState(_transport.IsHost, _transport.LocalClientId, _transport.ServerClientId, senderClientId, state.ClientId, _peerRegistry, out string reason2)) { Debug($"Dropped peer identity from sender={senderClientId}, peer={state.ClientId}: {reason2}."); return; } _remoteIdentityRegistry.Update(state); Debug($"Peer identity received from peer={state.ClientId}: slot={state.PlayerSlotId}, name={state.DisplayName}, voiceName={FormatVoiceName(state.VoicePlayerName)}."); RelayPeerIdentity(senderClientId, state); } } private void OnVoiceActivityReceived(ulong senderClientId, VoiceActivityState state) { if (!_initialized || !_config.EnableNetworking.Value || !_config.EnableVoiceActivitySync.Value) { return; } if (!_runtimeState.CanUseModNetworking(out string reason)) { DebugVoice($"Dropped voice activity from sender={senderClientId}: {reason}."); } else if (state.ClientId != _transport.LocalClientId) { if (!HostRelayPlanner.CanAcceptSpectatorState(_transport.IsHost, _transport.LocalClientId, _transport.ServerClientId, senderClientId, state.ClientId, _peerRegistry, out string reason2)) { DebugVoice($"Dropped voice activity from sender={senderClientId}, peer={state.ClientId}: {reason2}."); return; } _remoteVoiceActivityRegistry.Update(state, _runtimeState.UtcNowTicks); DebugReceivedVoiceActivity(senderClientId, state); RelayVoiceActivityState(senderClientId, state); } } private void RelayCapabilityToCompatiblePeers(ModPeerCapability capability) { if (!_transport.IsHost || !_config.EnableHostRelay.Value) { return; } IReadOnlyList<ulong> relayRecipients = HostRelayPlanner.GetRelayRecipients(_peerRegistry, _transport.LocalClientId, capability.ClientId); if (relayRecipients.Count != 0) { if (_transport.SendCapability(capability, relayRecipients, out string reason)) { Debug($"Relayed capability for peer={capability.ClientId} to {relayRecipients.Count} peer(s)."); } else { Debug($"Capability relay for peer={capability.ClientId} failed: {reason}."); } } } private void RelayKnownCapabilitiesToPeer(ulong recipientClientId) { if (!_transport.IsHost || !_config.EnableHostRelay.Value) { return; } foreach (ModPeerCapability item in _peerRegistry.GetCapabilitiesSnapshot()) { if (item.ClientId != _transport.LocalClientId && item.ClientId != recipientClientId && item.HandshakeComplete && item.ProtocolVersion == 1 && item.SupportsCapabilityHandshake && item.SupportsSpectatorTargetSync) { if (_transport.SendCapability(item, new ulong[1] { recipientClientId }, out string reason)) { Debug($"Relayed known capability for peer={item.ClientId} to peer={recipientClientId}."); } else { Debug($"Known capability relay for peer={item.ClientId} to peer={recipientClientId} failed: {reason}."); } } } } private void RelayKnownSpectatorStatesToPeer(ulong recipientClientId) { if (!_transport.IsHost || !_config.EnableHostRelay.Value) { return; } foreach (SpectatorTargetState item in _remoteTargetRegistry.GetSnapshot()) { if (item.LocalClientId == _transport.LocalClientId || item.LocalClientId == recipientClientId) { continue; } if (!IsConnectedForKnownState(item.LocalClientId)) { Debug($"Skipped known spectator target relay for peer={item.LocalClientId} to peer={recipientClientId}: origin is not connected."); continue; } if (item.TargetClientId.HasValue && !IsConnectedForKnownState(item.TargetClientId.Value)) { Debug($"Skipped known spectator target relay for peer={item.LocalClientId} to peer={recipientClientId}: target={item.TargetClientId.Value} is not connected."); continue; } SpectatorTargetSyncMessage message = new SpectatorTargetSyncMessage(1, item, _runtimeState.UtcNowTicks); if (_transport.SendSpectatorTarget(message, new ulong[1] { recipientClientId }, out string reason)) { Debug($"Relayed known spectator target for peer={item.LocalClientId} to peer={recipientClientId}."); } else { Debug($"Known spectator target relay for peer={item.LocalClientId} to peer={recipientClientId} failed: {reason}."); } } if (!_config.EnableSpectatorPoseSync.Value) { return; } foreach (SpectatorPoseState item2 in _remotePoseRegistry.GetSnapshot()) { if (item2.LocalClientId == _transport.LocalClientId || item2.LocalClientId == recipientClientId) { continue; } if (!IsConnectedForKnownState(item2.LocalClientId)) { DebugPose($"Skipped known spectator pose relay for peer={item2.LocalClientId} to peer={recipientClientId}: origin is not connected."); continue; } if (item2.TargetClientId.HasValue && !IsConnectedForKnownState(item2.TargetClientId.Value)) { DebugPose($"Skipped known spectator pose relay for peer={item2.LocalClientId} to peer={recipientClientId}: target={item2.TargetClientId.Value} is not connected."); continue; } if (!HasMatchingStoredTarget(item2)) { DebugPose($"Skipped known spectator pose relay for peer={item2.LocalClientId} to peer={recipientClientId}: no matching active target."); continue; } SpectatorPoseSyncMessage message2 = new SpectatorPoseSyncMessage(1, item2, _runtimeState.UtcNowTicks); if (_transport.SendSpectatorPose(message2, new ulong[1] { recipientClientId }, out string reason2)) { DebugPose($"Relayed known spectator pose for peer={item2.LocalClientId} to peer={recipientClientId}."); } else { DebugPose($"Known spectator pose relay for peer={item2.LocalClientId} to peer={recipientClientId} failed: {reason2}."); } } } private bool HasMatchingStoredPose(SpectatorTargetState targetState) { if (_remotePoseRegistry.TryGet(targetState.LocalClientId, out SpectatorPoseState state) && state.IsSpectating && state.TargetClientId == targetState.TargetClientId) { return state.TargetPlayerSlotId == targetState.TargetPlayerSlotId; } return false; } private bool HasMatchingStoredTarget(SpectatorPoseState poseState) { if (_remoteTargetRegistry.TryGet(poseState.LocalClientId, out SpectatorTargetState state) && state.IsSpectating && state.TargetClientId == poseState.TargetClientId) { return state.TargetPlayerSlotId == poseState.TargetPlayerSlotId; } return false; } private bool IsConnectedForKnownState(ulong clientId) { if (clientId != _transport.LocalClientId) { return _transport.IsPeerConnected(clientId); } return true; } private bool IsConnectedForRelayState(ulong originClientId, bool isSpectating, ulong? targetClientId, out string reason) { if (!IsConnectedForKnownState(originClientId)) { reason = "origin is not connected"; return false; } if (isSpectating && targetClientId.HasValue && !IsConnectedForKnownState(targetClientId.Value)) { reason = $"target={targetClientId.Value} is not connected"; return false; } reason = string.Empty; return true; } private void RelaySpectatorTargetState(ulong senderClientId, SpectatorTargetState state) { if (!_transport.IsHost || !_config.EnableHostRelay.Value || senderClientId != state.LocalClientId) { return; } if (!IsConnectedForRelayState(state.LocalClientId, state.IsSpectating, state.TargetClientId, out string reason)) { Debug($"Skipped spectator target relay from peer={state.LocalClientId}: {reason}."); return; } IReadOnlyList<ulong> relayRecipients = HostRelayPlanner.GetRelayRecipients(_peerRegistry, _transport.LocalClientId, state.LocalClientId); if (relayRecipients.Count != 0) { SpectatorTargetSyncMessage message = new SpectatorTargetSyncMessage(1, state, _runtimeState.UtcNowTicks); if (_transport.SendSpectatorTarget(message, relayRecipients, out string reason2)) { Debug($"Relayed spectator target from peer={state.LocalClientId} to {relayRecipients.Count} peer(s)."); } else { Debug($"Spectator target relay from peer={state.LocalClientId} failed: {reason2}."); } } } private void RelaySpectatorPoseState(ulong senderClientId, SpectatorPoseState state) { if (!_transport.IsHost || !_config.EnableHostRelay.Value || senderClientId != state.LocalClientId) { return;
BepInEx/plugins/EnhancedSpectator/EnhancedSpectator.CameraRuntime.dll
Decompiled 3 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using EnhancedSpectator.CameraRuntime.Cinemachine; using EnhancedSpectator.CameraRuntime.Cinemachine.Utility; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Events; using UnityEngine.SceneManagement; using UnityEngine.Serialization; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: InternalsVisibleTo("com.unity.cinemachine.editor")] [assembly: InternalsVisibleTo("EnhancedSpectator.CameraRuntime.Cinemachine.Runtime.Tests")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("EnhancedSpectator.CameraRuntime")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("2.9.7.0")] [assembly: AssemblyInformationalVersion("2.9.7+fe5fa709727a7269f1623847f14194b6321c3744")] [assembly: AssemblyProduct("EnhancedSpectator.CameraRuntime")] [assembly: AssemblyTitle("EnhancedSpectator.CameraRuntime")] [assembly: AssemblyVersion("2.9.7.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; } } } [AddComponentMenu("")] [ExecuteAlways] [HelpURL("https://docs.unity3d.com/Packages/[email protected]/api/EnhancedSpectator.CameraRuntime.Cinemachine.CinemachineCameraOffset.html")] [SaveDuringPlay] public class CinemachineCameraOffset : CinemachineExtension { [Tooltip("Offset the camera's position by this much (camera space)")] public Vector3 m_Offset = Vector3.zero; [Tooltip("When to apply the offset")] public CinemachineCore.Stage m_ApplyAfter = CinemachineCore.Stage.Aim; [Tooltip("If applying offset after aim, re-adjust the aim to preserve the screen position of the LookAt target as much as possible")] public bool m_PreserveComposition; protected override void PostPipelineStageCallback(CinemachineVirtualCameraBase vcam, CinemachineCore.Stage stage, ref CameraState state, float deltaTime) { //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_002d: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: 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_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: 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_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: 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_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: 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_00d3: 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_0090: 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_0096: Unknown result type (might be due to invalid IL or missing references) if (stage == m_ApplyAfter) { bool num = m_PreserveComposition && state.HasLookAt && stage > CinemachineCore.Stage.Body; Vector3 val = Vector2.op_Implicit(Vector2.zero); if (num) { val = Vector2.op_Implicit(state.RawOrientation.GetCameraRotationToTarget(state.ReferenceLookAt - state.CorrectedPosition, state.ReferenceUp)); } Vector3 val2 = state.RawOrientation * m_Offset; ref Vector3 positionCorrection = ref state.PositionCorrection; positionCorrection += val2; if (!num) { ref Vector3 referenceLookAt = ref state.ReferenceLookAt; referenceLookAt += val2; } else { Quaternion orient = Quaternion.LookRotation(state.ReferenceLookAt - state.CorrectedPosition, state.ReferenceUp); orient = orient.ApplyCameraRotation(Vector2.op_Implicit(-val), state.ReferenceUp); state.RawOrientation = orient; } } } } [AddComponentMenu("")] [ExecuteAlways] [SaveDuringPlay] [HelpURL("https://docs.unity3d.com/Packages/[email protected]/manual/CinemachineRecomposer.html")] public class CinemachineRecomposer : CinemachineExtension { [Tooltip("When to apply the adjustment")] public CinemachineCore.Stage m_ApplyAfter; [Tooltip("Tilt the camera by this much")] public float m_Tilt; [Tooltip("Pan the camera by this much")] public float m_Pan; [Tooltip("Roll the camera by this much")] public float m_Dutch; [Tooltip("Scale the zoom by this amount (normal = 1)")] public float m_ZoomScale; [Range(0f, 1f)] [Tooltip("Lowering this value relaxes the camera's attention to the Follow target (normal = 1)")] public float m_FollowAttachment; [Range(0f, 1f)] [Tooltip("Lowering this value relaxes the camera's attention to the LookAt target (normal = 1)")] public float m_LookAtAttachment; private void Reset() { m_ApplyAfter = CinemachineCore.Stage.Finalize; m_Tilt = 0f; m_Pan = 0f; m_Dutch = 0f; m_ZoomScale = 1f; m_FollowAttachment = 1f; m_LookAtAttachment = 1f; } private void OnValidate() { m_ZoomScale = Mathf.Max(0.01f, m_ZoomScale); m_FollowAttachment = Mathf.Clamp01(m_FollowAttachment); m_LookAtAttachment = Mathf.Clamp01(m_LookAtAttachment); } public override void PrePipelineMutateCameraStateCallback(CinemachineVirtualCameraBase vcam, ref CameraState curState, float deltaTime) { vcam.FollowTargetAttachment = m_FollowAttachment; vcam.LookAtTargetAttachment = m_LookAtAttachment; } protected override void PostPipelineStageCallback(CinemachineVirtualCameraBase vcam, CinemachineCore.Stage stage, ref CameraState state, float deltaTime) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_0029: 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_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: 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_0041: 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) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //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_0059: Unknown result type (might be due to invalid IL or missing references) if (stage == m_ApplyAfter) { LensSettings lens = state.Lens; Quaternion val = state.RawOrientation * Quaternion.AngleAxis(m_Tilt, Vector3.right); Quaternion val2 = Quaternion.AngleAxis(m_Pan, state.ReferenceUp) * val; state.OrientationCorrection = Quaternion.Inverse(state.CorrectedOrientation) * val2; lens.Dutch += m_Dutch; if (m_ZoomScale != 1f) { lens.OrthographicSize *= m_ZoomScale; lens.FieldOfView *= m_ZoomScale; } state.Lens = lens; } } } public class CinemachineTouchInputMapper : MonoBehaviour { [Tooltip("Sensitivity multiplier for x-axis")] public float TouchSensitivityX = 10f; [Tooltip("Sensitivity multiplier for y-axis")] public float TouchSensitivityY = 10f; [Tooltip("Input channel to spoof for X axis")] public string TouchXInputMapTo = "Mouse X"; [Tooltip("Input channel to spoof for Y axis")] public string TouchYInputMapTo = "Mouse Y"; private void Start() { CinemachineCore.GetInputAxis = GetInputAxis; } private float GetInputAxis(string axisName) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) if (Input.touchCount > 0) { if (axisName == TouchXInputMapTo) { return ((Touch)(ref Input.touches[0])).deltaPosition.x / TouchSensitivityX; } if (axisName == TouchYInputMapTo) { return ((Touch)(ref Input.touches[0])).deltaPosition.y / TouchSensitivityY; } } return Input.GetAxis(axisName); } } namespace EnhancedSpectator.CameraRuntime.Cinemachine { [DocumentationSorting(DocumentationSortingAttribute.Level.UserRef)] [DisallowMultipleComponent] [ExecuteAlways] [ExcludeFromPreset] [AddComponentMenu("EnhancedSpectator.CameraRuntime.Cinemachine/CinemachineBlendListCamera")] [HelpURL("https://docs.unity3d.com/Packages/[email protected]/manual/CinemachineBlendListCamera.html")] public class CinemachineBlendListCamera : CinemachineVirtualCameraBase { [Serializable] public struct Instruction { [Tooltip("The virtual camera to activate when this instruction becomes active")] public CinemachineVirtualCameraBase m_VirtualCamera; [Tooltip("How long to wait (in seconds) before activating the next virtual camera in the list (if any)")] public float m_Hold; [CinemachineBlendDefinitionProperty] [Tooltip("How to blend to the next virtual camera in the list (if any)")] public CinemachineBlendDefinition m_Blend; } [Tooltip("Default object for the camera children to look at (the aim target), if not specified in a child camera. May be empty if all of the children define targets of their own.")] [NoSaveDuringPlay] [VcamTargetProperty] public Transform m_LookAt; [Tooltip("Default object for the camera children wants to move with (the body target), if not specified in a child camera. May be empty if all of the children define targets of their own.")] [NoSaveDuringPlay] [VcamTargetProperty] public Transform m_Follow; [Tooltip("When enabled, the current child camera and blend will be indicated in the game window, for debugging")] public bool m_ShowDebugText; [Tooltip("When enabled, the child vcams will cycle indefinitely instead of just stopping at the last one")] public bool m_Loop; [SerializeField] [HideInInspector] [NoSaveDuringPlay] internal CinemachineVirtualCameraBase[] m_ChildCameras; [Tooltip("The set of instructions for enabling child cameras.")] public Instruction[] m_Instructions; private ICinemachineCamera m_TransitioningFrom; private CameraState m_State = CameraState.Default; private float mActivationTime = -1f; private int mCurrentInstruction; private CinemachineBlend mActiveBlend; public override string Description { get { if (mActiveBlend != null) { return mActiveBlend.Description; } ICinemachineCamera liveChild = LiveChild; if (liveChild == null) { return "(none)"; } StringBuilder stringBuilder = CinemachineDebug.SBFromPool(); stringBuilder.Append("["); stringBuilder.Append(liveChild.Name); stringBuilder.Append("]"); string result = stringBuilder.ToString(); CinemachineDebug.ReturnToPool(stringBuilder); return result; } } public ICinemachineCamera LiveChild { get; set; } public override CameraState State => m_State; public override Transform LookAt { get { return ResolveLookAt(m_LookAt); } set { m_LookAt = value; } } public override Transform Follow { get { return ResolveFollow(m_Follow); } set { m_Follow = value; } } public CinemachineVirtualCameraBase[] ChildCameras { get { UpdateListOfChildren(); return m_ChildCameras; } } public bool IsBlending => mActiveBlend != null; private void Reset() { m_LookAt = null; m_Follow = null; m_ShowDebugText = false; m_Loop = false; m_Instructions = null; m_ChildCameras = null; } public override bool IsLiveChild(ICinemachineCamera vcam, bool dominantChildOnly = false) { if (vcam != LiveChild) { if (mActiveBlend != null) { return mActiveBlend.Uses(vcam); } return false; } return true; } public override void OnTargetObjectWarped(Transform target, Vector3 positionDelta) { //IL_0015: 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) UpdateListOfChildren(); CinemachineVirtualCameraBase[] childCameras = m_ChildCameras; for (int i = 0; i < childCameras.Length; i++) { childCameras[i].OnTargetObjectWarped(target, positionDelta); } base.OnTargetObjectWarped(target, positionDelta); } public override void ForceCameraPosition(Vector3 pos, Quaternion rot) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0026: 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) UpdateListOfChildren(); CinemachineVirtualCameraBase[] childCameras = m_ChildCameras; for (int i = 0; i < childCameras.Length; i++) { childCameras[i].ForceCameraPosition(pos, rot); } base.ForceCameraPosition(pos, rot); } public override void OnTransitionFromCamera(ICinemachineCamera fromCam, Vector3 worldUp, float deltaTime) { //IL_0002: 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_003b: Unknown result type (might be due to invalid IL or missing references) base.OnTransitionFromCamera(fromCam, worldUp, deltaTime); InvokeOnTransitionInExtensions(fromCam, worldUp, deltaTime); mActivationTime = CinemachineCore.CurrentTime; mCurrentInstruction = 0; LiveChild = null; mActiveBlend = null; m_TransitioningFrom = fromCam; InternalUpdateCameraState(worldUp, deltaTime); } public override void InternalUpdateCameraState(Vector3 worldUp, float deltaTime) { //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) if (!PreviousStateIsValid) { mCurrentInstruction = -1; mActiveBlend = null; } UpdateListOfChildren(); AdvanceCurrentInstruction(deltaTime); CinemachineVirtualCameraBase cinemachineVirtualCameraBase = null; if (mCurrentInstruction >= 0 && mCurrentInstruction < m_Instructions.Length) { cinemachineVirtualCameraBase = m_Instructions[mCurrentInstruction].m_VirtualCamera; } if ((Object)(object)cinemachineVirtualCameraBase != (Object)null) { if (!((Component)cinemachineVirtualCameraBase).gameObject.activeInHierarchy) { ((Component)cinemachineVirtualCameraBase).gameObject.SetActive(true); cinemachineVirtualCameraBase.UpdateCameraState(worldUp, deltaTime); } ICinemachineCamera liveChild = LiveChild; LiveChild = cinemachineVirtualCameraBase; if (liveChild != LiveChild && LiveChild != null) { LiveChild.OnTransitionFromCamera(liveChild, worldUp, deltaTime); CinemachineCore.Instance.GenerateCameraActivationEvent(LiveChild, liveChild); if (liveChild != null) { mActiveBlend = CreateBlend(liveChild, LiveChild, m_Instructions[mCurrentInstruction].m_Blend, mActiveBlend); if (mActiveBlend == null || !mActiveBlend.Uses(liveChild)) { CinemachineCore.Instance.GenerateCameraCutEvent(LiveChild); } } } } if (mActiveBlend != null) { mActiveBlend.TimeInBlend += ((deltaTime >= 0f) ? deltaTime : mActiveBlend.Duration); if (mActiveBlend.IsComplete) { mActiveBlend = null; } } if (mActiveBlend != null) { mActiveBlend.UpdateCameraState(worldUp, deltaTime); m_State = mActiveBlend.State; } else if (LiveChild != null) { if (m_TransitioningFrom != null) { LiveChild.OnTransitionFromCamera(m_TransitioningFrom, worldUp, deltaTime); } m_State = LiveChild.State; } m_TransitioningFrom = null; InvokePostPipelineStageCallback(this, CinemachineCore.Stage.Finalize, ref m_State, deltaTime); PreviousStateIsValid = true; } protected override void OnEnable() { base.OnEnable(); InvalidateListOfChildren(); LiveChild = null; mActiveBlend = null; CinemachineDebug.OnGUIHandlers = (CinemachineDebug.OnGUIDelegate)Delegate.Remove(CinemachineDebug.OnGUIHandlers, new CinemachineDebug.OnGUIDelegate(OnGuiHandler)); CinemachineDebug.OnGUIHandlers = (CinemachineDebug.OnGUIDelegate)Delegate.Combine(CinemachineDebug.OnGUIHandlers, new CinemachineDebug.OnGUIDelegate(OnGuiHandler)); } protected override void OnDisable() { base.OnDisable(); CinemachineDebug.OnGUIHandlers = (CinemachineDebug.OnGUIDelegate)Delegate.Remove(CinemachineDebug.OnGUIHandlers, new CinemachineDebug.OnGUIDelegate(OnGuiHandler)); } private void OnTransformChildrenChanged() { InvalidateListOfChildren(); } private void OnGuiHandler() { } private void InvalidateListOfChildren() { m_ChildCameras = null; LiveChild = null; } private void UpdateListOfChildren() { if (m_ChildCameras != null) { return; } List<CinemachineVirtualCameraBase> list = new List<CinemachineVirtualCameraBase>(); CinemachineVirtualCameraBase[] componentsInChildren = ((Component)this).GetComponentsInChildren<CinemachineVirtualCameraBase>(true); foreach (CinemachineVirtualCameraBase cinemachineVirtualCameraBase in componentsInChildren) { if ((Object)(object)((Component)cinemachineVirtualCameraBase).transform.parent == (Object)(object)((Component)this).transform) { list.Add(cinemachineVirtualCameraBase); } } m_ChildCameras = list.ToArray(); ValidateInstructions(); } internal void ValidateInstructions() { if (m_Instructions == null) { m_Instructions = Array.Empty<Instruction>(); } for (int i = 0; i < m_Instructions.Length; i++) { if ((Object)(object)m_Instructions[i].m_VirtualCamera != (Object)null && (Object)(object)((Component)m_Instructions[i].m_VirtualCamera).transform.parent != (Object)(object)((Component)this).transform) { m_Instructions[i].m_VirtualCamera = null; } } mActiveBlend = null; } private void AdvanceCurrentInstruction(float deltaTime) { if (m_ChildCameras == null || m_ChildCameras.Length == 0 || mActivationTime < 0f || m_Instructions.Length == 0) { mActivationTime = -1f; mCurrentInstruction = -1; mActiveBlend = null; return; } float currentTime = CinemachineCore.CurrentTime; if (mCurrentInstruction < 0 || deltaTime < 0f) { mActivationTime = currentTime; mCurrentInstruction = 0; } if (mCurrentInstruction > m_Instructions.Length - 1) { mActivationTime = currentTime; mCurrentInstruction = m_Instructions.Length - 1; } float num = m_Instructions[mCurrentInstruction].m_Hold + m_Instructions[mCurrentInstruction].m_Blend.BlendTime; float num2 = ((mCurrentInstruction < m_Instructions.Length - 1 || m_Loop) ? 0f : float.MaxValue); if (currentTime - mActivationTime > Mathf.Max(num2, num)) { mActivationTime = currentTime; mCurrentInstruction++; if (m_Loop && mCurrentInstruction == m_Instructions.Length) { mCurrentInstruction = 0; } } } } public interface ICameraOverrideStack { Vector3 DefaultWorldUp { get; } int SetCameraOverride(int overrideId, ICinemachineCamera camA, ICinemachineCamera camB, float weightB, float deltaTime); void ReleaseCameraOverride(int overrideId); } [DocumentationSorting(DocumentationSortingAttribute.Level.UserRef)] [DisallowMultipleComponent] [ExecuteAlways] [AddComponentMenu("EnhancedSpectator.CameraRuntime.Cinemachine/CinemachineBrain")] [SaveDuringPlay] [HelpURL("https://docs.unity3d.com/Packages/[email protected]/manual/CinemachineBrainProperties.html")] public class CinemachineBrain : MonoBehaviour, ICameraOverrideStack { [DocumentationSorting(DocumentationSortingAttribute.Level.UserRef)] public enum UpdateMethod { FixedUpdate, LateUpdate, SmartUpdate, ManualUpdate } [DocumentationSorting(DocumentationSortingAttribute.Level.UserRef)] public enum BrainUpdateMethod { FixedUpdate, LateUpdate } [Serializable] public class BrainEvent : UnityEvent<CinemachineBrain> { } [Serializable] public class VcamActivatedEvent : UnityEvent<ICinemachineCamera, ICinemachineCamera> { } private class BrainFrame { public int id; public CinemachineBlend blend = new CinemachineBlend(null, null, null, 0f, 0f); public CinemachineBlend workingBlend = new CinemachineBlend(null, null, null, 0f, 0f); public BlendSourceVirtualCamera workingBlendSource = new BlendSourceVirtualCamera(null); public float deltaTimeOverride; public float blendStartPosition; public bool Active => blend.IsValid; } [Tooltip("When enabled, the current camera and blend will be indicated in the game window, for debugging")] public bool m_ShowDebugText; [Tooltip("When enabled, the camera's frustum will be shown at all times in the scene view")] public bool m_ShowCameraFrustum = true; [Tooltip("When enabled, the cameras will always respond in real-time to user input and damping, even if the game is running in slow motion")] public bool m_IgnoreTimeScale; [Tooltip("If set, this object's Y axis will define the worldspace Up vector for all the virtual cameras. This is useful for instance in top-down game environments. If not set, Up is worldspace Y. Setting this appropriately is important, because Virtual Cameras don't like looking straight up or straight down.")] public Transform m_WorldUpOverride; [Tooltip("The update time for the vcams. Use FixedUpdate if all your targets are animated during FixedUpdate (e.g. RigidBodies), LateUpdate if all your targets are animated during the normal Update loop, and SmartUpdate if you want EnhancedSpectator.CameraRuntime.Cinemachine to do the appropriate thing on a per-target basis. SmartUpdate is the recommended setting")] public UpdateMethod m_UpdateMethod = UpdateMethod.SmartUpdate; [Tooltip("The update time for the Brain, i.e. when the blends are evaluated and the brain's transform is updated")] public BrainUpdateMethod m_BlendUpdateMethod = BrainUpdateMethod.LateUpdate; [CinemachineBlendDefinitionProperty] [Tooltip("The blend that is used in cases where you haven't explicitly defined a blend between two Virtual Cameras")] public CinemachineBlendDefinition m_DefaultBlend = new CinemachineBlendDefinition(CinemachineBlendDefinition.Style.EaseInOut, 2f); [Tooltip("This is the asset that contains custom settings for blends between specific virtual cameras in your scene")] public CinemachineBlenderSettings m_CustomBlends; private Camera m_OutputCamera; private GameObject m_TargetOverride; [Tooltip("This event will fire whenever a virtual camera goes live and there is no blend")] public BrainEvent m_CameraCutEvent = new BrainEvent(); [Tooltip("This event will fire whenever a virtual camera goes live. If a blend is involved, then the event will fire on the first frame of the blend.")] public VcamActivatedEvent m_CameraActivatedEvent = new VcamActivatedEvent(); private static ICinemachineCamera mSoloCamera; private Coroutine mPhysicsCoroutine; private int m_LastFrameUpdated; private WaitForFixedUpdate mWaitForFixedUpdate = new WaitForFixedUpdate(); private List<BrainFrame> mFrameStack = new List<BrainFrame>(); private int mNextFrameId = 1; private CinemachineBlend mCurrentLiveCameras = new CinemachineBlend(null, null, null, 0f, 0f); private static readonly AnimationCurve mDefaultLinearAnimationCurve = AnimationCurve.Linear(0f, 0f, 1f, 1f); private ICinemachineCamera mActiveCameraPreviousFrame; private GameObject mActiveCameraPreviousFrameGameObject; public Camera OutputCamera { get { if ((Object)(object)m_OutputCamera == (Object)null && !Application.isPlaying) { ControlledObject.TryGetComponent<Camera>(ref m_OutputCamera); } return m_OutputCamera; } } public GameObject ControlledObject { get { if (!((Object)(object)m_TargetOverride == (Object)null)) { return m_TargetOverride; } return ((Component)this).gameObject; } set { if (m_TargetOverride != value) { m_TargetOverride = value; ControlledObject.TryGetComponent<Camera>(ref m_OutputCamera); } } } public static ICinemachineCamera SoloCamera { get { return mSoloCamera; } set { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if (value != null && !CinemachineCore.Instance.IsLive(value)) { value.OnTransitionFromCamera(null, Vector3.up, CinemachineCore.DeltaTime); } mSoloCamera = value; } } public Vector3 DefaultWorldUp { get { //IL_001f: 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) if (!((Object)(object)m_WorldUpOverride != (Object)null)) { return Vector3.up; } return ((Component)m_WorldUpOverride).transform.up; } } public ICinemachineCamera ActiveVirtualCamera { get { if (SoloCamera != null) { return SoloCamera; } return DeepCamBFromBlend(mCurrentLiveCameras); } } public bool IsBlending => ActiveBlend != null; public CinemachineBlend ActiveBlend { get { if (SoloCamera != null) { return null; } if (mCurrentLiveCameras.CamA == null || mCurrentLiveCameras.Equals(null) || mCurrentLiveCameras.IsComplete) { return null; } return mCurrentLiveCameras; } set { if (value == null) { mFrameStack[0].blend.Duration = 0f; } else { mFrameStack[0].blend = value; } } } public CameraState CurrentCameraState { get; private set; } public static Color GetSoloGUIColor() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) return Color.Lerp(Color.red, Color.yellow, 0.8f); } private void OnEnable() { if (mFrameStack.Count == 0) { mFrameStack.Add(new BrainFrame()); } CinemachineCore.Instance.AddActiveBrain(this); CinemachineDebug.OnGUIHandlers = (CinemachineDebug.OnGUIDelegate)Delegate.Remove(CinemachineDebug.OnGUIHandlers, new CinemachineDebug.OnGUIDelegate(OnGuiHandler)); CinemachineDebug.OnGUIHandlers = (CinemachineDebug.OnGUIDelegate)Delegate.Combine(CinemachineDebug.OnGUIHandlers, new CinemachineDebug.OnGUIDelegate(OnGuiHandler)); mPhysicsCoroutine = ((MonoBehaviour)this).StartCoroutine(AfterPhysics()); SceneManager.sceneLoaded += OnSceneLoaded; SceneManager.sceneUnloaded += OnSceneUnloaded; } private void OnDisable() { SceneManager.sceneLoaded -= OnSceneLoaded; SceneManager.sceneUnloaded -= OnSceneUnloaded; CinemachineDebug.OnGUIHandlers = (CinemachineDebug.OnGUIDelegate)Delegate.Remove(CinemachineDebug.OnGUIHandlers, new CinemachineDebug.OnGUIDelegate(OnGuiHandler)); CinemachineCore.Instance.RemoveActiveBrain(this); mFrameStack.Clear(); ((MonoBehaviour)this).StopCoroutine(mPhysicsCoroutine); } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { if (Time.frameCount == m_LastFrameUpdated && mFrameStack.Count > 0) { ManualUpdate(); } } private void OnSceneUnloaded(Scene scene) { if (Time.frameCount == m_LastFrameUpdated && mFrameStack.Count > 0) { ManualUpdate(); } } private void Awake() { ControlledObject.TryGetComponent<Camera>(ref m_OutputCamera); } private void Start() { m_LastFrameUpdated = -1; UpdateVirtualCameras(CinemachineCore.UpdateFilter.Late, -1f); } private void OnGuiHandler() { } private IEnumerator AfterPhysics() { while (true) { yield return mWaitForFixedUpdate; if (m_UpdateMethod == UpdateMethod.FixedUpdate || m_UpdateMethod == UpdateMethod.SmartUpdate) { CinemachineCore.UpdateFilter updateFilter = CinemachineCore.UpdateFilter.Fixed; if (m_UpdateMethod == UpdateMethod.SmartUpdate) { UpdateTracker.OnUpdate(UpdateTracker.UpdateClock.Fixed); updateFilter = CinemachineCore.UpdateFilter.Smart; } UpdateVirtualCameras(updateFilter, GetEffectiveDeltaTime(fixedDelta: true)); } if (m_BlendUpdateMethod == BrainUpdateMethod.FixedUpdate) { UpdateFrame0(Time.fixedDeltaTime); ProcessActiveCamera(Time.fixedDeltaTime); } } } private void LateUpdate() { if (m_UpdateMethod != UpdateMethod.ManualUpdate) { ManualUpdate(); } } public void ManualUpdate() { //IL_005f: Unknown result type (might be due to invalid IL or missing references) m_LastFrameUpdated = Time.frameCount; float effectiveDeltaTime = GetEffectiveDeltaTime(fixedDelta: false); if (!Application.isPlaying || m_BlendUpdateMethod != BrainUpdateMethod.FixedUpdate) { UpdateFrame0(effectiveDeltaTime); } ComputeCurrentBlend(ref mCurrentLiveCameras, 0); if (m_UpdateMethod == UpdateMethod.FixedUpdate) { if (m_BlendUpdateMethod != BrainUpdateMethod.FixedUpdate) { CinemachineCore.Instance.m_CurrentUpdateFilter = CinemachineCore.UpdateFilter.Fixed; if (SoloCamera == null) { mCurrentLiveCameras.UpdateCameraState(DefaultWorldUp, GetEffectiveDeltaTime(fixedDelta: true)); } } } else { CinemachineCore.UpdateFilter updateFilter = CinemachineCore.UpdateFilter.Late; if (m_UpdateMethod == UpdateMethod.SmartUpdate) { UpdateTracker.OnUpdate(UpdateTracker.UpdateClock.Late); updateFilter = CinemachineCore.UpdateFilter.SmartLate; } UpdateVirtualCameras(updateFilter, effectiveDeltaTime); } if (!Application.isPlaying || m_BlendUpdateMethod != BrainUpdateMethod.FixedUpdate) { ProcessActiveCamera(effectiveDeltaTime); } } private float GetEffectiveDeltaTime(bool fixedDelta) { if (CinemachineCore.UniformDeltaTimeOverride >= 0f) { return CinemachineCore.UniformDeltaTimeOverride; } if (SoloCamera != null) { return Time.unscaledDeltaTime; } if (!Application.isPlaying) { for (int num = mFrameStack.Count - 1; num > 0; num--) { BrainFrame brainFrame = mFrameStack[num]; if (brainFrame.Active) { return brainFrame.deltaTimeOverride; } } return -1f; } if (m_IgnoreTimeScale) { if (!fixedDelta) { return Time.unscaledDeltaTime; } return Time.fixedDeltaTime; } if (!fixedDelta) { return Time.deltaTime; } return Time.fixedDeltaTime; } private void UpdateVirtualCameras(CinemachineCore.UpdateFilter updateFilter, float deltaTime) { //IL_002a: 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_0042: Unknown result type (might be due to invalid IL or missing references) CinemachineCore.Instance.m_CurrentUpdateFilter = updateFilter; Camera outputCamera = OutputCamera; CinemachineCore.Instance.UpdateAllActiveVirtualCameras(((Object)(object)outputCamera == (Object)null) ? (-1) : outputCamera.cullingMask, DefaultWorldUp, deltaTime); if (SoloCamera != null) { SoloCamera.UpdateCameraState(DefaultWorldUp, deltaTime); } mCurrentLiveCameras.UpdateCameraState(DefaultWorldUp, deltaTime); updateFilter = CinemachineCore.UpdateFilter.Late; if (Application.isPlaying) { if (m_UpdateMethod == UpdateMethod.SmartUpdate) { updateFilter |= CinemachineCore.UpdateFilter.Smart; } else if (m_UpdateMethod == UpdateMethod.FixedUpdate) { updateFilter = CinemachineCore.UpdateFilter.Fixed; } } CinemachineCore.Instance.m_CurrentUpdateFilter = updateFilter; } private static ICinemachineCamera DeepCamBFromBlend(CinemachineBlend blend) { ICinemachineCamera camB; for (camB = blend.CamB; camB != null; camB = blendSourceVirtualCamera.Blend.CamB) { if (!camB.IsValid) { return null; } if (!(camB is BlendSourceVirtualCamera blendSourceVirtualCamera)) { break; } } return camB; } public bool IsLiveInBlend(ICinemachineCamera vcam) { if (vcam == mCurrentLiveCameras.CamA) { return true; } if (mCurrentLiveCameras.CamA is BlendSourceVirtualCamera blendSourceVirtualCamera && blendSourceVirtualCamera.Blend.Uses(vcam)) { return true; } ICinemachineCamera parentCamera = vcam.ParentCamera; if (parentCamera != null && parentCamera.IsLiveChild(vcam)) { return IsLiveInBlend(parentCamera); } return false; } private int GetBrainFrame(int withId) { for (int num = mFrameStack.Count - 1; num > 0; num--) { if (mFrameStack[num].id == withId) { return num; } } mFrameStack.Add(new BrainFrame { id = withId }); return mFrameStack.Count - 1; } public int SetCameraOverride(int overrideId, ICinemachineCamera camA, ICinemachineCamera camB, float weightB, float deltaTime) { if (overrideId < 0) { overrideId = mNextFrameId++; } BrainFrame brainFrame = mFrameStack[GetBrainFrame(overrideId)]; brainFrame.deltaTimeOverride = deltaTime; brainFrame.blend.CamA = camA; brainFrame.blend.CamB = camB; brainFrame.blend.BlendCurve = mDefaultLinearAnimationCurve; brainFrame.blend.Duration = 1f; brainFrame.blend.TimeInBlend = weightB; CinemachineVirtualCameraBase cinemachineVirtualCameraBase = camA as CinemachineVirtualCameraBase; if ((Object)(object)cinemachineVirtualCameraBase != (Object)null) { cinemachineVirtualCameraBase.EnsureStarted(); } cinemachineVirtualCameraBase = camB as CinemachineVirtualCameraBase; if ((Object)(object)cinemachineVirtualCameraBase != (Object)null) { cinemachineVirtualCameraBase.EnsureStarted(); } return overrideId; } public void ReleaseCameraOverride(int overrideId) { for (int num = mFrameStack.Count - 1; num > 0; num--) { if (mFrameStack[num].id == overrideId) { mFrameStack.RemoveAt(num); break; } } } private void ProcessActiveCamera(float deltaTime) { //IL_003e: 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_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) ICinemachineCamera activeVirtualCamera = ActiveVirtualCamera; if (SoloCamera != null) { CameraState state = SoloCamera.State; PushStateToUnityCamera(ref state); } else if (activeVirtualCamera == null) { CameraState state2 = CameraState.Default; Transform transform = ControlledObject.transform; state2.RawPosition = transform.position; state2.RawOrientation = transform.rotation; state2.Lens = LensSettings.FromCamera(m_OutputCamera); state2.BlendHint |= (CameraState.BlendHintValue)67; PushStateToUnityCamera(ref state2); } else { if ((Object)(object)mActiveCameraPreviousFrameGameObject == (Object)null) { mActiveCameraPreviousFrame = null; } if (activeVirtualCamera != mActiveCameraPreviousFrame) { activeVirtualCamera.OnTransitionFromCamera(mActiveCameraPreviousFrame, DefaultWorldUp, deltaTime); if (m_CameraActivatedEvent != null) { ((UnityEvent<ICinemachineCamera, ICinemachineCamera>)m_CameraActivatedEvent).Invoke(activeVirtualCamera, mActiveCameraPreviousFrame); } if (!IsBlending || (mActiveCameraPreviousFrame != null && !ActiveBlend.Uses(mActiveCameraPreviousFrame))) { if (m_CameraCutEvent != null) { ((UnityEvent<CinemachineBrain>)m_CameraCutEvent).Invoke(this); } if (CinemachineCore.CameraCutEvent != null) { ((UnityEvent<CinemachineBrain>)CinemachineCore.CameraCutEvent).Invoke(this); } } activeVirtualCamera.UpdateCameraState(DefaultWorldUp, deltaTime); } CameraState state3 = mCurrentLiveCameras.State; PushStateToUnityCamera(ref state3); } mActiveCameraPreviousFrame = activeVirtualCamera; mActiveCameraPreviousFrameGameObject = activeVirtualCamera?.VirtualCameraGameObject; } private void UpdateFrame0(float deltaTime) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown if (mFrameStack.Count == 0) { mFrameStack.Add(new BrainFrame()); } BrainFrame brainFrame = mFrameStack[0]; ICinemachineCamera cinemachineCamera = TopCameraFromPriorityQueue(); ICinemachineCamera camB = brainFrame.blend.CamB; if (cinemachineCamera != camB) { if ((Object)cinemachineCamera != (Object)null && (Object)camB != (Object)null && deltaTime >= 0f) { CinemachineBlendDefinition cinemachineBlendDefinition = LookupBlend(camB, cinemachineCamera); float num = cinemachineBlendDefinition.BlendTime; float blendStartPosition = 0f; if (cinemachineBlendDefinition.BlendCurve != null && num > 0.0001f) { if (brainFrame.blend.IsComplete) { brainFrame.blend.CamA = camB; } else { if ((brainFrame.blend.CamA == cinemachineCamera || (brainFrame.blend.CamA as BlendSourceVirtualCamera)?.Blend.CamB == cinemachineCamera) && brainFrame.blend.CamB == camB) { float num2 = brainFrame.blendStartPosition + (1f - brainFrame.blendStartPosition) * brainFrame.blend.TimeInBlend / brainFrame.blend.Duration; num *= num2; blendStartPosition = 1f - num2; } brainFrame.blend.CamA = new BlendSourceVirtualCamera(new CinemachineBlend(brainFrame.blend.CamA, brainFrame.blend.CamB, brainFrame.blend.BlendCurve, brainFrame.blend.Duration, brainFrame.blend.TimeInBlend)); } } brainFrame.blend.BlendCurve = cinemachineBlendDefinition.BlendCurve; brainFrame.blend.Duration = num; brainFrame.blend.TimeInBlend = 0f; brainFrame.blendStartPosition = blendStartPosition; } brainFrame.blend.CamB = cinemachineCamera; } if (brainFrame.blend.CamA != null) { brainFrame.blend.TimeInBlend += ((deltaTime >= 0f) ? deltaTime : brainFrame.blend.Duration); if (brainFrame.blend.IsComplete) { brainFrame.blend.CamA = null; brainFrame.blend.BlendCurve = null; brainFrame.blend.Duration = 0f; brainFrame.blend.TimeInBlend = 0f; } } } public void ComputeCurrentBlend(ref CinemachineBlend outputBlend, int numTopLayersToExclude) { if (mFrameStack.Count == 0) { mFrameStack.Add(new BrainFrame()); } int index = 0; int num = Mathf.Max(1, mFrameStack.Count - numTopLayersToExclude); for (int i = 0; i < num; i++) { BrainFrame brainFrame = mFrameStack[i]; if (i != 0 && !brainFrame.Active) { continue; } brainFrame.workingBlend.CamA = brainFrame.blend.CamA; brainFrame.workingBlend.CamB = brainFrame.blend.CamB; brainFrame.workingBlend.BlendCurve = brainFrame.blend.BlendCurve; brainFrame.workingBlend.Duration = brainFrame.blend.Duration; brainFrame.workingBlend.TimeInBlend = brainFrame.blend.TimeInBlend; if (i > 0 && !brainFrame.blend.IsComplete) { if (brainFrame.workingBlend.CamA == null) { if (mFrameStack[index].blend.IsComplete) { brainFrame.workingBlend.CamA = mFrameStack[index].blend.CamB; } else { brainFrame.workingBlendSource.Blend = mFrameStack[index].workingBlend; brainFrame.workingBlend.CamA = brainFrame.workingBlendSource; } } else if (brainFrame.workingBlend.CamB == null) { if (mFrameStack[index].blend.IsComplete) { brainFrame.workingBlend.CamB = mFrameStack[index].blend.CamB; } else { brainFrame.workingBlendSource.Blend = mFrameStack[index].workingBlend; brainFrame.workingBlend.CamB = brainFrame.workingBlendSource; } } } index = i; } CinemachineBlend workingBlend = mFrameStack[index].workingBlend; outputBlend.CamA = workingBlend.CamA; outputBlend.CamB = workingBlend.CamB; outputBlend.BlendCurve = workingBlend.BlendCurve; outputBlend.Duration = workingBlend.Duration; outputBlend.TimeInBlend = workingBlend.TimeInBlend; } public bool IsLive(ICinemachineCamera vcam, bool dominantChildOnly = false) { if (SoloCamera == vcam) { return true; } if (mCurrentLiveCameras.Uses(vcam)) { return true; } ICinemachineCamera parentCamera = vcam.ParentCamera; while (parentCamera != null && parentCamera.IsLiveChild(vcam, dominantChildOnly)) { if (SoloCamera == parentCamera || mCurrentLiveCameras.Uses(parentCamera)) { return true; } vcam = parentCamera; parentCamera = vcam.ParentCamera; } return false; } private ICinemachineCamera TopCameraFromPriorityQueue() { CinemachineCore instance = CinemachineCore.Instance; Camera outputCamera = OutputCamera; int num = (((Object)(object)outputCamera == (Object)null) ? (-1) : outputCamera.cullingMask); int virtualCameraCount = instance.VirtualCameraCount; for (int i = 0; i < virtualCameraCount; i++) { CinemachineVirtualCameraBase virtualCamera = instance.GetVirtualCamera(i); GameObject val = (((Object)(object)virtualCamera != (Object)null) ? ((Component)virtualCamera).gameObject : null); if ((Object)(object)val != (Object)null && (num & (1 << val.layer)) != 0) { return virtualCamera; } } return null; } private CinemachineBlendDefinition LookupBlend(ICinemachineCamera fromKey, ICinemachineCamera toKey) { CinemachineBlendDefinition cinemachineBlendDefinition = m_DefaultBlend; if ((Object)(object)m_CustomBlends != (Object)null) { string fromCameraName = ((fromKey != null) ? fromKey.Name : string.Empty); string toCameraName = ((toKey != null) ? toKey.Name : string.Empty); cinemachineBlendDefinition = m_CustomBlends.GetBlendForVirtualCameras(fromCameraName, toCameraName, cinemachineBlendDefinition); } if (CinemachineCore.GetBlendOverride != null) { cinemachineBlendDefinition = CinemachineCore.GetBlendOverride(fromKey, toKey, cinemachineBlendDefinition, (MonoBehaviour)(object)this); } return cinemachineBlendDefinition; } private void PushStateToUnityCamera(ref CameraState state) { //IL_0024: 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_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) CurrentCameraState = state; Transform transform = ControlledObject.transform; if ((state.BlendHint & CameraState.BlendHintValue.NoPosition) == 0) { transform.position = state.FinalPosition; } if ((state.BlendHint & CameraState.BlendHintValue.NoOrientation) == 0) { transform.rotation = state.FinalOrientation; } if ((state.BlendHint & CameraState.BlendHintValue.NoLens) == 0) { Camera outputCamera = OutputCamera; if ((Object)(object)outputCamera != (Object)null) { outputCamera.nearClipPlane = state.Lens.NearClipPlane; outputCamera.farClipPlane = state.Lens.FarClipPlane; outputCamera.orthographicSize = state.Lens.OrthographicSize; outputCamera.fieldOfView = state.Lens.FieldOfView; outputCamera.lensShift = state.Lens.LensShift; if (state.Lens.ModeOverride != LensSettings.OverrideModes.None) { outputCamera.orthographic = state.Lens.Orthographic; } bool flag = (outputCamera.usePhysicalProperties = ((state.Lens.ModeOverride == LensSettings.OverrideModes.None) ? outputCamera.usePhysicalProperties : state.Lens.IsPhysicalCamera)); if (flag && state.Lens.IsPhysicalCamera) { outputCamera.sensorSize = state.Lens.SensorSize; outputCamera.gateFit = state.Lens.GateFit; outputCamera.focalLength = Camera.FieldOfViewToFocalLength(state.Lens.FieldOfView, state.Lens.SensorSize.y); outputCamera.focusDistance = state.Lens.FocusDistance; } } } if (CinemachineCore.CameraUpdatedEvent != null) { ((UnityEvent<CinemachineBrain>)CinemachineCore.CameraUpdatedEvent).Invoke(this); } } } [DocumentationSorting(DocumentationSortingAttribute.Level.UserRef)] [ExecuteAlways] [DisallowMultipleComponent] [HelpURL("https://docs.unity3d.com/Packages/[email protected]/manual/CinemachineDollyCart.html")] public class CinemachineDollyCart : MonoBehaviour { public enum UpdateMethod { Update, FixedUpdate, LateUpdate } [Tooltip("The path to follow")] public CinemachinePathBase m_Path; [Tooltip("When to move the cart, if Velocity is non-zero")] public UpdateMethod m_UpdateMethod; [Tooltip("How to interpret the Path Position. If set to Path Units, values are as follows: 0 represents the first waypoint on the path, 1 is the second, and so on. Values in-between are points on the path in between the waypoints. If set to Distance, then Path Position represents distance along the path.")] public CinemachinePathBase.PositionUnits m_PositionUnits = CinemachinePathBase.PositionUnits.Distance; [Tooltip("Move the cart with this speed along the path. The value is interpreted according to the Position Units setting.")] [FormerlySerializedAs("m_Velocity")] public float m_Speed; [Tooltip("The position along the path at which the cart will be placed. This can be animated directly or, if the velocity is non-zero, will be updated automatically. The value is interpreted according to the Position Units setting.")] [FormerlySerializedAs("m_CurrentDistance")] public float m_Position; private void FixedUpdate() { if (m_UpdateMethod == UpdateMethod.FixedUpdate) { SetCartPosition(m_Position + m_Speed * Time.deltaTime); } } private void Update() { float num = (Application.isPlaying ? m_Speed : 0f); if (m_UpdateMethod == UpdateMethod.Update) { SetCartPosition(m_Position + num * Time.deltaTime); } } private void LateUpdate() { if (!Application.isPlaying) { SetCartPosition(m_Position); } else if (m_UpdateMethod == UpdateMethod.LateUpdate) { SetCartPosition(m_Position + m_Speed * Time.deltaTime); } } private void SetCartPosition(float distanceAlongPath) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)m_Path != (Object)null) { m_Position = m_Path.StandardizeUnit(distanceAlongPath, m_PositionUnits); ((Component)this).transform.position = m_Path.EvaluatePositionAtUnit(m_Position, m_PositionUnits); ((Component)this).transform.rotation = m_Path.EvaluateOrientationAtUnit(m_Position, m_PositionUnits); } } } [DocumentationSorting(DocumentationSortingAttribute.Level.UserRef)] [RequireComponent(typeof(Camera))] [DisallowMultipleComponent] [AddComponentMenu("EnhancedSpectator.CameraRuntime.Cinemachine/CinemachineExternalCamera")] [ExecuteAlways] [HelpURL("https://docs.unity3d.com/Packages/[email protected]/manual/CinemachineExternalCamera.html")] public class CinemachineExternalCamera : CinemachineVirtualCameraBase { [Tooltip("The object that the camera is looking at. Setting this will improve the quality of the blends to and from this camera")] [NoSaveDuringPlay] [VcamTargetProperty] public Transform m_LookAt; private Camera m_Camera; private CameraState m_State = CameraState.Default; [Tooltip("Hint for blending positions to and from this virtual camera")] [FormerlySerializedAs("m_PositionBlending")] public BlendHint m_BlendHint; public override CameraState State => m_State; public override Transform LookAt { get { return m_LookAt; } set { m_LookAt = value; } } public override Transform Follow { get; set; } public override void InternalUpdateCameraState(Vector3 worldUp, float deltaTime) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: 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_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_006d: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: 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_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)m_Camera == (Object)null) { ((Component)this).TryGetComponent<Camera>(ref m_Camera); } m_State = CameraState.Default; m_State.RawPosition = ((Component)this).transform.position; m_State.RawOrientation = ((Component)this).transform.rotation; m_State.ReferenceUp = m_State.RawOrientation * Vector3.up; if ((Object)(object)m_Camera != (Object)null) { m_State.Lens = LensSettings.FromCamera(m_Camera); } if ((Object)(object)m_LookAt != (Object)null) { m_State.ReferenceLookAt = ((Component)m_LookAt).transform.position; Vector3 val = m_State.ReferenceLookAt - State.RawPosition; if (!val.AlmostZero()) { m_State.ReferenceLookAt = m_State.RawPosition + Vector3.Project(val, State.RawOrientation * Vector3.forward); } } ApplyPositionBlendMethod(ref m_State, m_BlendHint); InvokePostPipelineStageCallback(this, CinemachineCore.Stage.Finalize, ref m_State, deltaTime); } } [DocumentationSorting(DocumentationSortingAttribute.Level.UserRef)] [AddComponentMenu("")] [SaveDuringPlay] [ExecuteAlways] [DisallowMultipleComponent] [HelpURL("https://docs.unity3d.com/Packages/[email protected]/manual/CinemachineFollowZoom.html")] public class CinemachineFollowZoom : CinemachineExtension { private class VcamExtraState { public float m_previousFrameZoom; } [Tooltip("The shot width to maintain, in world units, at target distance.")] public float m_Width = 2f; [Range(0f, 20f)] [Tooltip("Increase this value to soften the aggressiveness of the follow-zoom. Small numbers are more responsive, larger numbers give a more heavy slowly responding camera.")] public float m_Damping = 1f; [Range(1f, 179f)] [Tooltip("Lower limit for the FOV that this behaviour will generate.")] public float m_MinFOV = 3f; [Range(1f, 179f)] [Tooltip("Upper limit for the FOV that this behaviour will generate.")] public float m_MaxFOV = 60f; private void OnValidate() { m_Width = Mathf.Max(0f, m_Width); m_MaxFOV = Mathf.Clamp(m_MaxFOV, 1f, 179f); m_MinFOV = Mathf.Clamp(m_MinFOV, 1f, m_MaxFOV); } public override float GetMaxDampTime() { return m_Damping; } protected override void PostPipelineStageCallback(CinemachineVirtualCameraBase vcam, CinemachineCore.Stage stage, ref CameraState state, float deltaTime) { //IL_004d: 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) VcamExtraState extraState = GetExtraState<VcamExtraState>(vcam); if (deltaTime < 0f || !base.VirtualCamera.PreviousStateIsValid) { extraState.m_previousFrameZoom = state.Lens.FieldOfView; } if (stage != CinemachineCore.Stage.Body) { return; } float num = Mathf.Max(m_Width, 0f); float num2 = 179f; float num3 = Vector3.Distance(state.CorrectedPosition, state.ReferenceLookAt); if (num3 > 0.0001f) { float num4 = num3 * 2f * Mathf.Tan(m_MinFOV * (MathF.PI / 180f) / 2f); float num5 = num3 * 2f * Mathf.Tan(m_MaxFOV * (MathF.PI / 180f) / 2f); num = Mathf.Clamp(num, num4, num5); if (deltaTime >= 0f && m_Damping > 0f && base.VirtualCamera.PreviousStateIsValid) { float num6 = num3 * 2f * Mathf.Tan(extraState.m_previousFrameZoom * (MathF.PI / 180f) / 2f); float initial = num - num6; initial = base.VirtualCamera.DetachedLookAtTargetDamp(initial, m_Damping, deltaTime); num = num6 + initial; } num2 = 2f * Mathf.Atan(num / (2f * num3)) * 57.29578f; } LensSettings lens = state.Lens; lens.FieldOfView = (extraState.m_previousFrameZoom = Mathf.Clamp(num2, m_MinFOV, m_MaxFOV)); state.Lens = lens; } } [DocumentationSorting(DocumentationSortingAttribute.Level.UserRef)] [DisallowMultipleComponent] [ExecuteAlways] [ExcludeFromPreset] [AddComponentMenu("EnhancedSpectator.CameraRuntime.Cinemachine/CinemachineFreeLook")] [HelpURL("https://docs.unity3d.com/Packages/[email protected]/manual/CinemachineFreeLook.html")] public class CinemachineFreeLook : CinemachineVirtualCameraBase { [Serializable] public struct Orbit { public float m_Height; public float m_Radius; public Orbit(float h, float r) { m_Height = h; m_Radius = r; } } public delegate CinemachineVirtualCamera CreateRigDelegate(CinemachineFreeLook vcam, string name, CinemachineVirtualCamera copyFrom); public delegate void DestroyRigDelegate(GameObject rig); [Tooltip("Object for the camera children to look at (the aim target).")] [NoSaveDuringPlay] [VcamTargetProperty] public Transform m_LookAt; [Tooltip("Object for the camera children wants to move with (the body target).")] [NoSaveDuringPlay] [VcamTargetProperty] public Transform m_Follow; [Tooltip("If enabled, this lens setting will apply to all three child rigs, otherwise the child rig lens settings will be used")] [FormerlySerializedAs("m_UseCommonLensSetting")] public bool m_CommonLens = true; [FormerlySerializedAs("m_LensAttributes")] [Tooltip("Specifies the lens properties of this Virtual Camera. This generally mirrors the Unity Camera's lens settings, and will be used to drive the Unity camera when the vcam is active")] public LensSettings m_Lens = LensSettings.Default; public TransitionParams m_Transitions; [SerializeField] [HideInInspector] [FormerlySerializedAs("m_BlendHint")] [FormerlySerializedAs("m_PositionBlending")] private BlendHint m_LegacyBlendHint; [Header("Axis Control")] [Tooltip("The Vertical axis. Value is 0..1. Chooses how to blend the child rigs")] [AxisStateProperty] public AxisState m_YAxis = new AxisState(0f, 1f, wrap: false, rangeLocked: true, 2f, 0.2f, 0.1f, "Mouse Y", invert: false); [Tooltip("Controls how automatic recentering of the Y axis is accomplished")] public AxisState.Recentering m_YAxisRecentering = new AxisState.Recentering(enabled: false, 1f, 2f); [Tooltip("The Horizontal axis. Value is -180...180. This is passed on to the rigs' OrbitalTransposer component")] [AxisStateProperty] public AxisState m_XAxis = new AxisState(-180f, 180f, wrap: true, rangeLocked: false, 300f, 0.1f, 0.1f, "Mouse X", invert: true); [OrbitalTransposerHeadingProperty] [Tooltip("The definition of Forward. Camera will follow behind.")] public CinemachineOrbitalTransposer.Heading m_Heading = new CinemachineOrbitalTransposer.Heading(CinemachineOrbitalTransposer.Heading.HeadingDefinition.TargetForward, 4, 0f); [Tooltip("Controls how automatic recentering of the X axis is accomplished")] public AxisState.Recentering m_RecenterToTargetHeading = new AxisState.Recentering(enabled: false, 1f, 2f); [Header("Orbits")] [Tooltip("The coordinate space to use when interpreting the offset from the target. This is also used to set the camera's Up vector, which will be maintained when aiming the camera.")] public CinemachineTransposer.BindingMode m_BindingMode = CinemachineTransposer.BindingMode.SimpleFollowWithWorldUp; [Tooltip("Controls how taut is the line that connects the rigs' orbits, which determines final placement on the Y axis")] [Range(0f, 1f)] [FormerlySerializedAs("m_SplineTension")] public float m_SplineCurvature = 0.2f; [Tooltip("The radius and height of the three orbiting rigs.")] public Orbit[] m_Orbits = new Orbit[3] { new Orbit(4.5f, 1.75f), new Orbit(2.5f, 3f), new Orbit(0.4f, 1.3f) }; [SerializeField] [HideInInspector] [FormerlySerializedAs("m_HeadingBias")] private float m_LegacyHeadingBias = float.MaxValue; private bool mUseLegacyRigDefinitions; private bool mIsDestroyed; private CameraState m_State = CameraState.Default; [SerializeField] [HideInInspector] [NoSaveDuringPlay] private CinemachineVirtualCamera[] m_Rigs = new CinemachineVirtualCamera[3]; private CinemachineOrbitalTransposer[] mOrbitals; private CinemachineBlend mBlendA; private CinemachineBlend mBlendB; public static CreateRigDelegate CreateRigOverride; public static DestroyRigDelegate DestroyRigOverride; private float m_CachedXAxisHeading; private float m_LastHeadingUpdateFrame; private Orbit[] m_CachedOrbits; private float m_CachedTension; private Vector4[] m_CachedKnots; private Vector4[] m_CachedCtrl1; private Vector4[] m_CachedCtrl2; internal bool RigsAreCreated { get { if (m_Rigs != null) { return m_Rigs.Length == 3; } return false; } } public static string[] RigNames => new string[3] { "TopRig", "MiddleRig", "BottomRig" }; public override bool PreviousStateIsValid { get { return base.PreviousStateIsValid; } set { if (!value) { int num = 0; while (m_Rigs != null && num < m_Rigs.Length) { if ((Object)(object)m_Rigs[num] != (Object)null) { m_Rigs[num].PreviousStateIsValid = value; } num++; } } base.PreviousStateIsValid = value; } } public override CameraState State => m_State; public override Transform LookAt { get { return ResolveLookAt(m_LookAt); } set { m_LookAt = value; } } public override Transform Follow { get { return ResolveFollow(m_Follow); } set { m_Follow = value; } } protected override void OnValidate() { base.OnValidate(); if (m_LegacyHeadingBias != float.MaxValue) { m_Heading.m_Bias = m_LegacyHeadingBias; m_LegacyHeadingBias = float.MaxValue; int heading = (int)m_Heading.m_Definition; if (m_RecenterToTargetHeading.LegacyUpgrade(ref heading, ref m_Heading.m_VelocityFilterStrength)) { m_Heading.m_Definition = (CinemachineOrbitalTransposer.Heading.HeadingDefinition)heading; } mUseLegacyRigDefinitions = true; } if (m_LegacyBlendHint != BlendHint.None) { m_Transitions.m_BlendHint = m_LegacyBlendHint; m_LegacyBlendHint = BlendHint.None; } m_YAxis.Validate(); m_XAxis.Validate(); m_RecenterToTargetHeading.Validate(); m_YAxisRecentering.Validate(); m_Lens.Validate(); InvalidateRigCache(); } public CinemachineVirtualCamera GetRig(int i) { if (!UpdateRigCache() || i < 0 || i >= 3) { return null; } return m_Rigs[i]; } protected override void OnEnable() { mIsDestroyed = false; base.OnEnable(); InvalidateRigCache(); UpdateInputAxisProvider(); } public void UpdateInputAxisProvider() { m_XAxis.SetInputAxisProvider(0, null); m_YAxis.SetInputAxisProvider(1, null); AxisState.IInputAxisProvider inputAxisProvider = GetInputAxisProvider(); if (inputAxisProvider != null) { m_XAxis.SetInputAxisProvider(0, inputAxisProvider); m_YAxis.SetInputAxisProvider(1, inputAxisProvider); } } protected override void OnDestroy() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) if (m_Rigs != null) { CinemachineVirtualCamera[] rigs = m_Rigs; foreach (CinemachineVirtualCamera cinemachineVirtualCamera in rigs) { if ((Object)(object)cinemachineVirtualCamera != (Object)null && (Object)(object)((Component)cinemachineVirtualCamera).gameObject != (Object)null) { GameObject gameObject = ((Component)cinemachineVirtualCamera).gameObject; ((Object)gameObject).hideFlags = (HideFlags)(((Object)gameObject).hideFlags & -4); } } } mIsDestroyed = true; base.OnDestroy(); } private void OnTransformChildrenChanged() { InvalidateRigCache(); } private void Reset() { DestroyRigs(); UpdateRigCache(); } public override bool IsLiveChild(ICinemachineCamera vcam, bool dominantChildOnly = false) { if (!RigsAreCreated) { return false; } float yAxisValue = GetYAxisValue(); if (dominantChildOnly) { if (vcam == m_Rigs[0]) { return yAxisValue > 0.666f; } if (vcam == m_Rigs[2]) { return (double)yAxisValue < 0.333; } if (vcam == m_Rigs[1]) { if (yAxisValue >= 0.333f) { return yAxisValue <= 0.666f; } return false; } return false; } if (vcam == m_Rigs[1]) { return true; } if (yAxisValue < 0.5f) { return vcam == m_Rigs[2]; } return vcam == m_Rigs[0]; } public override void OnTargetObjectWarped(Transform target, Vector3 positionDelta) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) UpdateRigCache(); if (RigsAreCreated) { CinemachineVirtualCamera[] rigs = m_Rigs; for (int i = 0; i < rigs.Length; i++) { rigs[i].OnTargetObjectWarped(target, positionDelta); } } base.OnTargetObjectWarped(target, positionDelta); } public override void ForceCameraPosition(Vector3 pos, Quaternion rot) { //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_0013: 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_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) Vector3 referenceUp = State.ReferenceUp; m_YAxis.Value = GetYAxisClosestValue(pos, referenceUp); PreviousStateIsValid = true; ((Component)this).transform.position = pos; ((Component)this).transform.rotation = rot; m_State.RawPosition = pos; m_State.RawOrientation = rot; if (UpdateRigCache()) { for (int i = 0; i < 3; i++) { m_Rigs[i].ForceCameraPosition(pos, rot); } if (m_BindingMode != CinemachineTransposer.BindingMode.SimpleFollowWithWorldUp) { m_XAxis.Value = mOrbitals[1].m_XAxis.Value; } PushSettingsToRigs(); InternalUpdateCameraState(referenceUp, -1f); } base.ForceCameraPosition(pos, rot); } public override void InternalUpdateCameraState(Vector3 worldUp, float deltaTime) { //IL_0018: 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_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_008c: 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_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: 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_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) UpdateTargetCache(); UpdateRigCache(); if (RigsAreCreated) { m_State = CalculateNewState(worldUp, deltaTime); ApplyPositionBlendMethod(ref m_State, m_Transitions.m_BlendHint); if ((Object)(object)Follow != (Object)null) { Vector3 val = State.RawPosition - ((Component)this).transform.position; ((Component)this).transform.position = State.RawPosition; Transform transform = ((Component)m_Rigs[0]).transform; transform.position -= val; Transform transform2 = ((Component)m_Rigs[1]).transform; transform2.position -= val; Transform transform3 = ((Component)m_Rigs[2]).transform; transform3.position -= val; } InvokePostPipelineStageCallback(this, CinemachineCore.Stage.Finalize, ref m_State, deltaTime); PreviousStateIsValid = true; if (PreviousStateIsValid && CinemachineCore.Instance.IsLive(this) && deltaTime >= 0f && m_YAxis.Update(deltaTime)) { m_YAxisRecentering.CancelRecentering(); } PushSettingsToRigs(); if (m_BindingMode == CinemachineTransposer.BindingMode.SimpleFollowWithWorldUp) { m_XAxis.Value = 0f; } } } public override void OnTransitionFromCamera(ICinemachineCamera fromCam, Vector3 worldUp, float deltaTime) { //IL_0002: 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_008f: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: 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_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0072: 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) base.OnTransitionFromCamera(fromCam, worldUp, deltaTime); if (!RigsAreCreated) { return; } InvokeOnTransitionInExtensions(fromCam, worldUp, deltaTime); if (fromCam != null && m_Transitions.m_InheritPosition && !CinemachineCore.Instance.IsLiveInBlend(this)) { Vector3 pos = fromCam.State.RawPosition; if (fromCam is CinemachineFreeLook) { CinemachineFreeLook cinemachineFreeLook = fromCam as CinemachineFreeLook; CinemachineOrbitalTransposer cinemachineOrbitalTransposer = ((cinemachineFreeLook.mOrbitals != null) ? cinemachineFreeLook.mOrbitals[1] : null); if ((Object)(object)cinemachineOrbitalTransposer != (Object)null) { pos = cinemachineOrbitalTransposer.GetTargetCameraPosition(worldUp); } } ForceCameraPosition(pos, fromCam.State.FinalOrientation); } UpdateCameraState(worldUp, deltaTime); if (m_Transitions.m_OnCameraLive != null) { ((UnityEvent<ICinemachineCamera, ICinemachineCamera>)m_Transitions.m_OnCameraLive).Invoke((ICinemachineCamera)this, fromCam); } } internal override bool RequiresUserInput() { return true; } private float GetYAxisClosestValue(Vector3 cameraPos, Vector3 up) { //IL_0011: 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_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_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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) //IL_0041: 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_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_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_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) if ((Object)(object)Follow != (Object)null) { Vector3 val = Quaternion.FromToRotation(up, Vector3.up) * (cameraPos - Follow.position); Vector3 val2 = val; val2.y = 0f; if (!val2.AlmostZero()) { val = Quaternion.AngleAxis(UnityVectorExtensions.SignedAngle(val2, Vector3.back, Vector3.up), Vector3.up) * val; } val.x = 0f; Vector3 normalized = ((Vector3)(ref val)).normalized; Vector3 val3 = cameraPos - Follow.position; return SteepestDescent(normalized * ((Vector3)(ref val3)).magnitude); } return m_YAxis.Value; } private float SteepestDescent(Vector3 cameraOffset) { //IL_000a: 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_0012: Unknown result type (might be due to invalid IL or missing references) float num = InitialGuess(cameraOffset); for (int i = 0; i < 10; i++) { float num2 = AngleFunction(num); float num3 = SlopeOfAngleFunction(num); if (Mathf.Abs(num3) < 5E-05f || Mathf.Abs(num2) < 5E-05f) { break; } num = Mathf.Clamp01(num - num2 / num3); } return num; float AngleFunction(float input) { //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_0009: 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_000f: Unknown result type (might be due to invalid IL or missing references) Vector3 localPositionForCameraFromInput = GetLocalPositionForCameraFromInput(input); return Mathf.Abs(UnityVectorExtensions.SignedAngle(cameraOffset, localPositionForCameraFromInput, Vector3.right)); } float InitialGuess(Vector3 cameraPosInRigSpace) { //IL_000d: 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_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_002c: 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_002e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: 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) //IL_0035: 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_0041: 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) //IL_0047: 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_005d: 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_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: 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_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) UpdateCachedSpline(); Vector4 val = m_CachedKnots[1]; Vector4 val2 = m_CachedKnots[2]; Vector4 val3 = m_CachedKnots[3]; float num4 = cameraPosInRigSpace.ClosestPointOnSegment(Vector4.op_Implicit(val), Vector4.op_Implicit(val2)); float num5 = Vector3.SqrMagnitude(Vector3.Lerp(Vector4.op_Implicit(val), Vector4.op_Implicit(val2), num4) - cameraPosInRigSpace); float num6 = cameraPosInRigSpace.ClosestPointOnSegment(Vector4.op_Implicit(val2), Vector4.op_Implicit(val3)); float num7 = Vector3.SqrMagnitude(Vector3.Lerp(Vector4.op_Implicit(val2), Vector4.op_Implicit(val3), num6) - cameraPosInRigSpace); if (!(num5 < num7)) { return Mathf.Lerp(0.5f, 1f, num6); } return Mathf.Lerp(0f, 0.5f, num4); } float SlopeOfAngleFunction(float input) { float num4 = AngleFunction(input - 5E-05f); return (AngleFunction(input + 5E-05f) - num4) / 0.0001f; } } private void InvalidateRigCache() { mOrbitals = null; } private void DestroyRigs() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown List<CinemachineVirtualCamera> list = new List<CinemachineVirtualCamera>(3); for (int i = 0; i < RigNames.Length; i++) { foreach (Transform item in ((Component)this).transform) { Transform val = item; if (((Object)((Component)val).gameObject).name == RigNames[i]) { list.Add(((Component)val).GetComponent<CinemachineVirtualCamera>()); } } } foreach (CinemachineVirtualCamera item2 in list) { if (!((Object)(object)item2 != (Object)null)) { continue; } if (DestroyRigOverride != null) { DestroyRigOverride(((Component)item2).gameObject); continue; } item2.DestroyPipeline(); Object.Destroy((Object)(object)item2); if (!RuntimeUtility.IsPrefab(((Component)this).gameObject)) { Object.Destroy((Object)(object)((Component)item2).gameObject); } } mOrbitals = null; m_Rigs = null; } private CinemachineVirtualCamera[] CreateRigs(CinemachineVirtualCamera[] copyFrom) { //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Expected O, but got Unknown //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Expected O, but got Unknown float[] array = new float[3] { 0.5f, 0.55f, 0.6f }; mOrbitals = null; m_Rigs = null; CinemachineVirtualCamera[] array2 = new CinemachineVirtualCamera[3]; for (int i = 0; i < array2.Length; i++) { CinemachineVirtualCamera cinemachineVirtualCamera = ((copyFrom != null && copyFrom.Length > i) ? copyFrom[i] : null); if (CreateRigOverride != null) { array2[i] = CreateRigOverride(this, RigNames[i], cinemachineVirtualCamera); } else { GameObject val = null; foreach (Transform item in ((Component)this).transform) { Transform val2 = item; if (((Object)((Component)val2).gameObject).name == RigNames[i]) { val = ((Component)val2).gameObject; break; } } if ((Object)(object)val == (Object)null && !RuntimeUtility.IsPrefab(((Component)this).gameObject)) { val = new GameObject(RigNames[i]); val.transform.parent = ((Component)this).transform; } if ((Object)(object)val == (Object)null) { array2[i] = null; } else { array2[i] = val.AddComponent<CinemachineVirtualCamera>(); array2[i].AddCinemachineComponent<CinemachineOrbitalTransposer>(); array2[i].AddCinemachineComponent<CinemachineComposer>(); } } if (!((Object)(object)array2[i] != (Object)null)) { continue; } array2[i].InvalidateComponentPipeline(); CinemachineOrbitalTransposer cinemachineOrbitalTransposer = array2[i].GetCinemachineComponent<CinemachineOrbitalTransposer>(); if ((Object)(object)cinemachineOrbitalTransposer == (Object)null) { cinemachineOrbitalTransposer = array2[i].AddCinemachineComponent<CinemachineOrbitalTransposer>(); } if ((Object)(object)cinemachineVirtualCamera == (Object)null) { cinemachineOrbitalTransposer.m_YawDamping = 0f; CinemachineComposer cinemachineComponent = array2[i].GetCinemachineComponent<CinemachineComposer>(); if ((Object)(object)cinemachineComponent != (Object)null) { cinemachineComponent.m_HorizontalDamping = (cinemachineComponent.m_VerticalDamping = 0f); cinemachineComponent.m_ScreenX = 0.5f; cinemachineComponent.m_ScreenY = array[i]; cinemachineComponent.m_DeadZoneWidth = (cinemachineComponent.m_DeadZoneHeight = 0f); cinemachineComponent.m_SoftZoneWidth = (cinemachineComponent.m_SoftZoneHeight = 0.8f); cinemachineComponent.m_BiasX = (cinemachineComponent.m_BiasY = 0f); } } } return array2; } private bool UpdateRigCache() { if (mIsDestroyed) { return false; } if (mOrbitals != null && mOrbitals.Length == 3) { return true; } m_CachedXAxisHeading = 0f; m_Rigs = null; mOrbitals = null; List<CinemachineVirtualCamera> list = LocateExistingRigs(forceOrbital: false); if (list == null || list.Count != 3) { DestroyRigs(); CreateRigs(null); list = LocateExistingRigs(forceOrbital: true); } if (list != null && list.Count == 3) { m_Rigs = list.ToArray(); } if (RigsAreCreated) { mOrbitals = new CinemachineOrbitalTransposer[m_Rigs.Length]; for (int i = 0; i < m_Rigs.Length; i++) { mOrbitals[i] = m_Rigs[i].GetCinemachineComponent<CinemachineOrbitalTransposer>(); } mBlendA = new CinemachineBlend(m_Rigs[1], m_Rigs[0], AnimationCurve.Linear(0f, 0f, 1f, 1f), 1f, 0f); mBlendB = new CinemachineBlend(m_Rigs[2], m_Rigs[1], AnimationCurve.Linear(0f, 0f, 1f, 1f), 1f, 0f); return true; } return false; } private List<CinemachineVirtualCamera> LocateExistingRigs(bool forceOrbital) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown m_CachedXAxisHeading = m_XAxis.Value; m_LastHeadingUpdateFrame = -1f; List<CinemachineVirtualCamera> list = new List<CinemachineVirtualCamera>(3); foreach (Transform item in ((Component)this).transform) { Transform val = item; CinemachineVirtualCamera component = ((Component)val).GetComponent<CinemachineVirtualCamera>(); if (!((Object)(object)component != (Object)null)) { continue; } GameObject gameObject = ((Component)val).gameObject; for (int i = 0; i < RigNames.Length; i++) { if (!(((Object)gameObject).name != RigNames[i])) { CinemachineOrbitalTransposer cinemachineOrbitalTransposer = component.GetCinemachineComponent<CinemachineOrbitalTransposer>(); if ((Object)(object)cinemachineOrbitalTransposer == (Object)null && forceOrbital) { cinemachineOrbitalTransposer = component.AddCinemachineComponent<CinemachineOrbitalTransposer>(); } if ((Object)(object)cinemachineOrbitalTransposer != (Object)null) { cinemachineOrbitalTransposer.m_HeadingIsSlave = true; cinemachineOrbitalTransposer.HideOffsetInInspector = true; cinemachineOrbitalTransposer.m_XAxis.m_InputAxisName = string.Empty; cinemachineOrbitalTransposer.HeadingUpdater = UpdateXAxisHeading; cinemachineOrbitalTransposer.m_RecenterToTargetHeading.m_enabled = false; component.m_StandbyUpdate = m_StandbyUpdate; list.Add(component); } } } } return list; } private float UpdateXAxisHeading(CinemachineOrbitalTransposer orbital, float deltaTime, Vector3 up) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)this == (Object)null) { return 0f; } if (!PreviousStateIsValid) { deltaTime = -1f; } if (m_LastHeadingUpdateFrame != (float)Time.frameCount || deltaTime < 0f) { m_LastHeadingUpdateFrame = Time.frameCount; float value = m_XAxis.Value; m_CachedXAxisHeading = orbital.UpdateHeading(deltaTime, up, ref m_XAxis, ref m_RecenterToTargetHeading, CinemachineCore.Instance.IsLive(this)); if (m_BindingMode == CinemachineTransposer.BindingMode.SimpleFollowWithWorldUp) { m_XAxis.Value = value; } } return m_CachedXAxisHeading; } private void PushSettingsToRigs() { //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_012d: 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) for (int i = 0; i < m_Rigs.Length; i++) { if (m_CommonLens) { m_Rigs[i].m_Lens = m_Lens; } if (mUseLegacyRigDefinitions) { mUseLegacyRigDefinitions = false; m_Orbits[i].m_Height = mOrbitals[i].m_FollowOffset.y; m_Orbits[i].m_Radius = 0f - mOrbitals[i].m_FollowOffset.z; if ((Object)(object)m_Rigs[i].Follow != (Object)null) { Follow = m_Rigs[i].Follow; } } m_Rigs[i].Follow = null; m_Rigs[i].m_StandbyUpdate = m_StandbyUpdate; m_Rigs[i].FollowTargetAttachment = FollowTargetAttachment; m_Rigs[i].LookAtTargetAttachment = LookAtTargetAttachment; if (!PreviousStateIsValid) { m_Rigs[i].PreviousStateIsValid = false; ((Component)m_Rigs[i]).transform.position = ((Component)this).transform.position; ((Component)m_Rigs[i]).transform.rotation = ((Component)this).transform.rotation; } mOrbitals[i].m_FollowOffset = GetLocalPositionForCameraFromInput(GetYAxisValue()); mOrbitals[i].m_BindingMode = m_BindingMode; mOrbitals[i].m_Heading = m_Heading; mOrbitals[i].m_XAxis.Value = m_XAxis.Value; if (m_BindingMode == CinemachineTransposer.BindingMode.SimpleFollowWithWorldUp) { m_Rigs[i].SetStateRawPosition(State.RawPosition); } } } private float GetYAxisValue() { float num = m_YAxis.m_MaxValue - m_YAxis.m_MinValue; if (!(num > 0.0001f)) { return 0.5f; } return m_YAxis.Value / num; } private CameraState CalculateNewState(Vector3 worldUp, float deltaTime) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) CameraState result = PullStateFromVirtualCamera(worldUp, ref m_Lens); m_YAxisRecentering.DoRecentering(ref m_YAxis, deltaTime, 0.5f); float yAxisValue = GetYAxisValue(); if (yAxisValue > 0.5f) { if (mBlendA != null) { mBlendA.TimeInBlend = (yAxisValue - 0.5f) * 2f; mBlendA.UpdateCameraState(worldUp, deltaTime); result = mBlendA.State; } } else if (mBlendB != null) { mBlendB.TimeInBlend = yAxisValue * 2f; mBlendB.UpdateCameraState(worldUp, deltaTime); result = mBlendB.State; } return result; } public Vector3 GetLocalPositionForCameraFromInput(float t) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //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_0059: 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_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) if (mOrbitals == null) { return Vector3.zero; } UpdateCachedSpline(); int num = 1; if (t > 0.5f) { t -= 0.5f; num = 2; } return SplineHelpers.Bezier3(t * 2f, Vector4.op_Implicit(m_CachedKnots[num]), Vector4.op_Implicit(m_CachedCtrl1[num]), Vector4.op_Implicit(m_CachedCtrl2[num]), Vector4.op_Implicit(m_CachedKnots[num + 1])); } private void UpdateCachedSpline() { //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0162: 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_017a: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) bool flag = m_CachedOrbits != null && m_CachedOrbits.Length == 3 && m_CachedTension == m_SplineCurvature; for (int i = 0; i < 3 && flag; i++) { flag = m_CachedOrbits[i].m_Height == m_Orbits[i].m_Height && m_CachedOrbits[i].m_Radius == m_Orbits[i].m_Radius; } if (!flag) { float splineCurvature = m_SplineCurvature; m_CachedKnots = (Vector4[])(object)new Vector4[5]; m_CachedCtrl1 = (Vector4[])(object)new Vector4[5]; m_CachedCtrl2 = (Vector4[])(object)new Vector4[5]; m_CachedKnots[1] = new Vector4(0f, m_Orbits[2].m_Height, 0f - m_Orbits[2].m_Radius, 0f); m_CachedKnots[2] = new Vector4(0f, m_Orbits[1].m_Height, 0f - m_Orbits[1].m_Radius, 0f); m_CachedKnots[3] = new Vector4(0f, m_Orbits[0].m_Height, 0f - m_Orbits[0].m_Radius, 0f); m_CachedKnots[0] = Vector4.Lerp(m_CachedKnots[1], Vector4.zero, splineCurvature); m_CachedKnots[4] = Vector4.Lerp(m_CachedKnots[3], Vector4.zero, splineCurvature); SplineHelpers.ComputeSmoothControlPoints(ref m_CachedKnots, ref m_CachedCtrl1, ref m_CachedCtrl2); m_CachedOrbits = new Orbit[3]; for (int j = 0; j < 3; j++) { m_CachedOrbits[j] = m_Orbits[j]; } m_CachedTension = m_SplineCurvature; } } internal override void OnBeforeSerialize() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (!m_Lens.IsPhysicalCamera) { m_Lens.SensorSize = Vector2.one; } } } [DocumentationSorting(DocumentationSortingAttribute.Level.UserRef)] [DisallowMultipleComponent] [ExecuteAlways] [ExcludeFromPreset] [AddComponentMenu("EnhancedSpectator.CameraRuntime.Cinemachine/CinemachineMixingCamera")] [HelpURL("https://docs.unity3d.com/Packages/[email protected]/manual/CinemachineMixingCamera.html")] public class CinemachineMixingCamera : CinemachineVirtualCameraBase { public const int MaxCameras = 8; [Tooltip("The weight of the first tracked camera")] public float m_Weight0 = 0.5f; [Tooltip("The weight of the second tracked camera")] public float m_Weight1 = 0.5f; [Tooltip("The weight of the third tracked camera")] public float m_Weight2 = 0.5f; [Tooltip("The weight of the fourth tracked camera")] public float m_Weight3 = 0.5f; [Tooltip("The weight of the fifth tracked camera")] public float m_Weight4 = 0.5f; [Tooltip("The weight of the sixth tracked camera")] public float m_Weight5 = 0.5f; [Tooltip("The weight of the seventh tracked camera")] public float m_Weight6 = 0.5f; [Tooltip("The weight of the eighth tracked camera")] public float m_Weight7 = 0.5f; private CameraState m_State = CameraState.Default; private CinemachineVirtualCameraBase[] m_ChildCameras; private Dictionary<CinemachineVirtualCameraBase, int> m_indexMap; private ICinemachineCamera LiveChild { get; set; } public override CameraState State => m_State; public override Transform LookAt { get; set; } public override Transform Follow { get; set; } public CinemachineVirtualCameraBase[] ChildCameras { get { ValidateListOfChildren(); return m_ChildCameras; } } public float GetWeight(int index) { switch (index) { case 0: return m_Weight0; case 1: return m_Weight1; case 2: return m_Weight2; case 3: return m_Weight3; case 4: return m_Weight4; case 5: return m_Weight5; case 6: return m_Weight6; case 7: return m_Weight7; default: Debug.LogError((object)("CinemachineMixingCamera: Invalid index: " + index)); return 0f; } } public void SetWeight(int index, float w) { switch (index) { case 0: m_Weight0 = w; break; case 1: m_Weight1 = w; break; case 2: m_Weight2 = w; break; case 3: m_Weight3 = w; break; case 4: m_Weight4 = w; break; case 5: m_Weight5 = w; break; case 6: m_Weight6 = w; break; case 7: m_Weight7 = w; break; default: Debug.LogError((object)("CinemachineMixingCamera: Invalid index: " + index)); break; } } public float GetWeight(CinemachineVirtualCameraBase vcam) { ValidateListOfChildren(); if (m_indexMap.TryGetValue(vcam, out var value)) { return GetWeight(value); } Debug.LogError((object)("CinemachineMixingCamera: Invalid child: " + (((Object)(object)vcam != (Object)null) ? vcam.Name : "(null)"))); return 0f; } public void SetWeight(CinemachineVirtualCameraBase vcam, float w) { ValidateListOfChildren(); if (m_indexMap.TryGetValue(vcam, out var value)) { SetWeight(value, w); } else { Debug.LogError((object)("CinemachineMixingCamera: Invalid child: " + (((Object)(object)vcam != (Object)null) ? vcam.Name : "(null)"))); } } public override void OnTargetObjectWarped(Transform target, Vector3 positionDelta) { //IL_0015: 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) ValidateListOfChildren(); CinemachineVirtualCameraBase[] childCameras = m_ChildCameras; for (int i = 0; i < childCameras.Length; i++) { childCameras[i].OnTargetObjectWarped(target, positionDelta); } base.OnTargetObjectWarped(target, positionDelta); } public override void ForceCameraPosition(Vector3 pos, Quaternion rot) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0026: 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) ValidateListOfChildren(); CinemachineVirtualCameraBase[] childCameras = m_ChildCameras; for (int i = 0; i < childCameras.Length; i++) { childCameras[i].ForceCameraPosition(pos, rot); } base.ForceCameraPosition(pos, rot); } protected override void OnEnable() { base.OnEnable(); InvalidateListOfChildren(); } public void OnTransformChildrenChanged() { InvalidateListOfChildren(); } protected override void OnValidate() { base.OnValidate(); for (int i = 0; i < 8; i++) { SetWeight(i, Mathf.Max(0f, GetWeight(i))); } } public override bool IsLiveChild(ICinemachineCamera vcam, bool dominantChildOnly = false) { CinemachineVirtualCameraBase[] childCameras = ChildCameras; for (int i = 0; i < 8 && i < childCameras.Length; i++) { if (childCameras[i] == vcam) { if (GetWeight(i) > 0.0001f) { return ((Behaviour)childCameras[i]).isActiveAndEnabled; } return false; } } return false; } protected void InvalidateListOfChildren() { m_ChildCameras = null; m_indexMap = null; LiveChild = null; } protected void ValidateListOfChildren() { if (m_ChildCameras != null) { return; } m_indexMap = new Dictionary<CinemachineVirtualCameraBase, int>(); List<CinemachineVirtualCameraBase> list = new List<CinemachineVirtualCameraBase>(); CinemachineVirtualCameraBase[] componentsInChildren = ((Component)this).GetComponentsInChildren<CinemachineVirtualCameraBase>(true); foreach (CinemachineVirtualCameraBase cinemachineVirtualCameraBase in componentsInChildren) { if ((Object)(object)((Component)cinemachineVirtualCameraBase).transform.parent == (Object)(object)((Component)this).transform) { int count = list.Count; list.Add(cinemachineVirtualCameraBase); if (count < 8) { m_indexMap.Add(cinemachineVirtualCameraBase, count); } } } m_ChildCameras = list.ToArray(); } public override void OnTransitionFromCamera(ICinemachineCamera fromCam, Vector3 worldUp, float deltaTime) { //IL_0002: 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_0038: Unknown result type (might be du