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 CruiserRecall v0.1.0
CruiserRecall/cruiserrecall.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; 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.Bootstrap; using GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; using Unity.Collections; using Unity.Netcode; 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: AssemblyCompany("CruiserRecall")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.0.0")] [assembly: AssemblyInformationalVersion("0.1.0")] [assembly: AssemblyProduct("CruiserRecall")] [assembly: AssemblyTitle("CruiserRecall")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.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 CruiserRecall { [HarmonyPatch(typeof(GrabbableObject), "LateUpdate")] internal static class CarryPose { private static readonly Vector3 Grip = new Vector3(0f, 0f, -0.1f); [HarmonyPostfix] private static void AfterHeldPlacement(GrabbableObject __instance) { //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_0054: 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_006e: 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_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<RemoteMarker>()) && __instance.isHeld && !__instance.isPocketed && Object.op_Implicit((Object)(object)__instance.playerHeldBy) && Object.op_Implicit((Object)(object)__instance.parentObject)) { Transform transform = ((Component)__instance).transform; Vector3 val = -((Component)__instance.playerHeldBy).transform.forward; val.y = 0f; transform.rotation = Quaternion.LookRotation(Vector3.up, ((Vector3)(ref val)).normalized); transform.position = __instance.parentObject.position - transform.TransformVector(Grip); } } } internal static class Placement { internal static Bounds Hull(VehicleController car) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: 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_006b: Unknown result type (might be due to invalid IL or missing references) //IL_007b: 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_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) Bounds bounds = default(Bounds); bool initialized = false; Collider[] array = PhysicalBody(car); foreach (Collider val in array) { WheelCollider val2 = (WheelCollider)(object)((val is WheelCollider) ? val : null); if (val2 != null) { Vector3 val3 = RootMetres(((Component)car).transform, ((Component)val2).transform.TransformPoint(val2.center)); Include(ref bounds, ref initialized, val3 - Vector3.up * ((val2.radius + val2.suspensionDistance) * Mathf.Abs(((Component)val2).transform.lossyScale.y))); } else { Encapsulate(((Component)car).transform, val, ref bounds, ref initialized); } } if (!initialized) { if (!Object.op_Implicit((Object)(object)car.boundsCollider)) { throw new InvalidOperationException("Cruiser bounds collider is unavailable."); } Encapsulate(((Component)car).transform, (Collider)(object)car.boundsCollider, ref bounds, ref initialized); } if (!(((Bounds)(ref bounds)).size.x > 15f) && !(((Bounds)(ref bounds)).size.y > 15f) && !(((Bounds)(ref bounds)).size.z > 20f)) { Vector3 size = ((Bounds)(ref bounds)).size; if (!(((Vector3)(ref size)).sqrMagnitude < 1f)) { return bounds; } } throw new InvalidOperationException("Unsupported cruiser dimensions."); } internal static Vector3 RootMetres(Transform root, Vector3 world) { //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_000b: 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) return Quaternion.Inverse(root.rotation) * (world - root.position); } private static void Include(ref Bounds bounds, ref bool initialized, Vector3 point) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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) if (!initialized) { bounds = new Bounds(point, Vector3.zero); initialized = true; } else { ((Bounds)(ref bounds)).Encapsulate(point); } } private static void Encapsulate(Transform root, Collider c, ref Bounds bounds, ref bool initialized) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_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_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00be: 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_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: 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_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) BoxCollider val = (BoxCollider)(object)((c is BoxCollider) ? c : null); Bounds bounds2 = default(Bounds); Transform val2; if (val != null) { ((Bounds)(ref bounds2))..ctor(val.center, val.size); val2 = ((Component)val).transform; } else { MeshCollider val3 = (MeshCollider)(object)((c is MeshCollider) ? c : null); if (val3 != null && Object.op_Implicit((Object)(object)val3.sharedMesh)) { bounds2 = val3.sharedMesh.bounds; val2 = ((Component)val3).transform; } else { bounds2 = c.bounds; val2 = null; } } int[] array = new int[2] { -1, 1 }; foreach (int num in array) { int[] array2 = new int[2] { -1, 1 }; foreach (int num2 in array2) { int[] array3 = new int[2] { -1, 1 }; foreach (int num3 in array3) { Vector3 val4 = ((Bounds)(ref bounds2)).center + Vector3.Scale(((Bounds)(ref bounds2)).extents, new Vector3((float)num, (float)num2, (float)num3)); Include(ref bounds, ref initialized, RootMetres(root, Object.op_Implicit((Object)(object)val2) ? val2.TransformPoint(val4) : val4)); } } } } private static bool DetectionOnly(Collider collider) { Transform val = ((Component)collider).transform; while (Object.op_Implicit((Object)(object)val)) { if (RecallRules.DetectionOnlyName(((Object)val).name)) { return true; } val = val.parent; } return RecallRules.DetectionOnlyName(LayerMask.LayerToName(((Component)collider).gameObject.layer)); } private static Collider[] PhysicalBody(VehicleController car) { return (from c in ((Component)car).GetComponentsInChildren<Collider>() where c.enabled && !c.isTrigger && !DetectionOnly(c) && !Object.op_Implicit((Object)(object)((Component)c).GetComponentInParent<GrabbableObject>()) && (Object)(object)c.attachedRigidbody == (Object)(object)car.mainRigidbody select c).ToArray(); } private static bool CanStopCar(Collider obstacle, Collider[] body) { if (!Object.op_Implicit((Object)(object)obstacle) || !obstacle.enabled || !((Component)obstacle).gameObject.activeInHierarchy || obstacle.isTrigger || DetectionOnly(obstacle)) { return false; } foreach (Collider val in body) { if (!Physics.GetIgnoreLayerCollision(((Component)val).gameObject.layer, ((Component)obstacle).gameObject.layer) && !Physics.GetIgnoreCollision(val, obstacle)) { return true; } } return false; } internal static bool InVehicle(VehicleController car, Vector3 world) { //IL_0045: 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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: 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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0069: 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_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_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_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: 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_00a8: Unknown result type (might be due to invalid IL or missing references) PlayerPhysicsRegion physicsRegion = car.physicsRegion; Collider val = (Collider)((Object.op_Implicit((Object)(object)physicsRegion) && Object.op_Implicit((Object)(object)physicsRegion.itemDropCollider)) ? ((object)physicsRegion.itemDropCollider) : ((object)car.boundsCollider)); if (!Object.op_Implicit((Object)(object)val)) { return false; } BoxCollider val2 = (BoxCollider)(object)((val is BoxCollider) ? val : null); if (val2 != null) { Vector3 val3 = ((Component)val2).transform.InverseTransformPoint(world) - val2.center; Vector3 val4 = val2.size * 0.5f; if (Mathf.Abs(val3.x) <= val4.x + 0.03f && Mathf.Abs(val3.y) <= val4.y + 0.03f) { return Mathf.Abs(val3.z) <= val4.z + 0.03f; } return false; } if (val.enabled && ((Component)val).gameObject.activeInHierarchy) { Vector3 val5 = val.ClosestPoint(world) - world; return ((Vector3)(ref val5)).sqrMagnitude < 0.0025f; } return false; } internal static List<GrabbableObject> Cargo(VehicleController car) { return (from item in Object.FindObjectsOfType<GrabbableObject>(true) where Object.op_Implicit((Object)(object)item) && Object.op_Implicit((Object)(object)((NetworkBehaviour)item).NetworkObject) && ((NetworkBehaviour)item).NetworkObject.IsSpawned && !item.isHeld && !item.isHeldByEnemy && (((Component)item).transform.IsChildOf(((Component)car).transform) || InVehicle(car, ((Component)item).transform.position)) select item).ToList(); } private static bool Own(Collider c, VehicleController car, HashSet<Transform> cargo) { if (!((Component)c).transform.IsChildOf(((Component)car).transform) && !((Object)(object)((Component)c).GetComponentInParent<VehicleController>() == (Object)(object)car)) { GrabbableObject componentInParent = ((Component)c).GetComponentInParent<GrabbableObject>(); if (componentInParent != null) { return cargo.Contains(((Component)componentInParent).transform); } return false; } return true; } private static bool Dangerous(Collider c) { MonoBehaviour[] componentsInParent = ((Component)c).GetComponentsInParent<MonoBehaviour>(true); foreach (MonoBehaviour val in componentsInParent) { if (Object.op_Implicit((Object)(object)val)) { string name = ((object)val).GetType().Name; if (name.IndexOf("Quicksand", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("WaterTrigger", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("KillLocalPlayer", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("DamagePlayer", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("Landmine", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("Turret", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } } } return false; } internal static bool Find(VehicleController car, PlayerControllerB player, List<GrabbableObject> items, out Vector3 target, out float yaw, out string failure, Action<string> log) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: 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_011c: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Expected O, but got Unknown //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_0284: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Unknown result type (might be due to invalid IL or missing references) //IL_0295: Unknown result type (might be due to invalid IL or missing references) //IL_029a: Unknown result type (might be due to invalid IL or missing references) //IL_029f: Unknown result type (might be due to invalid IL or missing references) //IL_02ac: Unknown result type (might be due to invalid IL or missing references) //IL_02b1: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Unknown result type (might be due to invalid IL or missing references) //IL_04e4: Unknown result type (might be due to invalid IL or missing references) //IL_030b: Unknown result type (might be due to invalid IL or missing references) //IL_0314: Unknown result type (might be due to invalid IL or missing references) //IL_031c: Unknown result type (might be due to invalid IL or missing references) //IL_032b: Unknown result type (might be due to invalid IL or missing references) //IL_0332: Unknown result type (might be due to invalid IL or missing references) //IL_0337: Unknown result type (might be due to invalid IL or missing references) //IL_033c: Unknown result type (might be due to invalid IL or missing references) //IL_0341: Unknown result type (might be due to invalid IL or missing references) //IL_034b: Unknown result type (might be due to invalid IL or missing references) //IL_0350: Unknown result type (might be due to invalid IL or missing references) //IL_0355: Unknown result type (might be due to invalid IL or missing references) //IL_0557: Unknown result type (might be due to invalid IL or missing references) //IL_0560: Unknown result type (might be due to invalid IL or missing references) //IL_0567: Unknown result type (might be due to invalid IL or missing references) //IL_0578: Unknown result type (might be due to invalid IL or missing references) //IL_0582: Unknown result type (might be due to invalid IL or missing references) //IL_0587: Unknown result type (might be due to invalid IL or missing references) //IL_058c: Unknown result type (might be due to invalid IL or missing references) //IL_0591: Unknown result type (might be due to invalid IL or missing references) //IL_0599: Unknown result type (might be due to invalid IL or missing references) //IL_05b1: Unknown result type (might be due to invalid IL or missing references) //IL_05ba: Unknown result type (might be due to invalid IL or missing references) //IL_05c1: Unknown result type (might be due to invalid IL or missing references) //IL_05c6: Unknown result type (might be due to invalid IL or missing references) //IL_05cb: Unknown result type (might be due to invalid IL or missing references) //IL_05d0: Unknown result type (might be due to invalid IL or missing references) //IL_05d7: Unknown result type (might be due to invalid IL or missing references) //IL_05e3: Unknown result type (might be due to invalid IL or missing references) //IL_05ef: Unknown result type (might be due to invalid IL or missing references) //IL_05fb: Unknown result type (might be due to invalid IL or missing references) //IL_0600: Unknown result type (might be due to invalid IL or missing references) //IL_0609: Unknown result type (might be due to invalid IL or missing references) //IL_0613: Unknown result type (might be due to invalid IL or missing references) //IL_0629: Unknown result type (might be due to invalid IL or missing references) //IL_0630: Unknown result type (might be due to invalid IL or missing references) //IL_063c: Unknown result type (might be due to invalid IL or missing references) //IL_0538: Unknown result type (might be due to invalid IL or missing references) //IL_03f0: Unknown result type (might be due to invalid IL or missing references) //IL_03f5: 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_0747: Unknown result type (might be due to invalid IL or missing references) //IL_0756: Unknown result type (might be due to invalid IL or missing references) //IL_041d: Unknown result type (might be due to invalid IL or missing references) //IL_07d9: Unknown result type (might be due to invalid IL or missing references) //IL_07db: Unknown result type (might be due to invalid IL or missing references) //IL_07fb: Unknown result type (might be due to invalid IL or missing references) //IL_081b: Unknown result type (might be due to invalid IL or missing references) //IL_07c2: Unknown result type (might be due to invalid IL or missing references) //IL_0461: Unknown result type (might be due to invalid IL or missing references) //IL_0476: Unknown result type (might be due to invalid IL or missing references) //IL_06a1: Unknown result type (might be due to invalid IL or missing references) //IL_06ad: Unknown result type (might be due to invalid IL or missing references) //IL_06bb: Unknown result type (might be due to invalid IL or missing references) //IL_06c7: Unknown result type (might be due to invalid IL or missing references) target = default(Vector3); yaw = ((Component)player).transform.eulerAngles.y; failure = "no valid ground"; Quaternion rotation = Quaternion.Euler(0f, yaw, 0f); Bounds bounds = Hull(car); foreach (GrabbableObject item in items) { Collider[] componentsInChildren = ((Component)item).GetComponentsInChildren<Collider>(); foreach (Collider val in componentsInChildren) { if (val.enabled && !val.isTrigger && ((Component)val).gameObject.activeInHierarchy && !DetectionOnly(val)) { bool initialized = true; Encapsulate(((Component)car).transform, val, ref bounds, ref initialized); } } } log($"Placement: player={((Component)player).transform.position}, cruiserScale={((Component)car).transform.lossyScale}, hullCentreMetres={((Bounds)(ref bounds)).center}, hullSizeMetres={((Bounds)(ref bounds)).size}, cargo={items.Count}."); if (((Bounds)(ref bounds)).size.x > 15f || ((Bounds)(ref bounds)).size.z > 20f || ((Bounds)(ref bounds)).size.y > 15f) { failure = "cargo extends too far beyond the vehicle"; return false; } HashSet<Transform> cargo = new HashSet<Transform>(items.Select((GrabbableObject val11) => ((Component)val11).transform)); Collider[] body = PhysicalBody(car); if (body.Length == 0) { failure = "cruiser has no active physical colliders"; return false; } Vector3 extents = ((Bounds)(ref bounds)).extents; int mask = LayerMask.GetMask(new string[4] { "Default", "Room", "Colliders", "Terrain" }); GameObject val2 = new GameObject("Cruiser Recall placement query"); ((Object)val2).hideFlags = (HideFlags)61; val2.layer = 2; val2.transform.position = new Vector3(0f, -10000f, 0f); BoxCollider val3 = val2.AddComponent<BoxCollider>(); ((Collider)val3).isTrigger = true; try { Vector3 val9 = default(Vector3); float num8 = default(float); for (int num = 0; num < 6; num++) { Vector3 val4 = ((Component)player).transform.position + rotation * Vector3.forward * RecallRules.CentreDistance(extents.z, num); float num2 = float.PositiveInfinity; float num3 = float.NegativeInfinity; string text = ""; int[] array = new int[3] { -1, 0, 1 }; foreach (int num4 in array) { int[] array2 = new int[3] { -1, 0, 1 }; foreach (int num6 in array2) { RaycastHit[] array3 = (from h in Physics.RaycastAll(val4 + rotation * new Vector3((float)num4 * extents.x, 0f, (float)num6 * extents.z) + Vector3.up * 4f, Vector3.down, 12f, mask, (QueryTriggerInteraction)1) where !Own(((RaycastHit)(ref h)).collider, car, cargo) && CanStopCar(((RaycastHit)(ref h)).collider, body) && !Object.op_Implicit((Object)(object)((Component)((RaycastHit)(ref h)).collider).GetComponentInParent<PlayerControllerB>()) && !Object.op_Implicit((Object)(object)((Component)((RaycastHit)(ref h)).collider).GetComponentInParent<GrabbableObject>()) && !Object.op_Implicit((Object)(object)((Component)((RaycastHit)(ref h)).collider).GetComponentInParent<VehicleController>()) orderby ((RaycastHit)(ref h)).distance select h).ToArray(); if (array3.Length == 0) { text = $"missing ground at sample {num4},{num6}"; continue; } RaycastHit val5 = array3[0]; if (!RecallRules.SlopeAllowed(((RaycastHit)(ref val5)).normal.y)) { text = $"ground too steep: {Describe(((RaycastHit)(ref val5)).collider)}, normalY={((RaycastHit)(ref val5)).normal.y:F2}"; continue; } if (Dangerous(((RaycastHit)(ref val5)).collider)) { text = "hazardous ground: " + Describe(((RaycastHit)(ref val5)).collider); continue; } num2 = Mathf.Min(num2, ((RaycastHit)(ref val5)).point.y); num3 = Mathf.Max(num3, ((RaycastHit)(ref val5)).point.y); } } if (text.Length > 0) { failure = text; log($"Placement candidate {num + 1} rejected: {failure}."); continue; } if (!RecallRules.Supported(num2, num3, ((Component)player).transform.position.y)) { failure = "terrain height varies too much"; log($"Placement candidate {num + 1} rejected: {failure}; min={num2:F2}, max={num3:F2}, playerY={((Component)player).transform.position.y:F2}."); continue; } Vector3 val6 = val4 - rotation * new Vector3(((Bounds)(ref bounds)).center.x, 0f, ((Bounds)(ref bounds)).center.z); val6.y = num3 - ((Bounds)(ref bounds)).min.y + 0.6f; Vector3 boxCentre = val6 + rotation * ((Bounds)(ref bounds)).center; Vector3 clearHalf = new Vector3(extents.x + 0.08f, extents.y + 0.02f, extents.z + 0.08f); val3.size = clearHalf * 2f; Collider val7 = null; float num7 = 0f; Collider[] componentsInChildren = Physics.OverlapBox(boxCentre, clearHalf, rotation, -1, (QueryTriggerInteraction)2); foreach (Collider val8 in componentsInChildren) { if (!((Object)(object)val8 == (Object)(object)val3) && !Own(val8, car, cargo) && CanStopCar(val8, body) && RecallRules.PenetrationBlocks(Physics.ComputePenetration((Collider)(object)val3, boxCentre, rotation, val8, ((Component)val8).transform.position, ((Component)val8).transform.rotation, ref val9, ref num8), num8)) { val7 = val8; num7 = num8; break; } } if (Object.op_Implicit((Object)(object)val7)) { failure = "landing space intersects " + ((Object)val7).name; log($"Placement candidate {num + 1} rejected: {Describe(val7)}, penetration={num7:F3}m, centre={boxCentre}, half={clearHalf}."); continue; } PlayerControllerB val10 = ((IEnumerable<PlayerControllerB>)StartOfRound.Instance.allPlayerScripts).FirstOrDefault((Func<PlayerControllerB, bool>)((PlayerControllerB p) => Object.op_Implicit((Object)(object)p) && p.isPlayerControlled && !p.isPlayerDead && NearBox(((Component)p).transform.position, boxCentre, rotation, clearHalf))); if (Object.op_Implicit((Object)(object)val10)) { failure = "a player is in the landing area"; log($"Placement candidate {num + 1} rejected: player {val10.actualClientId} at {((Component)val10).transform.position}."); continue; } target = val6; log($"Placement candidate {num + 1} accepted: root={val6}, ground={num2:F2}..{num3:F2}, hullSizeMetres={((Bounds)(ref bounds)).size}."); return true; } return false; } finally { ((Collider)val3).enabled = false; Object.Destroy((Object)(object)val2); } } private static string Describe(Collider c) { string text = ((Object)c).name; Transform parent = ((Component)c).transform.parent; int num = 0; while (Object.op_Implicit((Object)(object)parent) && num < 3) { text = ((Object)parent).name + "/" + text; num++; parent = parent.parent; } return $"{text} ({((object)c).GetType().Name}, layer={LayerMask.LayerToName(((Component)c).gameObject.layer)}, trigger={c.isTrigger})"; } private static bool NearBox(Vector3 point, Vector3 centre, Quaternion rotation, Vector3 half) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //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_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_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_0013: 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_002c: 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_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) Vector3 val = Quaternion.Inverse(rotation) * (point - centre); if (Mathf.Abs(val.x) < half.x + 0.5f && Mathf.Abs(val.z) < half.z + 0.5f) { return Mathf.Abs(val.y) < half.y + 2f; } return false; } } [BepInPlugin("achachala.cruiserrecall", "Cruiser Recall", "0.1.0")] [BepInDependency("evaisa.lethallib", "1.2.0")] public sealed class Plugin : BaseUnityPlugin { public const string Id = "achachala.cruiserrecall"; public const string Version = "0.1.0"; private const string Request = "achachala.cruiserrecall.request.v1"; private const string Warp = "achachala.cruiserrecall.warp.v1"; private const string Feedback = "achachala.cruiserrecall.feedback.v1"; private const string ButtonSound = "achachala.cruiserrecall.button-sound.v1"; internal static Plugin Instance; private NetworkManager? network; private float nextLocalUse; private readonly RecallCooldown cooldown = new RecallCooldown(); private uint revision; private readonly Dictionary<ulong, uint> applied = new Dictionary<ulong, uint>(); private readonly Dictionary<ulong, float> protectedUntil = new Dictionary<ulong, float>(); private readonly List<(WarpPacket state, float deadline)> pending = new List<(WarpPacket, float)>(); private void Awake() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) Instance = this; RecallAudio.Load(); RemoteItem.Register(); new Harmony("achachala.cruiserrecall").PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Cruiser Recall 0.1.0 loaded. Store price: 250 credits. Host and all clients required."); } private void Update() { //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Expected O, but got Unknown //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Expected O, but got Unknown //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Expected O, but got Unknown NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)network != (Object)(object)singleton || (Object.op_Implicit((Object)(object)network) && !network.IsListening)) { Detach(); } if (!Object.op_Implicit((Object)(object)singleton) || !singleton.IsListening || singleton.CustomMessagingManager == null) { return; } if (!Object.op_Implicit((Object)(object)network)) { network = singleton; singleton.CustomMessagingManager.RegisterNamedMessageHandler("achachala.cruiserrecall.button-sound.v1", new HandleNamedMessageDelegate(ReceiveButtonSound)); singleton.CustomMessagingManager.RegisterNamedMessageHandler("achachala.cruiserrecall.request.v1", new HandleNamedMessageDelegate(ReceiveRequest)); singleton.CustomMessagingManager.RegisterNamedMessageHandler("achachala.cruiserrecall.warp.v1", new HandleNamedMessageDelegate(ReceiveWarp)); singleton.CustomMessagingManager.RegisterNamedMessageHandler("achachala.cruiserrecall.feedback.v1", new HandleNamedMessageDelegate(ReceiveFeedback)); } (WarpPacket, float)[] array = pending.ToArray(); for (int i = 0; i < array.Length; i++) { (WarpPacket, float) item = array[i]; if (Apply(item.Item1)) { pending.Remove(item); } else if (Time.unscaledTime > item.Item2) { pending.Remove(item); ((BaseUnityPlugin)this).Logger.LogWarning((object)"Cruiser recall sync timed out waiting for existing vehicle/cargo objects."); } } ulong[] array2 = (from p in protectedUntil where p.Value < Time.unscaledTime select p.Key).ToArray(); foreach (ulong key in array2) { protectedUntil.Remove(key); } } private void Detach() { if (Object.op_Implicit((Object)(object)network) && network.CustomMessagingManager != null) { network.CustomMessagingManager.UnregisterNamedMessageHandler("achachala.cruiserrecall.button-sound.v1"); network.CustomMessagingManager.UnregisterNamedMessageHandler("achachala.cruiserrecall.request.v1"); network.CustomMessagingManager.UnregisterNamedMessageHandler("achachala.cruiserrecall.warp.v1"); network.CustomMessagingManager.UnregisterNamedMessageHandler("achachala.cruiserrecall.feedback.v1"); } network = null; nextLocalUse = 0f; cooldown.Reset(); revision = 0u; pending.Clear(); applied.Clear(); protectedUntil.Clear(); } internal unsafe void Activate(GrabbableObject item) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_009b: 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_00b9: Unknown result type (might be due to invalid IL or missing references) if (!((NetworkBehaviour)item).IsOwner || !Object.op_Implicit((Object)(object)item.playerHeldBy) || !((NetworkBehaviour)item.playerHeldBy).IsOwner) { return; } RecallAudio.PlayButton(((Component)item).transform.position); if (!Object.op_Implicit((Object)(object)network) || Time.unscaledTime < nextLocalUse) { return; } nextLocalUse = Time.unscaledTime + 0.1f; if (network.IsServer) { Execute(network.LocalClientId, ((NetworkBehaviour)item).NetworkObjectId); return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(8, (Allocator)2, -1); try { ulong networkObjectId = ((NetworkBehaviour)item).NetworkObjectId; ((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref networkObjectId, default(ForPrimitives)); network.CustomMessagingManager.SendNamedMessage("achachala.cruiserrecall.request.v1", 0uL, val, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } private void ReceiveRequest(ulong sender, FastBufferReader reader) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)network) && network.IsServer && ((FastBufferReader)(ref reader)).Length - ((FastBufferReader)(ref reader)).Position == 8 && ((FastBufferReader)(ref reader)).TryBeginRead(8)) { ulong remote = default(ulong); ((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref remote, default(ForPrimitives)); Execute(sender, remote); } } private unsafe void Execute(ulong sender, ulong remote) { //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_0282: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_03a1: Unknown result type (might be due to invalid IL or missing references) //IL_03ae: Unknown result type (might be due to invalid IL or missing references) //IL_03bb: 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_03e4: Unknown result type (might be due to invalid IL or missing references) //IL_03e9: Unknown result type (might be due to invalid IL or missing references) //IL_051a: Unknown result type (might be due to invalid IL or missing references) //IL_04ac: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)network) || !network.IsServer || !network.ConnectedClients.ContainsKey(sender)) { return; } StartOfRound instance = StartOfRound.Instance; PlayerControllerB player = (Object.op_Implicit((Object)(object)instance) ? ((IEnumerable<PlayerControllerB>)instance.allPlayerScripts).FirstOrDefault((Func<PlayerControllerB, bool>)((PlayerControllerB p) => Object.op_Implicit((Object)(object)p) && p.actualClientId == sender && p.isPlayerControlled)) : null); if (!Object.op_Implicit((Object)(object)instance) || !Object.op_Implicit((Object)(object)player) || !network.SpawnManager.SpawnedObjects.TryGetValue(remote, out var value) || !Object.op_Implicit((Object)(object)value) || !Object.op_Implicit((Object)(object)((Component)value).GetComponent<RemoteMarker>())) { return; } GrabbableObject component = ((Component)value).GetComponent<GrabbableObject>(); bool flag = Object.op_Implicit((Object)(object)component) && component.isHeld && !component.isPocketed && (Object)(object)component.playerHeldBy == (Object)(object)player && (Object)(object)player.currentlyHeldObjectServer == (Object)(object)component; if (!flag || player.isPlayerDead) { return; } BroadcastButton(sender, ((Component)component).transform.position); int num = cooldown.Remaining(Time.unscaledTime); if (num > 0) { Tell(sender, $"Cooldown: {num}s remaining."); return; } if (!RecallRules.CanUse(alive: true, !player.isInsideFactory && !player.isInHangarShipRoom, instance.shipHasLanded, instance.shipIsLeaving || instance.travellingToNewLevel || instance.inShipPhase, flag)) { Tell(sender, "Use outside while the ship is landed."); return; } try { VehicleController car = (from c in Object.FindObjectsOfType<VehicleController>() where Object.op_Implicit((Object)(object)c) && Object.op_Implicit((Object)(object)((NetworkBehaviour)c).NetworkObject) && ((NetworkBehaviour)c).NetworkObject.IsSpawned && !c.carDestroyed select c).OrderBy(delegate(VehicleController c) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) Vector3 val2 = ((Component)c).transform.position - ((Component)player).transform.position; return ((Vector3)(ref val2)).sqrMagnitude; }).FirstOrDefault(); if (!Object.op_Implicit((Object)(object)car)) { Tell(sender, "No cruiser available."); return; } if (car.inDropshipAnimation) { Tell(sender, "Wait for delivery."); return; } if (car.magnetedToShip) { Tell(sender, "Release the ship magnet first."); return; } Bounds occupiedBounds = Placement.Hull(car); ((Bounds)(ref occupiedBounds)).Expand(new Vector3(1f, 3f, 1f)); if (Object.op_Implicit((Object)(object)car.currentDriver) || Object.op_Implicit((Object)(object)car.currentPassenger) || instance.allPlayerScripts.Any((PlayerControllerB p) => Object.op_Implicit((Object)(object)p) && p.isPlayerControlled && !p.isPlayerDead && ((Bounds)(ref occupiedBounds)).Contains(Placement.RootMetres(((Component)car).transform, ((Component)p).transform.position)))) { Tell(sender, "Everyone must get off the cruiser."); return; } List<GrabbableObject> list = Placement.Cargo(car); if (list.Count > 1024) { Tell(sender, "Too much cargo."); return; } if (!Placement.Find(car, player, list, out Vector3 target, out float yaw, out string failure, delegate(string text) { ((BaseUnityPlugin)this).Logger.LogInfo((object)text); })) { Tell(sender, RecallRules.PlacementMessage(failure)); return; } WarpPacket warpPacket = new WarpPacket { Car = ((NetworkBehaviour)car).NetworkObjectId, Revision = ++revision, X = target.x, Y = target.y, Z = target.z, Yaw = yaw }; Quaternion inverse = Quaternion.Inverse(((Component)car).transform.rotation); warpPacket.Cargo = list.Select(delegate(GrabbableObject c) { //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_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005d: 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_0075: 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_008d: Unknown result type (might be due to invalid IL or missing references) Vector3 val2 = ((Component)car).transform.InverseTransformPoint(((Component)c).transform.position); Quaternion val3 = inverse * ((Component)c).transform.rotation; return new CargoPose { Id = ((NetworkBehaviour)c).NetworkObjectId, X = val2.x, Y = val2.y, Z = val2.z, Qx = val3.x, Qy = val3.y, Qz = val3.z, Qw = val3.w }; }).ToArray(); byte[] array = warpPacket.Encode(); if (!WarpPacket.TryDecode(array, out WarpPacket _)) { throw new InvalidOperationException("Invalid vehicle/cargo transform; recall cancelled before movement."); } if (!Apply(warpPacket)) { throw new InvalidOperationException("Existing cruiser/cargo became unavailable before recall."); } cooldown.Start(Time.unscaledTime); FastBufferWriter val = default(FastBufferWriter); foreach (ulong connectedClientsId in network.ConnectedClientsIds) { if (connectedClientsId != network.LocalClientId) { ((FastBufferWriter)(ref val))..ctor(array.Length, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteBytesSafe(array, array.Length, 0); network.CustomMessagingManager.SendNamedMessage("achachala.cruiserrecall.warp.v1", connectedClientsId, val, (NetworkDelivery)4); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } } ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Client {sender} recalled cruiser {warpPacket.Car} with {list.Count} loose cargo objects to {target}."); Tell(sender, "Cruiser recalled."); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Cruiser recall failed: " + ex)); Tell(sender, "Recall failed."); } } private void ReceiveWarp(ulong sender, FastBufferReader reader) { if (!Object.op_Implicit((Object)(object)network) || network.IsServer || sender != 0L) { return; } int num = ((FastBufferReader)(ref reader)).Length - ((FastBufferReader)(ref reader)).Position; if (num >= 36 && num <= 36900 && ((FastBufferReader)(ref reader)).TryBeginRead(num)) { byte[] data = new byte[num]; ((FastBufferReader)(ref reader)).ReadBytesSafe(ref data, num, 0); if (WarpPacket.TryDecode(data, out WarpPacket state) && !Apply(state)) { pending.Add((state, Time.unscaledTime + 5f)); } } } private bool Apply(WarpPacket state) { //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: 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_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: 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_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: 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) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_010b: 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_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0115: 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_0124: Unknown result type (might be due to invalid IL or missing references) //IL_012f: 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_039a: Unknown result type (might be due to invalid IL or missing references) //IL_029c: Unknown result type (might be due to invalid IL or missing references) //IL_02a1: Unknown result type (might be due to invalid IL or missing references) //IL_02a6: Unknown result type (might be due to invalid IL or missing references) //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_02d0: Unknown result type (might be due to invalid IL or missing references) //IL_02d9: 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_02e9: Unknown result type (might be due to invalid IL or missing references) //IL_02eb: Unknown result type (might be due to invalid IL or missing references) //IL_02fa: Unknown result type (might be due to invalid IL or missing references) //IL_02ff: Unknown result type (might be due to invalid IL or missing references) //IL_0304: Unknown result type (might be due to invalid IL or missing references) //IL_030e: Unknown result type (might be due to invalid IL or missing references) //IL_0313: Unknown result type (might be due to invalid IL or missing references) //IL_0318: Unknown result type (might be due to invalid IL or missing references) //IL_0339: Unknown result type (might be due to invalid IL or missing references) //IL_033b: Unknown result type (might be due to invalid IL or missing references) //IL_0333: Unknown result type (might be due to invalid IL or missing references) //IL_0340: Unknown result type (might be due to invalid IL or missing references) //IL_0356: Unknown result type (might be due to invalid IL or missing references) //IL_0358: Unknown result type (might be due to invalid IL or missing references) //IL_0350: Unknown result type (might be due to invalid IL or missing references) //IL_035d: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)network)) { return false; } if (applied.TryGetValue(state.Car, out var value) && value >= state.Revision) { return true; } if (!network.SpawnManager.SpawnedObjects.TryGetValue(state.Car, out var value2) || !Object.op_Implicit((Object)(object)value2)) { return false; } VehicleController component = ((Component)value2).GetComponent<VehicleController>(); if (!Object.op_Implicit((Object)(object)component)) { return false; } List<(GrabbableObject, CargoPose, Vector3, Vector3)> list = new List<(GrabbableObject, CargoPose, Vector3, Vector3)>(); CargoPose[] cargo = state.Cargo; foreach (CargoPose cargoPose in cargo) { if (!network.SpawnManager.SpawnedObjects.TryGetValue(cargoPose.Id, out var value3) || !Object.op_Implicit((Object)(object)value3)) { return false; } GrabbableObject component2 = ((Component)value3).GetComponent<GrabbableObject>(); if (!Object.op_Implicit((Object)(object)component2)) { return false; } Transform parent = ((Component)component2).transform.parent; Vector3 val = (Object.op_Implicit((Object)(object)parent) ? parent.TransformPoint(component2.targetFloorPosition) : component2.targetFloorPosition); Vector3 val2 = (Object.op_Implicit((Object)(object)parent) ? parent.TransformPoint(component2.startFallingPosition) : component2.startFallingPosition); list.Add((component2, cargoPose, ((Component)component).transform.InverseTransformPoint(val), ((Component)component).transform.InverseTransformPoint(val2))); } protectedUntil[state.Car] = Time.unscaledTime + 0.75f; Vector3 val3 = default(Vector3); ((Vector3)(ref val3))..ctor(state.X, state.Y, state.Z); Quaternion val4 = Quaternion.Euler(0f, state.Yaw, 0f); Rigidbody mainRigidbody = component.mainRigidbody; Vector3 val5 = (Object.op_Implicit((Object)(object)mainRigidbody) ? ((Component)component).transform.InverseTransformPoint(((Component)mainRigidbody).transform.position) : Vector3.zero); Quaternion val6 = (Object.op_Implicit((Object)(object)mainRigidbody) ? (Quaternion.Inverse(((Component)component).transform.rotation) * mainRigidbody.rotation) : Quaternion.identity); ((Component)component).transform.SetPositionAndRotation(val3, val4); component.syncedPosition = val3; component.syncedRotation = val4; if (Object.op_Implicit((Object)(object)mainRigidbody)) { RelocateBody(mainRigidbody, ((Component)component).transform.TransformPoint(val5), val4 * val6); } foreach (var item in list) { var (val7, cargoPose2, _, _) = item; if (!val7.isHeld && !val7.isHeldByEnemy) { Vector3 val8 = ((Component)component).transform.TransformPoint(new Vector3(cargoPose2.X, cargoPose2.Y, cargoPose2.Z)); Quaternion val9 = val4 * new Quaternion(cargoPose2.Qx, cargoPose2.Qy, cargoPose2.Qz, cargoPose2.Qw); ((Component)val7).transform.SetPositionAndRotation(val8, val9); RelocateBody(val7.propBody, val8, val9); Vector3 val10 = ((Component)component).transform.TransformPoint(item.Item3); Vector3 val11 = ((Component)component).transform.TransformPoint(item.Item4); Transform parent2 = ((Component)val7).transform.parent; val7.targetFloorPosition = (Object.op_Implicit((Object)(object)parent2) ? parent2.InverseTransformPoint(val10) : val10); val7.startFallingPosition = (Object.op_Implicit((Object)(object)parent2) ? parent2.InverseTransformPoint(val11) : val11); } } Physics.SyncTransforms(); applied[state.Car] = state.Revision; RecallAudio.PlayTeleport(val3); return true; } private static void RelocateBody(Rigidbody? body, Vector3 position, Quaternion rotation) { //IL_000a: 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) if (Object.op_Implicit((Object)(object)body)) { body.position = position; body.rotation = rotation; } } internal bool Warping(VehicleController car) { if (Object.op_Implicit((Object)(object)car) && protectedUntil.TryGetValue(((NetworkBehaviour)car).NetworkObjectId, out var value)) { return Time.unscaledTime < value; } return false; } private unsafe void BroadcastButton(ulong sender, Vector3 position) { //IL_0029: 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_007d: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: 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_00c2: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)network) || !network.IsServer) { return; } if (sender != network.LocalClientId) { RecallAudio.PlayButton(position); } FastBufferWriter val = default(FastBufferWriter); foreach (ulong connectedClientsId in network.ConnectedClientsIds) { if (connectedClientsId != sender && connectedClientsId != network.LocalClientId) { ((FastBufferWriter)(ref val))..ctor(12, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref position.x, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref position.y, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref position.z, default(ForPrimitives)); network.CustomMessagingManager.SendNamedMessage("achachala.cruiserrecall.button-sound.v1", connectedClientsId, val, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } } } private void ReceiveButtonSound(ulong sender, FastBufferReader reader) { //IL_0042: 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_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)network) && !network.IsServer && sender == 0L && ((FastBufferReader)(ref reader)).Length - ((FastBufferReader)(ref reader)).Position == 12 && ((FastBufferReader)(ref reader)).TryBeginRead(12)) { float num = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref num, default(ForPrimitives)); float num2 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref num2, default(ForPrimitives)); float num3 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref num3, default(ForPrimitives)); if (WarpPacket.Finite(num) && WarpPacket.Finite(num2) && WarpPacket.Finite(num3)) { RecallAudio.PlayButton(new Vector3(num, num2, num3)); } } } private unsafe void Tell(ulong client, string message) { //IL_0070: Unknown result type (might be due to invalid IL or missing references) if (message.Length > 200) { message = message.Substring(0, 197) + "..."; } if (!Object.op_Implicit((Object)(object)network)) { return; } if (client == network.LocalClientId) { Tip(message); return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(512, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe(message, false); network.CustomMessagingManager.SendNamedMessage("achachala.cruiserrecall.feedback.v1", client, val, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } private void ReceiveFeedback(ulong sender, FastBufferReader reader) { if (Object.op_Implicit((Object)(object)network) && !network.IsServer && sender == 0L && ((FastBufferReader)(ref reader)).Length - ((FastBufferReader)(ref reader)).Position <= 512) { string text = default(string); ((FastBufferReader)(ref reader)).ReadValueSafe(ref text, false); Tip(text); } } private static void Tip(string text) { if (Object.op_Implicit((Object)(object)HUDManager.Instance)) { HUDManager.Instance.DisplayTip("Cruiser Recall", text, false, false, "LC_Tip1"); } } } [HarmonyPatch(typeof(GrabbableObject), "ItemActivate")] internal static class RemoteUsePatch { [HarmonyPrefix] private static bool Prefix(GrabbableObject __instance, bool buttonDown) { if (!Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<RemoteMarker>())) { return true; } if (buttonDown) { Plugin.Instance.Activate(__instance); } return false; } } [HarmonyPatch(typeof(VehicleController), "OnCollisionEnter")] internal static class WarpCollisionPatch { [HarmonyPrefix] private static bool Prefix(VehicleController __instance) { return !Plugin.Instance.Warping(__instance); } } [HarmonyPatch(typeof(VehicleController), "CarReactToObstacle")] internal static class WarpObstaclePatch { [HarmonyPrefix] private static bool Prefix(VehicleController __instance, ref bool __result) { if (!Plugin.Instance.Warping(__instance)) { return true; } __result = false; return false; } } internal static class RecallAudio { private static AudioClip button; private static AudioClip teleport; internal static void Load() { button = LoadClip("buttonpress"); teleport = LoadClip("teleport"); } private static AudioClip LoadClip(string name) { using Stream stream = typeof(Plugin).Assembly.GetManifestResourceStream("CruiserRecall." + name + ".pcm"); using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); float[] array = AudioSamples.Decode(memoryStream.ToArray()); AudioClip obj = AudioClip.Create("Cruiser Recall " + name, array.Length, 1, 24000, false); if (!obj.SetData(array, 0)) { throw new InvalidOperationException("Cannot initialize " + name + " audio."); } return obj; } internal static void PlayButton(Vector3 position) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) Play(button, position, 10f); } internal static void PlayTeleport(Vector3 position) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) Play(teleport, position, 35f); } private static void Play(AudioClip clip, Vector3 position, float range) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: 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_0083: Expected O, but got Unknown if (Object.op_Implicit((Object)(object)clip)) { GameObject val = new GameObject("Cruiser Recall sound"); val.transform.position = position; AudioSource obj = val.AddComponent<AudioSource>(); obj.playOnAwake = false; obj.spatialBlend = 1f; obj.rolloffMode = (AudioRolloffMode)1; obj.minDistance = 1f; obj.maxDistance = range; obj.dopplerLevel = 0f; obj.clip = clip; obj.volume = 1f; obj.Play(); Object.Destroy((Object)val, clip.length + 0.1f); } } } internal sealed class RemoteMarker : MonoBehaviour { } internal static class RemoteItem { internal static void Register() { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_028e: Unknown result type (might be due to invalid IL or missing references) //IL_02a2: Unknown result type (might be due to invalid IL or missing references) //IL_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_02da: Unknown result type (might be due to invalid IL or missing references) //IL_040f: Unknown result type (might be due to invalid IL or missing references) //IL_0414: Unknown result type (might be due to invalid IL or missing references) //IL_042a: Unknown result type (might be due to invalid IL or missing references) //IL_042f: Unknown result type (might be due to invalid IL or missing references) //IL_0436: Unknown result type (might be due to invalid IL or missing references) //IL_043b: Unknown result type (might be due to invalid IL or missing references) //IL_04b9: Unknown result type (might be due to invalid IL or missing references) //IL_04c0: Expected O, but got Unknown //IL_04f4: Unknown result type (might be due to invalid IL or missing references) //IL_0503: Unknown result type (might be due to invalid IL or missing references) //IL_0575: Unknown result type (might be due to invalid IL or missing references) //IL_057a: Unknown result type (might be due to invalid IL or missing references) Assembly assembly = ((object)Chainloader.PluginInfos["evaisa.lethallib"].Instance).GetType().Assembly; string text = "achachala.cruiserrecall.Remote.v1"; GameObject prefab = (GameObject)assembly.GetType("LethalLib.Modules.NetworkPrefabs").GetMethod("CreateNetworkPrefab", new Type[1] { typeof(string) }).Invoke(null, new object[1] { text }); uint num = 2166136261u; string text2 = text; foreach (char c in text2) { num = (num ^ c) * 16777619; } typeof(NetworkObject).GetField("GlobalObjectIdHash", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).SetValue(prefab.GetComponent<NetworkObject>(), num); prefab.tag = "PhysicsProp"; prefab.layer = LayerMask.NameToLayer("Props"); Rigidbody val = prefab.AddComponent<Rigidbody>(); val.isKinematic = true; val.useGravity = false; BoxCollider val2 = prefab.AddComponent<BoxCollider>(); val2.size = new Vector3(0.22f, 0.11f, 0.36f); prefab.AddComponent<AudioSource>().playOnAwake = false; prefab.AddComponent<RemoteMarker>(); Shader shader = Shader.Find("HDRP/Lit") ?? Shader.Find("HDRP/Unlit"); if (!Object.op_Implicit((Object)(object)shader)) { throw new InvalidOperationException("Remote model shader unavailable."); } Material material = Mat(new Color(0.065f, 0.075f, 0.065f)); Material material2 = Mat(new Color(0.65f, 0.28f, 0.055f)); Material material3 = Mat(new Color(0.12f, 0.7f, 0.35f)); MeshRenderer mainObjectRenderer = Part("Boxy remote housing", (PrimitiveType)3, Vector3.zero, new Vector3(0.21f, 0.1f, 0.33f), material2); Part("Faceplate", (PrimitiveType)3, new Vector3(0f, 0.054f, 0f), new Vector3(0.18f, 0.012f, 0.28f), material); Part("Recall button", (PrimitiveType)2, new Vector3(0f, 0.071f, -0.045f), new Vector3(0.1f, 0.014f, 0.1f), material3); Part("Display", (PrimitiveType)3, new Vector3(0f, 0.064f, 0.085f), new Vector3(0.12f, 0.012f, 0.055f), material3); Part("Antenna", (PrimitiveType)3, new Vector3(0.065f, 0f, 0.23f), new Vector3(0.018f, 0.018f, 0.16f), material); Item val3 = ScriptableObject.CreateInstance<Item>(); ((Object)val3).name = "CruiserRecallRemoteItem"; val3.itemName = "Cruiser recall remote"; val3.itemId = 847293; val3.spawnPrefab = prefab; val3.creditsWorth = 250; val3.weight = 1.02f; val3.isScrap = false; val3.canBeGrabbedBeforeGameStart = true; val3.disallowUtilitySlot = false; val3.twoHanded = (val3.twoHandedAnimation = false); val3.requiresBattery = false; val3.syncGrabFunction = (val3.syncDiscardFunction = true); val3.highestSalePercentage = 0; val3.grabAnim = (val3.useAnim = (val3.pocketAnim = (val3.throwAnim = ""))); val3.toolTips = new string[1] { "Recall cruiser: [LMB]" }; val3.spawnPositionTypes = new List<ItemGroup>(); val3.meshVariants = Array.Empty<Mesh>(); val3.materialVariants = Array.Empty<Material>(); val3.clinkAudios = Array.Empty<AudioClip>(); val3.positionOffset = new Vector3(0.02f, 0f, 0.01f); val3.rotationOffset = new Vector3(0f, 0f, -15f); val3.restingRotation = Vector3.zero; val3.verticalOffset = 0.06f; val3.allowDroppingAheadOfPlayer = true; using (Stream stream = typeof(Plugin).Assembly.GetManifestResourceStream("CruiserRecall.remote.png")) { byte[] array = new byte[stream.Length]; int num2; for (int j = 0; j < array.Length; j += num2) { num2 = stream.Read(array, j, array.Length - j); if (num2 == 0) { throw new InvalidOperationException("Incomplete remote icon."); } } Texture2D val4 = new Texture2D(2, 2, (TextureFormat)4, false); if (!ImageConversion.LoadImage(val4, array)) { throw new InvalidOperationException("Invalid remote icon."); } val3.itemIcon = Sprite.Create(val4, new Rect(0f, 0f, (float)((Texture)val4).width, (float)((Texture)val4).height), new Vector2(0.5f, 0.5f), 256f); } PhysicsProp val5 = prefab.AddComponent<PhysicsProp>(); ((GrabbableObject)val5).itemProperties = val3; ((GrabbableObject)val5).grabbable = (((GrabbableObject)val5).grabbableToEnemies = true); ((GrabbableObject)val5).mainObjectRenderer = mainObjectRenderer; ((GrabbableObject)val5).propBody = val; ((GrabbableObject)val5).propColliders = (Collider[])(object)new Collider[1] { (Collider)val2 }; ((GrabbableObject)val5).originalScale = Vector3.one; ((GrabbableObject)val5).useCooldown = 0.1f; assembly.GetType("LethalLib.Modules.Items").GetMethod("RegisterShopItem", new Type[2] { typeof(Item), typeof(int) }).Invoke(null, new object[2] { val3, 250 }); Material Mat(Color color) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0012: 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) Material val6 = new Material(shader); val6.SetColor("_BaseColor", color); if (val6.HasProperty("_UnlitColor")) { val6.SetColor("_UnlitColor", color); } return val6; } MeshRenderer Part(string label, PrimitiveType type, Vector3 pos, Vector3 scale, Material sharedMaterial) { //IL_0000: 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_0037: Unknown result type (might be due to invalid IL or missing references) GameObject obj = GameObject.CreatePrimitive(type); ((Object)obj).name = label; obj.transform.SetParent(prefab.transform, false); obj.transform.localPosition = pos; obj.transform.localScale = scale; obj.layer = prefab.layer; Object.Destroy((Object)(object)obj.GetComponent<Collider>()); MeshRenderer component = obj.GetComponent<MeshRenderer>(); ((Renderer)component).sharedMaterial = sharedMaterial; return component; } } } internal sealed class CargoPose { internal ulong Id; internal float X; internal float Y; internal float Z; internal float Qx; internal float Qy; internal float Qz; internal float Qw = 1f; } internal sealed class WarpPacket { internal const int Protocol = 1; internal const int MaxCargo = 1024; internal const int Header = 32; internal const int CargoSize = 36; internal ulong Car; internal uint Revision; internal float X; internal float Y; internal float Z; internal float Yaw; internal CargoPose[] Cargo = Array.Empty<CargoPose>(); internal byte[] Encode() { using MemoryStream memoryStream = new MemoryStream(); using BinaryWriter binaryWriter = new BinaryWriter(memoryStream); binaryWriter.Write(1); binaryWriter.Write(Car); binaryWriter.Write(Revision); binaryWriter.Write(X); binaryWriter.Write(Y); binaryWriter.Write(Z); binaryWriter.Write(Yaw); binaryWriter.Write(Cargo.Length); CargoPose[] cargo = Cargo; foreach (CargoPose cargoPose in cargo) { binaryWriter.Write(cargoPose.Id); binaryWriter.Write(cargoPose.X); binaryWriter.Write(cargoPose.Y); binaryWriter.Write(cargoPose.Z); binaryWriter.Write(cargoPose.Qx); binaryWriter.Write(cargoPose.Qy); binaryWriter.Write(cargoPose.Qz); binaryWriter.Write(cargoPose.Qw); } return memoryStream.ToArray(); } internal static bool Finite(float x) { if (!float.IsNaN(x)) { return !float.IsInfinity(x); } return false; } internal static bool TryDecode(byte[] data, out WarpPacket state) { state = null; if (data == null || data.Length < 36) { return false; } using BinaryReader binaryReader = new BinaryReader(new MemoryStream(data, writable: false)); if (binaryReader.ReadInt32() != 1) { return false; } WarpPacket warpPacket = new WarpPacket { Car = binaryReader.ReadUInt64(), Revision = binaryReader.ReadUInt32(), X = binaryReader.ReadSingle(), Y = binaryReader.ReadSingle(), Z = binaryReader.ReadSingle(), Yaw = binaryReader.ReadSingle() }; int num = binaryReader.ReadInt32(); if (warpPacket.Revision == 0 || num < 0 || num > 1024 || data.Length != 36 + num * 36 || !Finite(warpPacket.X) || !Finite(warpPacket.Y) || !Finite(warpPacket.Z) || !Finite(warpPacket.Yaw)) { return false; } warpPacket.Cargo = new CargoPose[num]; HashSet<ulong> hashSet = new HashSet<ulong>(); for (int i = 0; i < num; i++) { CargoPose cargoPose = new CargoPose { Id = binaryReader.ReadUInt64(), X = binaryReader.ReadSingle(), Y = binaryReader.ReadSingle(), Z = binaryReader.ReadSingle(), Qx = binaryReader.ReadSingle(), Qy = binaryReader.ReadSingle(), Qz = binaryReader.ReadSingle(), Qw = binaryReader.ReadSingle() }; if (!hashSet.Add(cargoPose.Id) || cargoPose.Id == warpPacket.Car) { return false; } float[] array = new float[7] { cargoPose.X, cargoPose.Y, cargoPose.Z, cargoPose.Qx, cargoPose.Qy, cargoPose.Qz, cargoPose.Qw }; for (int j = 0; j < array.Length; j++) { if (!Finite(array[j])) { return false; } } float num2 = cargoPose.Qx * cargoPose.Qx + cargoPose.Qy * cargoPose.Qy + cargoPose.Qz * cargoPose.Qz + cargoPose.Qw * cargoPose.Qw; if (num2 < 0.9f || num2 > 1.1f) { return false; } warpPacket.Cargo[i] = cargoPose; } state = warpPacket; return true; } } internal static class RecallRules { internal const float SpawnLift = 0.6f; internal static bool CanUse(bool alive, bool outside, bool landed, bool moving, bool holding) { return alive && outside && landed && !moving && holding; } internal static string PlacementMessage(string reason) { if (reason.IndexOf("player", StringComparison.OrdinalIgnoreCase) >= 0) { return "Someone is in the landing area."; } if (reason.IndexOf("cargo", StringComparison.OrdinalIgnoreCase) >= 0) { return "Cargo won't fit there."; } if (reason.IndexOf("ground", StringComparison.OrdinalIgnoreCase) >= 0 || reason.IndexOf("terrain", StringComparison.OrdinalIgnoreCase) >= 0) { return "No suitable ground ahead."; } return "Not enough room ahead."; } internal static bool DetectionOnlyName(string name) { if (string.IsNullOrEmpty(name)) { return false; } return name.Replace(" ", "").Replace("_", "").Replace("-", "") .IndexOf("lineofsight", StringComparison.OrdinalIgnoreCase) >= 0; } internal static bool PenetrationBlocks(bool intersects, float depth) { if (intersects) { if (WarpPacket.Finite(depth)) { return depth > 0.02f; } return true; } return false; } internal static float CentreDistance(float halfLength, int attempt) { return 1.5f + halfLength + (float)attempt * 1.5f; } internal static bool SlopeAllowed(float normalY) { if (WarpPacket.Finite(normalY)) { return normalY >= 0.85f; } return false; } internal static bool Supported(float min, float max, float playerHeight) { if (WarpPacket.Finite(min) && WarpPacket.Finite(max) && max >= min && max - min <= 2.5f) { return Math.Abs(max - playerHeight) <= 3f; } return false; } } internal sealed class RecallCooldown { internal const int Seconds = 60; private double readyAt; internal void Start(double now) { readyAt = now + 60.0; } internal int Remaining(double now) { return (int)Math.Ceiling(Math.Max(0.0, readyAt - now)); } internal void Reset() { readyAt = 0.0; } } internal static class AudioSamples { internal static float[] Decode(byte[] bytes) { if (bytes.Length % 2 != 0) { throw new ArgumentException("Invalid PCM length."); } float[] array = new float[bytes.Length / 2]; for (int i = 0; i < array.Length; i++) { array[i] = (float)(short)(bytes[i * 2] | (bytes[i * 2 + 1] << 8)) / 32768f; } return array; } } }