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 AddExtractionButton v0.2.0
BepInEx/plugins/AddExtractionButton/AddExtractionButton.dll
Decompiled 2 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("")] [assembly: AssemblyCompany("DJ-DarkLucky")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.2.0.0")] [assembly: AssemblyInformationalVersion("0.2.0+c1c6839f106c050be49a262ab27e7d8c2ac2ed9b")] [assembly: AssemblyProduct("AddExtractionButton")] [assembly: AssemblyTitle("AddExtractionButton")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.2.0.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 AddExtractionButton { internal sealed class ExtractionClownController : MonoBehaviour { private readonly struct PlacementBasis { internal Vector3 Origin { get; } internal Vector3 Right { get; } internal Vector3 Up { get; } internal Vector3 Into { get; } internal Bounds StorageBounds { get; } internal float ExpectedFloor { get; } internal PlacementBasis(Vector3 origin, Vector3 right, Vector3 up, Vector3 into, Bounds storageBounds, float expectedFloor) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: 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_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) Origin = origin; Right = right; Up = up; Into = into; StorageBounds = storageBounds; ExpectedFloor = expectedFloor; } } private sealed class DetachedCleanupEntry { internal GameObject Root { get; } internal ClownTrap? Clown { get; } internal int LookupId { get; } internal Room? Room { get; } internal PhotonView? RootView { get; } internal int RootViewId { get; } internal float NextAttemptAt { get; set; } internal bool FailureLogged { get; set; } internal DetachedCleanupEntry(GameObject root, ClownTrap? clown, int lookupId, Room? room, PhotonView? rootView, int rootViewId) { Root = root; Clown = clown; LookupId = lookupId; Room = room; RootView = rootView; RootViewId = rootViewId; } } private static readonly Dictionary<int, ExtractionClownController> ProxyOwners = new Dictionary<int, ExtractionClownController>(); private static readonly List<DetachedCleanupEntry> DetachedCleanups = new List<DetachedCleanupEntry>(); private static readonly HashSet<int> DetachedCleanupClownIds = new HashSet<int>(); private static bool DetachedCleanupRunnerFailureLogged; private static readonly string[] ClownResourcePathCandidates = new string[2] { "valuables/03 medium/Valuable Clown", "valuables/03 medium/Valueable Clown" }; private const float HeldSuccessDelaySeconds = 1.5f; private const float SpawnRetrySeconds = 1f; private const float PlacementFailureWarningDelaySeconds = 3f; private const float CleanupRetrySeconds = 1f; private const float PatchRevalidationSeconds = 1f; private const float AuthorityStabilizationSeconds = 1f; private const float InteractionRespawnCooldownSeconds = 0.35f; private const float StorageEdgeGap = 0.18f; private const float FloorClearance = 0.015f; private const float PlacementCollisionPadding = 0.035f; private const float PlacementCollisionSkin = 0.01f; private const float SupportProbeInset = 0.04f; private const float MaximumSupportHeightVariation = 0.035f; private const float MinimumSupportNormalDot = 0.65f; private const float ProxyBoundsTolerance = 0.05f; private const float SpawnPosePositionTolerance = 0.01f; private const float SpawnPoseRotationToleranceDegrees = 0.5f; private const float LockRefreshSeconds = 0.25f; private const float PositionCorrectionTolerance = 0.025f; private const float RotationCorrectionToleranceDegrees = 1f; private const float NetworkCorrectionCooldownSeconds = 0.2f; private const float MaximumFloorOffsetFromStorage = 1.25f; private const int NetworkProtocolVersion = 1; private ExtractionPoint _extractionPoint; private Transform _platform; private GameObject? _clownRoot; private GameObject? _orphanedSpawn; private ClownTrap? _clownTrap; private PhysGrabObject? _physGrabObject; private Rigidbody? _rigidbody; private Room? _clownSpawnRoom; private PhotonView? _clownRootPhotonView; private int _clownRootViewId; private bool _initialized; private bool _gateArmed; private bool _proxyConsumed; private bool _replacementRequested; private bool _pendingSuccess; private bool _successPermitAvailable; private bool _successPermitAccepted; private bool _successInvocationInProgress; private bool _submissionSent; private bool _blockedSuccessLogged; private bool _quotaPreviouslyReached; private bool _spawnFailureLogged; private bool _spawnAttemptDeferred; private bool _sessionFailedOpen; private bool _prefabInspectionWarningLogged; private bool _cleanupPending; private bool _wasCurrentActive; private bool _wasAuthoritative; private bool _destroyFailureLogged; private bool _controllerFailureLogged; private bool _staleProxyWarningLogged; private int _clownViewId; private float _nextSpawnAttemptAt; private float _placementFailureStartedAt = -1f; private float _replacementReadyAt; private float _nextNetworkCorrectionAt; private float _nextPatchRevalidationAt; private float _authorityReadyAt; private Vector3 _anchorPosition; private Quaternion _anchorRotation; private string? _resolvedResourcePath; private GameObject? _resolvedPrefab; private string? _lastDetailedSpawnFailure; private string? _nonRetryableSpawnFailure; internal void Initialize(ExtractionPoint extractionPoint) { _extractionPoint = extractionPoint; _platform = (((Object)(object)extractionPoint.platform != (Object)null) ? extractionPoint.platform : ((Component)extractionPoint).transform); _initialized = true; _wasAuthoritative = IsAuthoritative(); _authorityReadyAt = (_wasAuthoritative ? Time.realtimeSinceStartup : float.PositiveInfinity); Plugin.LogDebug("Attached network-clown controller to '" + ((Object)extractionPoint).name + "'. Platform='" + ((Object)_platform).name + "', extractionArea='" + (((Object)(object)extractionPoint.extractionArea != (Object)null) ? ((Object)extractionPoint.extractionArea).name : "<none>") + "', ramp='" + (((Object)(object)extractionPoint.ramp != (Object)null) ? ((Object)extractionPoint.ramp).name : "<none>") + "'."); } internal static ExtractionClownController? FindOwner(ClownTrap clown) { int clownLookupId = GetClownLookupId(clown); if (clownLookupId == 0) { return null; } if (!ProxyOwners.TryGetValue(clownLookupId, out ExtractionClownController value)) { return null; } if ((Object)(object)value == (Object)null) { ProxyOwners.Remove(clownLookupId); return null; } if (!value.OwnsClown(clown)) { return null; } return value; } internal bool OwnsClown(ClownTrap clown) { if (_initialized && (Object)(object)_clownTrap != (Object)null && _clownTrap == clown && _clownViewId != 0) { return GetClownLookupId(clown) == _clownViewId; } return false; } internal bool ShouldSuppressExplosion(ClownTrap clown) { return OwnsClown(clown); } internal static bool ShouldSuppressDetachedCleanup(ClownTrap clown) { int clownLookupId = GetClownLookupId(clown); if (!DetachedCleanupClownIds.Contains(clownLookupId)) { return false; } foreach (DetachedCleanupEntry detachedCleanup in DetachedCleanups) { if (detachedCleanup.LookupId == clownLookupId && (Object)(object)detachedCleanup.Root != (Object)null && (Object)(object)detachedCleanup.Clown != (Object)null && detachedCleanup.Clown == clown) { return true; } } return false; } internal static void RetryDetachedCleanup() { if (DetachedCleanups.Count == 0) { DetachedCleanupRunnerFailureLogged = false; return; } try { float realtimeSinceStartup = Time.realtimeSinceStartup; for (int num = DetachedCleanups.Count - 1; num >= 0; num--) { DetachedCleanupEntry detachedCleanupEntry = DetachedCleanups[num]; if ((Object)(object)detachedCleanupEntry.Root == (Object)null) { RemoveDetachedCleanupAt(num); } else if (!(realtimeSinceStartup < detachedCleanupEntry.NextAttemptAt)) { try { DestroyNetworkOrLocalObject(detachedCleanupEntry.Root, detachedCleanupEntry.Room, detachedCleanupEntry.RootView, detachedCleanupEntry.RootViewId); detachedCleanupEntry.NextAttemptAt = realtimeSinceStartup + 1f; } catch (Exception ex) { detachedCleanupEntry.NextAttemptAt = realtimeSinceStartup + 1f; if (!detachedCleanupEntry.FailureLogged) { detachedCleanupEntry.FailureLogged = true; Plugin.Log.LogError((object)("Detached cleanup for extraction clown " + $"ViewID={detachedCleanupEntry.LookupId} failed with " + ex.GetType().Name + ": " + ex.Message + ". Vanilla extraction is already available; cleanup will retry.")); } } } } DetachedCleanupRunnerFailureLogged = false; } catch (Exception ex2) { if (!DetachedCleanupRunnerFailureLogged) { DetachedCleanupRunnerFailureLogged = true; Plugin.Log.LogError((object)("Detached extraction-clown cleanup runner failed with " + ex2.GetType().Name + ": " + ex2.Message + ". Vanilla extraction remains available.")); Plugin.LogDebug(ex2.ToString()); } } } internal void OnNosePressed(ClownTrap clown, int playerActorNumber) { if (Plugin.CriticalPatchesReady && _initialized && _gateArmed && !_proxyConsumed && !_submissionSent && SemiFunc.IsMasterClientOrSingleplayer() && IsCurrentActivePoint() && OwnsClown(clown)) { _proxyConsumed = true; if (IsQuotaReached()) { _pendingSuccess = true; Plugin.LogDebug($"Quota confirmation received from clown ViewID={_clownViewId}, " + $"playerActor={playerActorNumber}, haul={_extractionPoint.haulCurrent}/{_extractionPoint.haulGoal}. " + "Vanilla Success will be requested on the next host frame."); } else if (TryScheduleDeniedReplacement(playerActorNumber)) { Plugin.LogDebug($"Pre-quota clown press accepted from playerActor={playerActorNumber}, " + $"haul={_extractionPoint.haulCurrent}/{_extractionPoint.haulGoal}. " + "The consumed clown stays visible and will be refreshed after " + $"{0.35f:0.##} seconds."); } } } internal bool AllowVanillaStateSet(State requestedState) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 if (!Plugin.CriticalPatchesReady) { return true; } if (!_initialized || (int)requestedState != 3 || !SemiFunc.IsMasterClientOrSingleplayer()) { return true; } if (_successPermitAvailable) { _successPermitAvailable = false; if (IsQuotaReached()) { _successPermitAccepted = true; _blockedSuccessLogged = false; return true; } return false; } if (_submissionSent) { return !IsCurrentActivePoint(); } if (!_gateArmed || !IsCurrentActivePoint()) { return true; } ApplySubmissionGate(); if (!_blockedSuccessLogged) { _blockedSuccessLogged = true; Plugin.LogDebug("Blocked vanilla Success at '" + ((Object)_extractionPoint).name + "' until the network clown nose is pressed with the quota filled."); } return false; } internal void BeforeVanillaUpdate() { TickExtractionSession(); } internal void AfterVanillaUpdate() { TickExtractionSession(); } internal void BeforeVanillaStateActive() { TickExtractionSession(); } internal void AfterVanillaStateSet() { if (_initialized) { if (!_successInvocationInProgress) { ObserveActivationState(); } RetryPendingCleanup(); } } internal void FailOpenFromRuntimeFailure(string callback, Exception exception) { if (!_initialized) { return; } try { FailOpenForActivation(callback + " failed with " + exception.GetType().Name + ": " + exception.Message, logAsError: false, logFailure: false); } catch (Exception ex) { Plugin.Log.LogError((object)("Emergency fail-open after " + callback + " also threw " + ex.GetType().Name + ": " + ex.Message + ". The Harmony callback will still allow vanilla game logic to continue.")); } } internal void FailOpenFromRuntimeCondition(string reason) { if (_initialized) { FailOpenForActivation(reason); } } private void TickExtractionSession() { if (!_initialized) { return; } bool flag = RefreshAuthorityState(); bool flag2 = ObserveActivationState(); RetryPendingCleanup(); if (!flag || !flag2) { return; } if (_sessionFailedOpen) { ReleaseVanillaSubmission(); } else if (!Plugin.CriticalPatchesReady) { if (_gateArmed || (Object)(object)_clownRoot != (Object)null) { FailOpenForActivation("critical Harmony patches are no longer available"); } } else if (_submissionSent) { if (!HasPendingVanillaSuccess()) { FailOpenForActivation("the accepted vanilla Success request stopped pending while the extraction point remained Active"); } else { ReleaseVanillaSubmission(); } } else { if (_cleanupPending || Time.realtimeSinceStartup < _authorityReadyAt) { return; } EnsureSessionStarted(); if (_gateArmed) { string failure; if (IsWaitingForReplacementProxy()) { ApplySubmissionGate(); } else if (!TryValidateProxy(out failure)) { FailOpenForActivation(failure); } else { ApplySubmissionGate(); } } } } private void LateUpdate() { try { RunLateUpdate(); } catch (Exception exception) { HandleControllerFailure("LateUpdate", exception); } } private void RunLateUpdate() { if (!_initialized) { return; } bool flag = RefreshAuthorityState(); bool flag2 = ObserveActivationState(); RetryPendingCleanup(); if (!flag || !flag2) { return; } if (_sessionFailedOpen) { ReleaseVanillaSubmission(); return; } if (!Plugin.CriticalPatchesReady) { if (_gateArmed || (Object)(object)_clownRoot != (Object)null) { FailOpenForActivation("critical Harmony patches are no longer available"); } return; } if (_gateArmed && Time.realtimeSinceStartup >= _nextPatchRevalidationAt) { _nextPatchRevalidationAt = Time.realtimeSinceStartup + 1f; if (!Plugin.RevalidateCriticalPatches()) { FailOpenForActivation("critical Harmony patch revalidation failed at runtime"); return; } } if (_cleanupPending) { return; } if (_pendingSuccess) { ProcessPendingSuccess(); } else if (_replacementRequested) { ReplaceConsumedClown(); } if (_gateArmed && !_sessionFailedOpen && IsCurrentActivePoint() && !IsWaitingForReplacementProxy()) { string failure2; if (!TryValidateProxy(out string failure)) { FailOpenForActivation(failure); } else if (!TryMaintainClownLock(forceNetworkCorrection: false, out failure2)) { FailOpenForActivation(failure2); } } } private void FixedUpdate() { try { if (_initialized && _gateArmed && !_sessionFailedOpen && IsAuthoritative() && !IsWaitingForReplacementProxy() && IsCurrentActivePoint()) { string failure2; if (!TryValidateProxy(out string failure)) { FailOpenForActivation(failure); } else if (!TryMaintainClownLock(forceNetworkCorrection: false, out failure2)) { FailOpenForActivation(failure2); } } } catch (Exception exception) { HandleControllerFailure("FixedUpdate", exception); } } private void OnDisable() { try { if (_initialized) { if (IsCurrentActivePoint()) { FailOpenForActivation("the extraction controller was disabled", logAsError: false, logFailure: false); return; } _wasCurrentActive = false; _sessionFailedOpen = false; _controllerFailureLogged = false; EndSession("the extraction controller was disabled"); } } catch (Exception exception) { HandleControllerFailure("OnDisable", exception); } } private void OnDestroy() { try { if (_initialized) { EndSession("the extraction controller was destroyed"); } } catch (Exception exception) { HandleControllerFailure("OnDestroy", exception); } finally { try { TransferCleanupToDetachedRunner(); } finally { _initialized = false; } } } private void EnsureSessionStarted() { if (!Plugin.CriticalPatchesReady || _gateArmed || _submissionSent || _sessionFailedOpen || _cleanupPending || Time.realtimeSinceStartup < _authorityReadyAt || Time.realtimeSinceStartup < _nextSpawnAttemptAt || !Plugin.RevalidateCriticalPatches()) { return; } if (TrySpawnClown()) { _gateArmed = true; _quotaPreviouslyReached = IsQuotaReached(); _spawnFailureLogged = false; ApplySubmissionGate(); Plugin.Log.LogInfo((object)("Extraction confirmation gate armed at '" + ((Object)_extractionPoint).name + "'. Automatic submission is held until the network clown nose is pressed.")); } else if (_nonRetryableSpawnFailure != null) { FailOpenForActivation(_nonRetryableSpawnFailure); } else { _nextSpawnAttemptAt = Time.realtimeSinceStartup + 1f; if (!_spawnAttemptDeferred && !_spawnFailureLogged) { _spawnFailureLogged = true; Plugin.Log.LogError((object)("Could not create the network clown at '" + ((Object)_extractionPoint).name + "'. Vanilla extraction remains available while the mod retries.")); } } } private bool RefreshAuthorityState() { bool flag = IsAuthoritative(); if (flag == _wasAuthoritative) { return flag; } _wasAuthoritative = flag; if (flag) { _authorityReadyAt = Time.realtimeSinceStartup + 1f; _nextSpawnAttemptAt = Mathf.Max(_nextSpawnAttemptAt, _authorityReadyAt); Plugin.LogDebug("Host authority acquired for '" + ((Object)_extractionPoint).name + "'. Waiting briefly for the previous actor-owned proxy to leave the room cache."); return true; } _authorityReadyAt = float.PositiveInfinity; if (_gateArmed || (Object)(object)_clownRoot != (Object)null || _submissionSent) { FailOpenForActivation("the local player lost host authority", logAsError: false, logFailure: false); } return false; } private bool ObserveActivationState() { bool flag = IsCurrentActivePoint(); if (flag && !_wasCurrentActive) { _wasCurrentActive = true; BeginActivation(); } else if (!flag && _wasCurrentActive) { _wasCurrentActive = false; EndSession(_submissionSent ? "the extraction point left Active after submission" : "the extraction point left Active before submission"); _sessionFailedOpen = false; _spawnFailureLogged = false; _controllerFailureLogged = false; } return flag; } private void BeginActivation() { _sessionFailedOpen = false; _gateArmed = false; _replacementRequested = false; _pendingSuccess = false; _successPermitAvailable = false; _successPermitAccepted = false; _successInvocationInProgress = false; _submissionSent = false; _replacementReadyAt = 0f; _blockedSuccessLogged = false; _quotaPreviouslyReached = false; _spawnFailureLogged = false; _spawnAttemptDeferred = false; _prefabInspectionWarningLogged = false; _controllerFailureLogged = false; _staleProxyWarningLogged = false; _lastDetailedSpawnFailure = null; _nonRetryableSpawnFailure = null; _placementFailureStartedAt = -1f; _nextPatchRevalidationAt = 0f; Plugin.LogDebug("Started extraction confirmation lifecycle for '" + ((Object)_extractionPoint).name + "'."); } private void FailOpenForActivation(string reason, bool logAsError = true, bool logFailure = true) { bool flag = !_sessionFailedOpen; bool flag2 = _gateArmed || (Object)(object)_clownRoot != (Object)null || _pendingSuccess || _replacementRequested || _submissionSent || _nonRetryableSpawnFailure != null; _wasCurrentActive = true; _sessionFailedOpen = true; _gateArmed = false; _replacementRequested = false; _pendingSuccess = false; _successPermitAvailable = false; _successPermitAccepted = false; _successInvocationInProgress = false; _submissionSent = false; _replacementReadyAt = 0f; _blockedSuccessLogged = false; ReleaseVanillaSubmission(); if ((Object)(object)_clownRoot != (Object)null && !_cleanupPending) { DestroyCurrentClown("the controller failed open: " + reason); } if (flag && flag2 && logFailure) { string text = "Extraction confirmation at '" + ((Object)_extractionPoint).name + "' failed open: " + reason + ". Vanilla extraction is restored for this activation."; if (logAsError) { Plugin.Log.LogError((object)text); } else { Plugin.Log.LogWarning((object)text); } } } private void ReleaseVanillaSubmission() { if ((Object)(object)_extractionPoint != (Object)null) { _extractionPoint.successDelay = 0f; } } private void HandleControllerFailure(string callback, Exception exception) { bool flag = !_controllerFailureLogged; _controllerFailureLogged = true; try { FailOpenForActivation(callback + " threw " + exception.GetType().Name + ": " + exception.Message, logAsError: false, logFailure: false); } catch (Exception ex) { if (flag) { Plugin.Log.LogError((object)("Emergency fail-open from " + callback + " also threw " + ex.GetType().Name + ": " + ex.Message + ".")); } } if (flag) { Plugin.Log.LogError((object)(callback + " failed with " + exception.GetType().Name + ": " + exception.Message + ". Vanilla extraction was allowed to continue.")); Plugin.LogDebug(exception.ToString()); } } private bool TryValidateProxy(out string failure) { failure = string.Empty; if ((Object)(object)_clownRoot == (Object)null || !_clownRoot.activeInHierarchy || (Object)(object)_clownTrap == (Object)null || (Object)(object)_physGrabObject == (Object)null) { failure = "the active extraction clown disappeared or became inactive"; return false; } if ((_clownTrap.CountDownActive || _clownTrap.NoseSqueezeActive) && !_proxyConsumed) { failure = "the vanilla clown nose was consumed without a completed mod callback"; return false; } if (_proxyConsumed && !_pendingSuccess && !_replacementRequested && !_submissionSent) { failure = "the extraction clown was consumed without a pending replacement or submission"; return false; } if (!OwnsClown(_clownTrap)) { failure = "the active extraction clown lost its ownership registration"; return false; } if (PhotonNetwork.InRoom) { PhotonView clownPhotonView = GetClownPhotonView(_clownTrap); if ((Object)(object)clownPhotonView == (Object)null || clownPhotonView.ViewID == 0 || !clownPhotonView.IsMine) { failure = "the active extraction clown lost its valid network ownership"; return false; } } return true; } private void RetryPendingCleanup() { if (_cleanupPending && !((Object)(object)_orphanedSpawn != (Object)null)) { _orphanedSpawn = null; if (!((Object)(object)_clownRoot != (Object)null)) { ClearProxyReferences(); _cleanupPending = false; _destroyFailureLogged = false; } } } private void ApplySubmissionGate() { if (!_gateArmed || _submissionSent) { return; } bool flag = IsQuotaReached(); _extractionPoint.successDelay = 1.5f; if (flag != _quotaPreviouslyReached) { _quotaPreviouslyReached = flag; if (flag) { Plugin.LogDebug("Quota reached at '" + ((Object)_extractionPoint).name + "'. Automatic submission remains held until the clown nose is pressed."); } else { Plugin.LogDebug("Quota is no longer reached at '" + ((Object)_extractionPoint).name + "'."); } } } private void ProcessPendingSuccess() { _pendingSuccess = false; if (!_gateArmed || _submissionSent || !IsCurrentActivePoint()) { return; } if (!IsQuotaReached()) { _proxyConsumed = true; TryScheduleDeniedReplacement(-1); return; } try { _successInvocationInProgress = true; _successPermitAvailable = true; _successPermitAccepted = false; _submissionSent = true; _extractionPoint.successDelay = 0f; _extractionPoint.StateSet((State)3); if (IsCurrentActivePoint() && (!_successPermitAccepted || !HasPendingVanillaSuccess())) { FailOpenForActivation("the one-shot vanilla StateSet(Success) request was not registered"); return; } Plugin.LogDebug("Clown confirmation submitted '" + ((Object)_extractionPoint).name + "' through vanilla " + $"StateSet(Success), haul={_extractionPoint.haulCurrent}/{_extractionPoint.haulGoal}."); } catch (Exception ex) { if (IsCurrentActivePoint()) { FailOpenForActivation("vanilla StateSet(Success) threw " + ex.GetType().Name + ": " + ex.Message); } else { EndSession("vanilla StateSet(Success) changed the extraction state before throwing"); } return; } finally { _successInvocationInProgress = false; _successPermitAvailable = false; _successPermitAccepted = false; } _gateArmed = false; DestroyCurrentClown("vanilla extraction Success started"); } private void ReplaceConsumedClown() { //IL_003a: 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_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_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) if (!_gateArmed || _submissionSent || !IsCurrentActivePoint()) { _replacementRequested = false; _replacementReadyAt = 0f; } else { if (Time.realtimeSinceStartup < _replacementReadyAt) { return; } Vector3 anchorPosition = _anchorPosition; Quaternion anchorRotation = _anchorRotation; if (((Object)(object)_clownRoot != (Object)null || (Object)(object)_clownTrap != (Object)null || _clownViewId != 0) && !DestroyCurrentClown("the denied nose press cooldown elapsed")) { FailOpenForActivation("the used extraction clown could not be removed before replacement"); return; } _replacementRequested = false; _replacementReadyAt = 0f; if (!TrySpawnClown(checkStaleProxies: false, anchorPosition, anchorRotation)) { FailOpenForActivation("a fresh extraction clown could not be created after the nose press"); } } } private bool TryPrepareNetworkSpawn(bool checkStaleProxies, out string failure) { failure = string.Empty; if (!PhotonNetwork.InRoom) { return true; } Room currentRoom = PhotonNetwork.CurrentRoom; if (currentRoom == null) { failure = "Photon reports InRoom without an available CurrentRoom"; return false; } if (!currentRoom.AutoCleanUp || currentRoom.PlayerTtl != 0) { failure = "The Photon room cannot guarantee host-only proxy cleanup: " + $"AutoCleanUp={currentRoom.AutoCleanUp}, PlayerTtl={currentRoom.PlayerTtl}. " + "Vanilla extraction will remain active"; return false; } if (!checkStaleProxies) { return true; } bool flag = false; PhotonView[] array = Object.FindObjectsOfType<PhotonView>(true); foreach (PhotonView val in array) { if (!IsMarkedExtractionProxy(val)) { continue; } if (!val.IsMine) { _spawnAttemptDeferred = true; failure = $"a previous extraction proxy ViewID={val.ViewID} is still " + $"controlled by actor {val.ControllerActorNr}"; if (!_staleProxyWarningLogged) { _staleProxyWarningLogged = true; Plugin.Log.LogWarning((object)("Waiting for " + failure + ". Vanilla extraction remains available and no duplicate proxy will be spawned.")); } return false; } try { int viewID = val.ViewID; GameObject gameObject = ((Component)val).gameObject; ClownTrap componentInChildren = gameObject.GetComponentInChildren<ClownTrap>(true); int lookupId = (((Object)(object)componentInChildren != (Object)null) ? GetClownLookupId(componentInChildren) : viewID); DetachedCleanupEntry detachedCleanupEntry = QueueDetachedCleanup(gameObject, componentInChildren, lookupId, currentRoom, val, viewID); DestroyNetworkOrLocalObject(gameObject, detachedCleanupEntry.Room, detachedCleanupEntry.RootView, detachedCleanupEntry.RootViewId); flag = true; Plugin.LogDebug($"Removed stale marked extraction proxy ViewID={viewID} " + "before creating a new confirmation session."); } catch (Exception ex) { failure = $"Removing stale extraction proxy ViewID={val.ViewID} failed " + "with " + ex.GetType().Name + ": " + ex.Message; return false; } } if (flag) { _spawnAttemptDeferred = true; Plugin.LogDebug("Deferred extraction clown spawn for one retry after stale proxy cleanup."); return false; } _staleProxyWarningLogged = false; return true; } private static bool IsMarkedExtractionProxy(PhotonView view) { if ((Object)(object)view == (Object)null || view.ViewID == 0 || view.InstantiationId != view.ViewID) { return false; } object[] instantiationData = view.InstantiationData; if (instantiationData != null && instantiationData.Length >= 2 && instantiationData[0] is string a) { return string.Equals(a, "DJDarkLucky.AddExtractionButton", StringComparison.Ordinal); } return false; } private bool TrySpawnClown(bool checkStaleProxies = true, Vector3? preservedAnchorPosition = null, Quaternion? preservedAnchorRotation = null) { //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0098: 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_00a1: 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) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_0370: Unknown result type (might be due to invalid IL or missing references) //IL_0372: Unknown result type (might be due to invalid IL or missing references) //IL_0430: Unknown result type (might be due to invalid IL or missing references) //IL_0432: Unknown result type (might be due to invalid IL or missing references) //IL_0438: Unknown result type (might be due to invalid IL or missing references) //IL_043a: Unknown result type (might be due to invalid IL or missing references) //IL_0531: Unknown result type (might be due to invalid IL or missing references) //IL_054d: Unknown result type (might be due to invalid IL or missing references) _spawnAttemptDeferred = false; _nonRetryableSpawnFailure = null; if (_cleanupPending) { return false; } if ((Object)(object)_clownRoot != (Object)null) { return true; } if (!TryPrepareNetworkSpawn(checkStaleProxies, out string failure)) { if (!_spawnAttemptDeferred) { LogDetailedSpawnFailure(failure); } return false; } if (!TryResolveClownPrefab(out string resourcePath, out GameObject prefab)) { return false; } bool flag = preservedAnchorPosition.HasValue && preservedAnchorRotation.HasValue; if (preservedAnchorPosition.HasValue != preservedAnchorRotation.HasValue) { LogDetailedSpawnFailure("A preserved extraction-clown pose must include both position and rotation."); return false; } PlacementBasis basis = default(PlacementBasis); Bounds offsets = default(Bounds); Vector3 position; Quaternion desiredRotation; string text; if (flag) { position = preservedAnchorPosition.GetValueOrDefault(); desiredRotation = preservedAnchorRotation.GetValueOrDefault(); text = "preserved previous extraction proxy pose"; } else { if (!TryPreparePlacementBasis(out basis, out desiredRotation, out text)) { LogDetailedSpawnFailure("Could not calculate a clown placement at '" + ((Object)_extractionPoint).name + "': " + text + "."); return false; } if (!TryMeasureProxyOffsets(prefab, desiredRotation, basis, out offsets, out string source)) { LogDetailedSpawnFailure("Could not measure the vanilla clown before network spawn: " + source + "."); return false; } if (!TryCalculateFinalPose(basis, offsets, out position, out string source2)) { ReportTransientPlacementFailure("No safe floor placement was found at '" + ((Object)_extractionPoint).name + "': " + source2 + "."); return false; } text = text + ", geometry=" + source + ", final=" + source2; } GameObject val = null; try { if (PhotonNetwork.InRoom) { if (!PhotonNetwork.IsMasterClient) { return false; } val = PhotonNetwork.Instantiate(resourcePath, position, desiredRotation, (byte)0, new object[2] { "DJDarkLucky.AddExtractionButton", 1 }); } else { val = Object.Instantiate<GameObject>(prefab, position, desiredRotation); } if (!TryValidateSpawnPose(val, position, desiredRotation, out string diagnostics)) { DestroyUntrackedSpawn(val); LogNonRetryableSpawnFailure("The vanilla clown did not instantiate at its calculated final pose: " + diagnostics + "."); return false; } if (!TryMakeClownEconomicallyNeutral(val, out string diagnostics2)) { DestroyUntrackedSpawn(val); LogNonRetryableSpawnFailure("The spawned extraction clown could not be made economically neutral: " + diagnostics2 + "."); return false; } ClownTrap componentInChildren = val.GetComponentInChildren<ClownTrap>(true); PhysGrabObject val2 = (((Object)(object)componentInChildren != (Object)null && (Object)(object)componentInChildren.physgrabobject != (Object)null) ? componentInChildren.physgrabobject : (((Object)(object)componentInChildren != (Object)null && (Object)(object)((Trap)componentInChildren).physGrabObject != (Object)null) ? ((Trap)componentInChildren).physGrabObject : val.GetComponentInChildren<PhysGrabObject>(true))); PhotonView val3 = (PhotonView)(((Object)(object)componentInChildren != (Object)null) ? ((object)GetClownPhotonView(componentInChildren)) : ((object)val.GetComponentInChildren<PhotonView>(true))); Room val4 = (PhotonNetwork.InRoom ? PhotonNetwork.CurrentRoom : null); PhotonView val5 = ((val4 != null) ? FindRootNetworkView(val) : null); if ((Object)(object)componentInChildren == (Object)null || (Object)(object)val2 == (Object)null || (val4 != null && ((Object)(object)val3 == (Object)null || val3.ViewID == 0 || (Object)(object)val5 == (Object)null || val5.ViewID == 0))) { DestroyUntrackedSpawn(val); LogNonRetryableSpawnFailure("Resolved prefab '" + resourcePath + "' did not create a usable ClownTrap + PhysGrabObject + root PhotonView instance."); return false; } string text2; if (flag) { text2 = "spawnPose=" + diagnostics + ", geometry='preserved pose reuse'"; } else { if (!TryValidateSpawnedGeometry(basis, val, offsets, position, out text2)) { DestroyUntrackedSpawn(val); LogNonRetryableSpawnFailure("The spawned extraction clown did not match its preflight geometry: " + text2 + "."); return false; } text2 = "spawnPose=" + diagnostics + ", " + text2; } _clownRoot = val; _clownTrap = componentInChildren; _physGrabObject = val2; _rigidbody = (((Object)(object)val2.rb != (Object)null) ? val2.rb : val.GetComponentInChildren<Rigidbody>(true)); _clownViewId = GetClownLookupId(componentInChildren); _clownSpawnRoom = val4; _clownRootPhotonView = val5; _clownRootViewId = (((Object)(object)val5 != (Object)null) ? val5.ViewID : 0); _anchorPosition = position; _anchorRotation = desiredRotation; ProxyOwners[_clownViewId] = this; _proxyConsumed = false; _replacementRequested = false; _nextSpawnAttemptAt = 0f; _replacementReadyAt = 0f; _nextNetworkCorrectionAt = 0f; _cleanupPending = false; _destroyFailureLogged = false; _staleProxyWarningLogged = false; if (!TryMaintainClownLock(forceNetworkCorrection: true, out string failure2)) { DestroyCurrentClown("the initial proxy lock failed"); LogNonRetryableSpawnFailure("The spawned extraction clown could not be locked safely: " + failure2 + "."); return false; } _lastDetailedSpawnFailure = null; _placementFailureStartedAt = -1f; Plugin.LogDebug("Spawned network clown for '" + ((Object)_extractionPoint).name + "': resourcePath='" + resourcePath + "', prefab='" + ((Object)prefab).name + "', " + $"ViewID={_clownViewId}, position={FormatVector(_anchorPosition)}, " + "rotation=" + FormatQuaternion(_anchorRotation) + ", value=" + diagnostics2 + ", placement=" + text + ", verification=" + text2 + ", network=" + GetNetworkLifecycleSnapshot(val) + ", visual=" + GetSpawnVisualSnapshot(val) + "."); return true; } catch (Exception ex) { if ((Object)(object)val != (Object)null) { DestroyUntrackedSpawn(val); LogNonRetryableSpawnFailure("Network clown post-instantiation setup failed with " + ex.GetType().Name + ": " + ex.Message + "."); } else { LogDetailedSpawnFailure("Network clown spawn failed with " + ex.GetType().Name + ": " + ex.Message + "."); } ClearProxyReferences(); return false; } } private static bool TryMakeClownEconomicallyNeutral(GameObject spawned, out string diagnostics) { diagnostics = string.Empty; try { ValuableObject[] componentsInChildren = spawned.GetComponentsInChildren<ValuableObject>(true); if (componentsInChildren.Length != 1) { diagnostics = $"expected exactly one ValuableObject, found {componentsInChildren.Length}"; return false; } ValuableObject val = componentsInChildren[0]; float dollarValueOriginal = val.dollarValueOriginal; float dollarValueCurrent = val.dollarValueCurrent; int dollarValueOverride = val.dollarValueOverride; bool dollarValueSet = val.dollarValueSet; val.dollarValueOverride = 0; val.dollarValueOriginal = 0f; val.dollarValueCurrent = 0f; val.dollarValueSet = true; int num = 0; if (PhotonNetwork.InRoom) { PhotonView val2 = (((Object)(object)val.photonView != (Object)null) ? val.photonView : ((Component)val).GetComponent<PhotonView>()); if ((Object)(object)val2 == (Object)null || val2.ViewID == 0) { diagnostics = "the ValuableObject has no valid PhotonView for value synchronization"; return false; } num = val2.ViewID; val2.RPC("DollarValueSetRPC", (RpcTarget)4, new object[1] { 0f }); } if (!val.dollarValueSet || !Mathf.Approximately(val.dollarValueOriginal, 0f) || !Mathf.Approximately(val.dollarValueCurrent, 0f)) { diagnostics = "the zero-value invariant did not hold after assignment"; return false; } RoundDirector instance = RoundDirector.instance; string arg = (((Object)(object)instance != (Object)null) ? ($"currentHaul={instance.currentHaul}, " + $"currentHaulMax={instance.currentHaulMax}, " + $"haulGoal={instance.haulGoal}, " + $"haulGoalMax={instance.haulGoalMax}") : "<unavailable>"); diagnostics = $"previous=(original={dollarValueOriginal:0.##}, " + $"current={dollarValueCurrent:0.##}, override={dollarValueOverride}, " + $"set={dollarValueSet}), current=(original=0, current=0, set=True), " + $"valueViewID={num}, round=({arg})"; return true; } catch (Exception ex) { diagnostics = ex.GetType().Name + ": " + ex.Message; return false; } } private bool TryResolveClownPrefab(out string resourcePath, out GameObject prefab) { if (!string.IsNullOrEmpty(_resolvedResourcePath) && (Object)(object)_resolvedPrefab != (Object)null && IsClownPrefab(_resolvedPrefab)) { resourcePath = _resolvedResourcePath; prefab = _resolvedPrefab; return true; } ValuableDirector instance = ValuableDirector.instance; if ((Object)(object)instance != (Object)null && instance.mediumValuables != null) { foreach (PrefabRef mediumValuable in instance.mediumValuables) { if (mediumValuable == null) { continue; } try { GameObject prefab2 = ((PrefabRef<GameObject>)(object)mediumValuable).Prefab; if ((Object)(object)prefab2 != (Object)null && IsClownPrefab(prefab2) && !string.IsNullOrEmpty(((PrefabRef<GameObject>)(object)mediumValuable).ResourcePath)) { return CacheResolvedPrefab(((PrefabRef<GameObject>)(object)mediumValuable).ResourcePath, prefab2, out resourcePath, out prefab); } } catch (Exception ex) { if (!_prefabInspectionWarningLogged) { _prefabInspectionWarningLogged = true; Plugin.Log.LogWarning((object)("Inspecting a vanilla medium valuable PrefabRef failed with " + ex.GetType().Name + ": " + ex.Message + ".")); } } } } string[] clownResourcePathCandidates = ClownResourcePathCandidates; foreach (string text in clownResourcePathCandidates) { GameObject val = Resources.Load<GameObject>(text); if ((Object)(object)val != (Object)null && IsClownPrefab(val)) { return CacheResolvedPrefab(text, val, out resourcePath, out prefab); } } GameObject[] array = Resources.LoadAll<GameObject>("valuables/03 medium"); foreach (GameObject val2 in array) { if (!((Object)(object)val2 == (Object)null) && IsClownPrefab(val2)) { string text2 = "valuables/03 medium/" + ((Object)val2).name; GameObject val3 = Resources.Load<GameObject>(text2); if ((Object)(object)val3 != (Object)null && IsClownPrefab(val3)) { return CacheResolvedPrefab(text2, val3, out resourcePath, out prefab); } } } resourcePath = string.Empty; prefab = null; LogDetailedSpawnFailure("The vanilla Valuable Clown prefab could not be found in Resources."); return false; } private bool CacheResolvedPrefab(string path, GameObject candidate, out string resourcePath, out GameObject prefab) { _resolvedResourcePath = path; _resolvedPrefab = candidate; resourcePath = path; prefab = candidate; Plugin.LogDebug("Resolved vanilla clown prefab: path='" + path + "', prefab='" + ((Object)candidate).name + "'."); return true; } private static bool IsClownPrefab(GameObject candidate) { return (Object)(object)candidate.GetComponentInChildren<ClownTrap>(true) != (Object)null; } private bool TryPreparePlacementBasis(out PlacementBasis basis, out Quaternion desiredRotation, out string source) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_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_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: 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_0039: 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_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_0069: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_0083: 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_0093: 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_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: 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_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_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0101: 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_010c: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_010f: 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_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0113: 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) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: 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) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) basis = default(PlacementBasis); desiredRotation = Quaternion.identity; source = string.Empty; Vector3 position = _platform.position; Vector3 val = _platform.up; Vector3 normalized = ((Vector3)(ref val)).normalized; if (!TryGetWorldCenter(_extractionPoint.extractionArea, out var center)) { center = _platform.position + _platform.forward; } Vector3 val2 = (((Object)(object)_extractionPoint.ramp != (Object)null) ? _extractionPoint.ramp.position : (_platform.position - _platform.forward)); Vector3 val3 = Vector3.ProjectOnPlane(center - val2, normalized); if (((Vector3)(ref val3)).sqrMagnitude < 0.0001f) { val3 = Vector3.ProjectOnPlane(_platform.forward, normalized); } if (((Vector3)(ref val3)).sqrMagnitude < 0.0001f) { source = "could not determine the direction from the ramp into the platform"; return false; } ((Vector3)(ref val3)).Normalize(); val = Vector3.Cross(normalized, val3); Vector3 normalized2 = ((Vector3)(ref val)).normalized; Bounds val4 = CreateSyntheticStorageBounds(position, normalized2, normalized, val3, center, val2); float num = Vector3.Dot(val2 - position, normalized); float expectedFloor = ((Mathf.Abs(num) <= 1.25f) ? num : 0f); basis = new PlacementBasis(position, normalized2, normalized, val3, val4, expectedFloor); desiredRotation = Quaternion.LookRotation(-val3, normalized); source = "storageBoundsSource='fixed ramp-relative footprint', storageBounds=" + FormatBounds(val4) + ", platformWorld=" + FormatVector(position) + ", rampWorld=" + FormatVector(val2) + ", areaWorld=" + FormatVector(center); return true; } private static bool TryMeasureProxyOffsets(GameObject root, Quaternion desiredRotation, PlacementBasis basis, out Bounds offsets, out string source) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0061: 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_0123: 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_0131: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: 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_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) offsets = default(Bounds); source = string.Empty; try { Bounds offsets2 = default(Bounds); bool initialized = false; int num = 0; int num2 = 0; Transform transform = root.transform; Collider[] componentsInChildren = root.GetComponentsInChildren<Collider>(true); foreach (Collider val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !val.isTrigger && TryGetColliderLocalBounds(val, out var localBounds)) { EncapsulatePrefabLocalBounds(transform, ((Component)val).transform, localBounds, desiredRotation, basis, ref offsets2, ref initialized); num++; } } Renderer[] componentsInChildren2 = root.GetComponentsInChildren<Renderer>(true); foreach (Renderer val2 in componentsInChildren2) { if (!((Object)(object)val2 == (Object)null) && !(val2 is ParticleSystemRenderer) && !(val2 is TrailRenderer) && !(val2 is LineRenderer)) { Bounds localBounds2 = val2.localBounds; if (IsFiniteBounds(localBounds2)) { EncapsulatePrefabLocalBounds(transform, ((Component)val2).transform, localBounds2, desiredRotation, basis, ref offsets2, ref initialized); num2++; } } } if (!initialized || num == 0) { source = "usable physical bounds were not found " + $"(colliders={num}, renderers={num2})"; return false; } offsets = offsets2; source = "offsets=" + FormatBounds(offsets) + ", " + $"colliders={num}, renderers={num2}"; return true; } catch (Exception ex) { source = ex.GetType().Name + ": " + ex.Message; return false; } } private static bool TryGetColliderLocalBounds(Collider collider, out Bounds localBounds) { //IL_0052: 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_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0087: 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_0175: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: 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_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) BoxCollider val = (BoxCollider)(object)((collider is BoxCollider) ? collider : null); if (val == null) { SphereCollider val2 = (SphereCollider)(object)((collider is SphereCollider) ? collider : null); if (val2 == null) { CapsuleCollider val3 = (CapsuleCollider)(object)((collider is CapsuleCollider) ? collider : null); if (val3 == null) { CharacterController val4 = (CharacterController)(object)((collider is CharacterController) ? collider : null); if (val4 == null) { MeshCollider val5 = (MeshCollider)(object)((collider is MeshCollider) ? collider : null); if (val5 == null || !((Object)(object)val5.sharedMesh != (Object)null)) { localBounds = default(Bounds); return false; } localBounds = val5.sharedMesh.bounds; } else { float num = val4.radius * 2f; localBounds = new Bounds(val4.center, new Vector3(num, Mathf.Max(val4.height, num), num)); } } else { float num2 = val3.radius * 2f; Vector3 val6 = Vector3.one * num2; float num3 = Mathf.Max(val3.height, num2); if (val3.direction == 0) { val6.x = num3; } else if (val3.direction == 1) { val6.y = num3; } else { val6.z = num3; } localBounds = new Bounds(val3.center, val6); } } else { localBounds = new Bounds(val2.center, Vector3.one * (val2.radius * 2f)); } } else { localBounds = new Bounds(val.center, val.size); } if (!TryCompensateColliderBoundsForPhysicsScale(collider, ref localBounds)) { return false; } return IsFiniteBounds(localBounds); } private static bool TryCompensateColliderBoundsForPhysicsScale(Collider collider, ref Bounds localBounds) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: 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_003c: 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_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_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Expected O, but got Unknown //IL_019c: Unknown result type (might be due to invalid IL or missing references) if (!(collider is SphereCollider) && !(collider is CapsuleCollider) && !(collider is CharacterController)) { return true; } Vector3 lossyScale = ((Component)collider).transform.lossyScale; float[] array = new float[3] { Mathf.Abs(lossyScale.x), Mathf.Abs(lossyScale.y), Mathf.Abs(lossyScale.z) }; if (array[0] < 0.0001f || array[1] < 0.0001f || array[2] < 0.0001f) { return false; } Vector3 size = ((Bounds)(ref localBounds)).size; SphereCollider val = (SphereCollider)(object)((collider is SphereCollider) ? collider : null); if (val != null) { float num = val.radius * 2f * Mathf.Max(new float[3] { array[0], array[1], array[2] }); size.x = num / array[0]; size.y = num / array[1]; size.z = num / array[2]; } else { CapsuleCollider val2 = (CapsuleCollider)(object)((collider is CapsuleCollider) ? collider : null); int num2; float radius; float height; if (val2 != null) { num2 = Mathf.Clamp(val2.direction, 0, 2); radius = val2.radius; height = val2.height; } else { CharacterController val3 = (CharacterController)collider; num2 = 1; radius = val3.radius; height = val3.height; } int num3 = ((num2 == 0) ? 1 : 0); int num4 = ((num2 == 2) ? 1 : 2); float num5 = Mathf.Max(array[num3], array[num4]); float num6 = radius * 2f * num5; float num7 = Mathf.Max(height * array[num2], num6); ((Vector3)(ref size))[num3] = num6 / array[num3]; ((Vector3)(ref size))[num4] = num6 / array[num4]; ((Vector3)(ref size))[num2] = num7 / array[num2]; } ((Bounds)(ref localBounds)).size = size; return true; } private static void EncapsulatePrefabLocalBounds(Transform prefabRoot, Transform componentTransform, Bounds localBounds, Quaternion desiredRotation, PlacementBasis basis, ref Bounds offsets, ref bool initialized) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_002a: 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_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_004a: 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) Vector3 rootScale = prefabRoot.localScale; Bounds collectedOffsets = offsets; bool hasOffsets = initialized; ForEachBoundsCorner(localBounds, delegate(Vector3 localPoint) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_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_0019: 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) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: 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_0039: 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_004a: 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_005b: 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) Vector3 val = prefabRoot.InverseTransformPoint(componentTransform.TransformPoint(localPoint)); Vector3 val2 = desiredRotation * Vector3.Scale(val, rootScale); Vector3 point = default(Vector3); ((Vector3)(ref point))..ctor(Vector3.Dot(val2, basis.Right), Vector3.Dot(val2, basis.Up), Vector3.Dot(val2, basis.Into)); EncapsulatePoint(ref collectedOffsets, ref hasOffsets, point); }); offsets = collectedOffsets; initialized = hasOffsets; } private bool TryCalculateFinalPose(PlacementBasis basis, Bounds proxyOffsets, out Vector3 position, out string source) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: 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_0038: 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_004b: 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_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: 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_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0098: 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_00a1: 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_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: 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_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_02c9: Unknown result type (might be due to invalid IL or missing references) //IL_02d6: Unknown result type (might be due to invalid IL or missing references) //IL_02db: Unknown result type (might be due to invalid IL or missing references) //IL_02df: Unknown result type (might be due to invalid IL or missing references) //IL_04cc: Unknown result type (might be due to invalid IL or missing references) //IL_0397: Unknown result type (might be due to invalid IL or missing references) //IL_0331: Unknown result type (might be due to invalid IL or missing references) //IL_033e: Unknown result type (might be due to invalid IL or missing references) //IL_0343: Unknown result type (might be due to invalid IL or missing references) //IL_0347: Unknown result type (might be due to invalid IL or missing references) //IL_02ef: Unknown result type (might be due to invalid IL or missing references) //IL_02fc: Unknown result type (might be due to invalid IL or missing references) //IL_0301: Unknown result type (might be due to invalid IL or missing references) //IL_0305: Unknown result type (might be due to invalid IL or missing references) //IL_03c9: Unknown result type (might be due to invalid IL or missing references) //IL_03d8: Unknown result type (might be due to invalid IL or missing references) //IL_03df: Unknown result type (might be due to invalid IL or missing references) //IL_03e6: Unknown result type (might be due to invalid IL or missing references) //IL_03eb: Unknown result type (might be due to invalid IL or missing references) //IL_03f2: Unknown result type (might be due to invalid IL or missing references) //IL_03f9: Unknown result type (might be due to invalid IL or missing references) //IL_03fe: Unknown result type (might be due to invalid IL or missing references) //IL_0405: Unknown result type (might be due to invalid IL or missing references) //IL_040c: Unknown result type (might be due to invalid IL or missing references) //IL_0411: Unknown result type (might be due to invalid IL or missing references) //IL_0416: Unknown result type (might be due to invalid IL or missing references) //IL_0419: Unknown result type (might be due to invalid IL or missing references) //IL_041b: Unknown result type (might be due to invalid IL or missing references) //IL_0357: Unknown result type (might be due to invalid IL or missing references) //IL_0364: Unknown result type (might be due to invalid IL or missing references) //IL_0369: Unknown result type (might be due to invalid IL or missing references) //IL_036d: Unknown result type (might be due to invalid IL or missing references) //IL_043e: Unknown result type (might be due to invalid IL or missing references) //IL_0440: Unknown result type (might be due to invalid IL or missing references) //IL_0464: Unknown result type (might be due to invalid IL or missing references) position = Vector3.zero; source = string.Empty; float expectedFloor = basis.ExpectedFloor; Bounds storageBounds = basis.StorageBounds; float item = ((Bounds)(ref storageBounds)).min.x - 0.18f - ((Bounds)(ref proxyOffsets)).max.x; storageBounds = basis.StorageBounds; float item2 = ((Bounds)(ref storageBounds)).max.x + 0.18f - ((Bounds)(ref proxyOffsets)).min.x; storageBounds = basis.StorageBounds; float num = ((Bounds)(ref storageBounds)).min.z - 0.18f - ((Bounds)(ref proxyOffsets)).max.z; storageBounds = basis.StorageBounds; float x = ((Bounds)(ref storageBounds)).min.x; storageBounds = basis.StorageBounds; float item3 = Mathf.Lerp(x, ((Bounds)(ref storageBounds)).max.x, 0.2f) - ((Bounds)(ref proxyOffsets)).center.x; storageBounds = basis.StorageBounds; float x2 = ((Bounds)(ref storageBounds)).min.x; storageBounds = basis.StorageBounds; float item4 = Mathf.Lerp(x2, ((Bounds)(ref storageBounds)).max.x, 0.8f) - ((Bounds)(ref proxyOffsets)).center.x; List<(string, float, float, bool, bool)> list = new List<(string, float, float, bool, bool)>(); float[] array = new float[3] { 0f, 0.2f, 0.4f }; float[] array2 = array; foreach (float num2 in array2) { string text = ((num2 > 0f) ? $" +{num2:0.##}m" : string.Empty); float item5 = num - num2; list.Add(("entrance left" + text, item3, item5, true, false)); list.Add(("entrance right" + text, item4, item5, true, false)); } float[] array3 = new float[2] { 0.25f, 0.65f }; float[] array4 = array3; foreach (float num3 in array4) { storageBounds = basis.StorageBounds; float z = ((Bounds)(ref storageBounds)).min.z; storageBounds = basis.StorageBounds; float item6 = Mathf.Lerp(z, ((Bounds)(ref storageBounds)).max.z, num3) - ((Bounds)(ref proxyOffsets)).center.z; list.Add(($"left side {num3:0.##}", item, item6, false, true)); list.Add(($"right side {num3:0.##}", item2, item6, false, true)); } List<string> list2 = new List<string>(); foreach (var (text2, num4, num5, flag, flag2) in list) { if (flag) { float num6 = num4 + ((Bounds)(ref proxyOffsets)).min.x; storageBounds = basis.StorageBounds; if (!(num6 < ((Bounds)(ref storageBounds)).min.x)) { float num7 = num4 + ((Bounds)(ref proxyOffsets)).max.x; storageBounds = basis.StorageBounds; if (!(num7 > ((Bounds)(ref storageBounds)).max.x)) { goto IL_0329; } } list2.Add(text2 + ": footprint exceeds platform width"); continue; } goto IL_0329; IL_0391: if (!TryFindSupportedFloor(basis, num4, num5, proxyOffsets, expectedFloor, null, out float floor, out string floorSource)) { list2.Add(text2 + ": " + floorSource); continue; } float num8 = floor + 0.015f - ((Bounds)(ref proxyOffsets)).min.y; Vector3 val = basis.Origin + basis.Right * num4 + basis.Up * num8 + basis.Into * num5; if (!TryValidatePlacementClearance(basis, val, proxyOffsets, null, out string source2)) { list2.Add(text2 + ": " + source2); continue; } position = val; source = "candidate='" + text2 + "', proxyOffsets=" + FormatBounds(proxyOffsets) + ", " + $"floor='{floorSource}', floorOffset={floor - expectedFloor:0.###}, " + "clearance='clear'"; return true; IL_0329: if (flag2) { float num9 = num5 + ((Bounds)(ref proxyOffsets)).min.z; storageBounds = basis.StorageBounds; if (!(num9 < ((Bounds)(ref storageBounds)).min.z)) { float num10 = num5 + ((Bounds)(ref proxyOffsets)).max.z; storageBounds = basis.StorageBounds; if (!(num10 > ((Bounds)(ref storageBounds)).max.z)) { goto IL_0391; } } list2.Add(text2 + ": footprint exceeds platform depth"); continue; } goto IL_0391; } source = "no fully supported collision-free candidate was found; proxyOffsets=" + FormatBounds(proxyOffsets) + ", rejections=[" + string.Join("; ", list2) + "]"; return false; } private bool TryFindSupportedFloor(PlacementBasis basis, float targetRight, float targetInto, Bounds proxyOffsets, float expectedFloor, Transform? excludedRoot, out float floor, out string floorSource) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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_0067: 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_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) floor = expectedFloor; floorSource = string.Empty; float num = Mathf.Min(0.04f, ((Bounds)(ref proxyOffsets)).size.x * 0.25f); float num2 = Mathf.Min(0.04f, ((Bounds)(ref proxyOffsets)).size.z * 0.25f); float item = ((Bounds)(ref proxyOffsets)).min.x + num; float item2 = ((Bounds)(ref proxyOffsets)).max.x - num; float item3 = ((Bounds)(ref proxyOffsets)).min.z + num2; float item4 = ((Bounds)(ref proxyOffsets)).max.z - num2; (string, float, float)[] array = new(string, float, float)[5] { ("center", ((Bounds)(ref proxyOffsets)).center.x, ((Bounds)(ref proxyOffsets)).center.z), ("near-left", item, item3), ("near-right", item2, item3), ("far-left", item, item4), ("far-right", item2, item4) }; float num3 = float.MaxValue; float num4 = float.MinValue; HashSet<string> hashSet = new HashSet<string>(); List<string> list = new List<string>(); (string, float, float)[] array2 = array; for (int i = 0; i < array2.Length; i++) { var (text, num5, num6) = array2[i]; if (!TryFindFloorAtProbe(basis, targetRight + num5, targetInto + num6, expectedFloor, excludedRoot, out float floor2, out string floorSource2)) { floorSource = "support probe '" + text + "' found no usable floor"; return false; } num3 = Mathf.Min(num3, floor2); num4 = Mathf.Max(num4, floor2); hashSet.Add(floorSource2); list.Add($"{text}={floor2:0.###}@'{floorSource2}'"); } float num7 = num4 - num3; if (num7 > 0.035f) { floorSource = $"support height varies by {num7:0.###}m across the footprint " + "[" + string.Join(", ", list) + "]"; return false; } floor = num4; List<string> list2 = new List<string>(hashSet); list2.Sort(StringComparer.Ordinal); floorSource = string.Format("{0}, probes={1}, ", string.Join(" | ", list2), array.Length) + $"variation={num7:0.###}"; return true; } private static bool TryFindFloorAtProbe(PlacementBasis basis, float targetRight, float targetInto, float expectedFloor, Transform? excludedRoot, out float floor, out string floorSource) { //IL_000e: 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_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0027: 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_0039: 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_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_0050: 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_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: 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_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) floor = expectedFloor; floorSource = string.Empty; Vector3 val = basis.Origin + basis.Right * targetRight + basis.Into * targetInto + basis.Up * (expectedFloor + 3f); RaycastHit[] array = Physics.RaycastAll(val, -basis.Up, 8f, -1, (QueryTriggerInteraction)1); bool result = false; float num = float.MaxValue; RaycastHit[] array2 = array; for (int i = 0; i < array2.Length; i++) { RaycastHit val2 = array2[i]; Collider collider = ((RaycastHit)(ref val2)).collider; if (!((Object)(object)collider == (Object)null) && !IsSameOrChildOf(((Component)collider).transform, excludedRoot) && !((Object)(object)((Component)collider).GetComponentInParent<PhysGrabObject>() != (Object)null) && !(Vector3.Dot(((RaycastHit)(ref val2)).normal, basis.Up) < 0.65f)) { float num2 = Vector3.Dot(((RaycastHit)(ref val2)).point - basis.Origin, basis.Up); float num3 = Mathf.Abs(num2 - expectedFloor); if (!(num3 > 1.25f) && !(num3 >= num)) { num = num3; floor = num2; floorSource = GetTransformPath(((Component)collider).transform); result = true; } } } return result; } private static bool TryValidatePlacementClearance(PlacementBasis basis, Vector3 rootPosition, Bounds proxyOffsets, Transform? excludedRoot, out string source) { //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_000a: 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_0044: 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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009c: 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_00ad: 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_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_00c1: 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_00cc: 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) Vector3 extents = ((Bounds)(ref proxyOffsets)).extents; extents.x = Mathf.Max(extents.x + 0.035f, 0.035f); extents.y = Mathf.Max(extents.y - 0.01f, 0.01f); extents.z = Mathf.Max(extents.z + 0.035f, 0.035f); Vector3 val = rootPosition + basis.Right * ((Bounds)(ref proxyOffsets)).center.x + basis.Up * ((Bounds)(ref proxyOffsets)).center.y + basis.Into * ((Bounds)(ref proxyOffsets)).center.z; Quaternion val2 = Quaternion.LookRotation(basis.Into, basis.Up); Collider[] array = Physics.OverlapBox(val, extents, val2, -1, (QueryTriggerInteraction)1); HashSet<string> hashSet = new HashSet<string>(); int num = 0; Collider[] array2 = array; foreach (Collider val3 in array2) { if (!((Object)(object)val3 == (Object)null) && !IsSameOrChildOf(((Component)val3).transform, excludedRoot)) { num++; hashSet.Add(GetTransformPath(((Component)val3).transform)); } } if (num == 0) { source = "clear"; return true; } source = $"volume overlaps {num} collider(s): " + FormatSortedPaths(hashSet); return false; } private static string FormatSortedPaths(HashSet<string> paths) { List<string> list = new List<string>(paths); list.Sort(StringComparer.Ordinal); int num = Mathf.Max(list.Count - 4, 0); if (num > 0) { list.RemoveRange(4, num); } string text = string.Join(" | ", list); if (num <= 0) { return text; } return $"{text} | ... +{num} path(s)"; } private bool TryValidateSpawnedGeometry(PlacementBasis basis, GameObject spawned, Bounds plannedOffsets, Vector3 spawnPosition, out string source) { //IL_0007: 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_0029: 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_0079: 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_003f: 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_00aa: 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_011b: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) if (!TryMeasureProxyOffsets(spawned, spawned.transform.rotation, basis, out Bounds offsets, out string source2)) { source = "the live object exposed no usable local geometry: " + source2; return false; } if (!BoundsCoveredByPlan(plannedOffsets, offsets) || Mathf.Abs(((Bounds)(ref plannedOffsets)).min.y - ((Bounds)(ref offsets)).min.y) > 0.05f) { source = "plannedOffsets=" + FormatBounds(plannedOffsets) + ", actualOffsets=" + FormatBounds(offsets) + ", " + $"tolerance={0.05f:0.###}"; return false; } if (!TryValidatePlacementClearance(basis, spawnPosition, offsets, spawned.transform, out string source3)) { source = "post-spawn clearance failed: " + source3 + ", plannedOffsets=" + FormatBounds(plannedOffsets) + ", actualOffsets=" + FormatBounds(offsets); return false; } source = "plannedOffsets=" + FormatBounds(plannedOffsets) + ", actualOffsets=" + FormatBounds(offsets) + ", clearance='clear'"; return true; } private static bool TryValidateSpawnPose(GameObject spawned, Vector3 expectedPosition, Quaternion expectedRotation, out string diagnostics) { //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_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) float num = Vector3.Distance(spawned.transform.position, expectedPosition); float num2 = Quaternion.Angle(spawned.transform.rotation, expectedRotation); diagnostics = $"positionDelta={num:0.####}, " + $"rotationDelta={num2:0.###}"; if (num <= 0.01f) { return num2 <= 0.5f; } return false; } private static bool BoundsCoveredByPlan(Bounds planned, Bounds actual) { //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_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001e: 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_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_0037: 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_003f: 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) //IL_0047: 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_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005c: 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_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_0078: 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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ((Bounds)(ref planned)).min - Vector3.one * 0.05f; Vector3 val2 = ((Bounds)(ref planned)).max + Vector3.one * 0.05f; Vector3 min = ((Bounds)(ref actual)).min; Vector3 max = ((Bounds)(ref actual)).max; if (min.x >= val.x && min.y >= val.y && min.z >= val.z && max.x <= val2.x && max.y <= val2.y) { return max.z <= val2.z; } return false; } private bool TryMaintainClownLock(bool forceNetworkCorrection, out string failure) { //IL_00ac: 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_00cf: 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_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_006e: 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_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) failure = string.Empty; if ((Object)(object)_clownRoot == (Object)null || (Object)(object)_physGrabObject == (Object)null) { failure = "the extraction clown lock lost its root or PhysGrabObject"; return false; } try { _physGrabObject.OverrideKinematic(0.25f); _physGrabObject.OverrideIndestructible(0.25f); if ((Object)(object)_rigidbody != (Object)null) { if (!_rigidbody.isKinematic) { _rigidbody.velocity = Vector3.zero; _rigidbody.angularVelocity = Vector3.zero; } _rigidbody.constraints = (RigidbodyConstraints)126; _rigidbody.isKinematic = true; } bool flag = Vector3.Distance(_clownRoot.transform.position, _anchorPosition) > 0.025f; bool flag2 = Quaternion.Angle(_clownRoot.transform.rotation, _anchorRotation) > 1f; if (!forceNetworkCorrection && !flag && !flag2) { return true; } _clownRoot.transform.SetPositionAndRotation(_anchorPosition, _anchorRotation); if ((Object)(object)_rigidbody != (Object)null) { _rigidbody.position = _anchorPosition; _rigidbody.rotation = _anchorRotation; } if (PhotonNetwork.InRoom && (forceNetworkCorrection || Time.realtimeSinceStartup >= _nextNetworkCorrectionAt)) { if (!TryResolvePositionSynchronizationView(out PhotonView positionView, out failure)) { return false; } _nextNetworkCorrectionAt = Time.realtimeSinceStartup + 0.2f; positionView.RPC("SetPositionRPC", (RpcTarget)(forceNetworkCorrection ? 1 : 0), new object[2] { _anchorPosition, _anchorRotation }); } else if (!PhotonNetwork.InRoom) { _physGrabObject.SetPositionLogic(_anchorPosition, _anchorRotation); } return true; } catch (Exception ex) { failure = "maintaining the extraction clown lock threw " + ex.GetType().Name + ": " + ex.Message; return false; } } private bool TryResolvePositionSynchronizationView(out PhotonView positionView, out string failure) { positionView = null; failure = string.Empty; if ((Object)(object)_physGrabObject == (Object)null) { failure = "the extraction clown lost its PhysGrabObject before position synchronization"; return false; } GameObject gameObject = ((Component)_physGrabObject).gameObject; PhotonView photonView = _physGrabObject.photonView; if ((Object)(object)photonView != (Object)null && (Object)(object)((Component)photonView).gameObject == (Object)(object)gameObject) { positionView = photonView; } else { PhotonView component = gameObject.GetComponent<PhotonView>(); if ((Object)(object)component == (Object)null) { failure = "the extraction clown has no PhotonView on the PhysGrabObject GameObject for position synchronization"; return false; } positionView = component; _physGrabObject.photonView = component; } if (positionView.ViewID == 0) { failure = "the extraction clown position PhotonView has no allocated ViewID"; return false; } if ((Object)(object)PhotonView.Find(positionView.ViewID) != (Object)(object)positionView) { failure = $"the extraction clown position PhotonView ViewID={positionView.ViewID} " + "is not the registered room instance"; return false; } if (!positionView.IsMine) { failure = $"the extraction clown position PhotonView ViewID={positionView.ViewID} " + $"is controlled by actor {positionView.ControllerActorNr}"; return false; } return true; } private bool TryScheduleDeniedReplacement(int playerActorNumber) { if (!TryPlayVanillaDeny(playerActorNumber, out string failure)) { FailOpenForActivation(failure); return false; } _replacementRequested = true; _replacementReadyAt = Time.realtimeSinceStartup + 0.35f; Plugin.LogDebug("Scheduled one seamless extraction-clown refresh after " + $"{0.35f:0.##} seconds; the consumed " + "proxy remains visible until the swap."); return true; } private bool IsWaitingForReplacementProxy() { if (_gateArmed && _replacementRequested && (Object)(object)_clownRoot == (Object)null) { return !_sessionFailedOpen; } return false; } private bool HasPendingVanillaSuccess() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Invalid comparison between Unknown and I4 if (_extractionPoint.settingState) { return (int)_extractionPoint.stateSetTo == 3; } return false; } private bool TryPlayVanillaDeny(int playerActorNumber, out string failure) { //IL_0046: 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) failure = string.Empty; try { PhotonView photonView = _extractionPoint.photonView; if (PhotonNetwork.InRoom && (Object)(object)photonView != (Object)null && photonView.ViewID != 0) { photonView.RPC("ButtonDenyRPC", (RpcTarget)0, Array.Empty<object>()); } else { _extractionPoint.ButtonDenyRPC(default(PhotonMessageInfo)); } Plugin.LogDebug("Played vanilla ButtonDenyRPC for clown press by " + $"playerActor={playerActorNumber}."); return true; } catch (Exception ex) { failure = "vanilla ButtonDenyRPC failed with " + ex.GetType().Name + ": " + ex.Message; return false; } } private bool DestroyCurrentClown(string reason) { GameObject clownRoot = _clownRoot; int clownViewId = _clownViewId; DetachedCleanupEntry detachedCleanupEntry = null; if ((Object)(object)clownRoot == (Object)null) { ClearProxyReferences(); return true; } try { detachedCleanupEntry = QueueDetachedCleanup(clownRoot, _clownTrap, clownViewId, _clownSpawnRoom, _clownRootPhotonView, _clownRootViewId); DestroyNetworkOrLocalObject(clownRoot, detachedCleanupEntry.Room, detachedCleanupEntry.RootView, detachedCleanupEntry.RootViewId); } catch (Exception ex) { if (detachedCleanupEntry != null) { detachedCleanupEntry.FailureLogged = true; } ScheduleCleanupFailure($"Destroying extraction clown ViewID={clownViewId} failed with " + ex.GetType().Name + ": " + ex.Message); return false; } ClearProxyReferences(); Plugin.LogDebug($"Removed network clown ViewID={clownViewId} because {reason}."); return true; } private bool DestroyUntrackedSpawn(GameObject spawned) { DetachedCleanupEntry detachedCleanupEntry = null; try { detachedCleanupEntry = QueueDetachedCleanup(spawned, spawned.GetComponentInChildren<ClownTrap>(true), 0); DestroyNetworkOrLocalObject(spawned, detachedCleanupEntry.Room, detachedCleanupEntry.RootView, detachedCleanupEntry.RootViewId); } catch (Exception ex) { if (detachedCleanupEntry != null) { detachedCleanupEntry.FailureLogged = true; } _orphanedSpawn = spawned; ScheduleCleanupFailure("Cleaning up an unusable extraction clown failed with " + ex.GetType().Name + ": " + ex.Message); return false; } if (_orphanedSpawn == spawned) { _orphanedSpawn = null; } if ((Object)(object)_clownRoot == (Object)null) { _cleanupPending = false; _destroyFailureLogged = false; } return true; } private static void DestroyNetworkOrLocalObject(GameObject root, Room? expectedRoom, PhotonView? expectedRootView, int expectedRootViewId) { if (expectedRoom == null || !PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom != expectedRoom) { Object.Destroy((Object)(object)root); return; } if ((Object)(object)expectedRootView == (Object)null || expectedRootViewId == 0 || expectedRootView.ViewID != expectedRootViewId || PhotonView.Find(expectedRootViewId) != expectedRootView) { Object.Destroy((Object)(object)root); return; } if (!expectedRootView.IsMine) { throw new InvalidOperationException($"local actor does not control PhotonView {expectedRootViewId}"); } PhotonNetwork.Destroy(expectedRootView); } private static PhotonView? FindRootNetworkView(GameObject root) { PhotonView[] componentsInChildren = root.GetComponentsInChildren<PhotonView>(true); foreach (PhotonView val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && val.ViewID != 0 && val.InstantiationId == val.ViewID) { return val; } } return null; } private void ScheduleCleanupFailure(string reason) { _cleanupPending = true; if (!_destroyFailureLogged) { _destroyFailureLogged = true; Plugin.Log.LogError((object)(reason + ". Vanilla extraction is already available; network cleanup will be retried in the background.")); } } private void EndSession(string reason) { bool flag = _gateArmed || (Object)(object)_clownRoot != (Object)null || (Object)(object)_orphanedSpawn != (Object)null || _submissionSent; ReleaseVanillaSubmission(); _gateArmed = false; _replacementRequested = false; _pendingSuccess = false; _successPermitAvailable = false; _successPermitAccepted = false; _successInvocationInProgress = false; _submissionSent = false; _replacementReadyAt = 0f; _blockedSuccessLogged = false; DestroyCurrentClown(reason); if ((Object)(object)_orphanedSpawn != (Object)null) { DestroyUntrackedSpawn(_orphanedSpawn); } if (flag) {