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 CartTrainLocomotives v0.3.4
plugins/CartTrainLocomotives/CartTrainLocomotives.dll
Decompiled a month agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Rendering; [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("CartTrainLocomotives")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("CartTrainLocomotives")] [assembly: AssemblyTitle("CartTrainLocomotives")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.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 CartTrainLocomotives { [BepInPlugin("CandyKane.CartTrainLocomotives", "CartTrain Locomotives", "0.3.4")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "CandyKane.CartTrainLocomotives"; public const string PluginName = "CartTrain Locomotives"; public const string PluginVersion = "0.3.4"; internal static ManualLogSource Log; internal static ConfigEntry<float> SnapDistance; internal static ConfigEntry<float> TowGap; internal static ConfigEntry<float> GrabStrength; internal static ConfigEntry<float> GrabDamping; internal static ConfigEntry<float> MaxGrabAcceleration; internal static ConfigEntry<float> MaxVerticalAcceleration; internal static ConfigEntry<float> CenteringStrength; internal static ConfigEntry<float> CenteringDamping; internal static ConfigEntry<float> MaxCenteringAcceleration; internal static ConfigEntry<float> YawAlignmentStrength; internal static ConfigEntry<float> MaxYawAcceleration; internal static ConfigEntry<float> PathSampleSpacing; internal static ConfigEntry<float> PathGuideStrength; internal static ConfigEntry<float> MaxPathGuideVelocityChange; internal static ConfigEntry<float> PoweredCatchupGain; internal static ConfigEntry<float> MaxPoweredCatchupSpeed; internal static ConfigEntry<float> MaxPoweredVelocityChange; internal static ConfigEntry<bool> IgnoreCoupledCollisions; internal static ConfigEntry<float> VehicleRearPadding; internal static ConfigEntry<float> CartEndPadding; internal static ConfigEntry<float> MaxSnapAngle; internal static ConfigEntry<float> EmergencyBreakawayDistance; internal static ConfigEntry<float> CouplingGraceSeconds; internal static ConfigEntry<KeyCode> DetachKey; internal static ConfigEntry<bool> DebugLogging; internal static ConfigEntry<bool> ShowConnectionBeam; internal static ConfigEntry<float> BeamWidth; private Harmony _harmony; private void Awake() { //IL_03ce: Unknown result type (might be due to invalid IL or missing references) //IL_03d8: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; SnapDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Coupling", "ManualAttachDistance", 1.5f, "Maximum rear-of-vehicle to nearest cart-end distance when Shift+X is pressed while holding either object."); TowGap = ((BaseUnityPlugin)this).Config.Bind<float>("Coupling", "TowGap", 0.18f, "Extra gap between the vehicle rear grab point and the cart handle/end."); MaxSnapAngle = ((BaseUnityPlugin)this).Config.Bind<float>("Coupling", "MaximumSnapAngle", 85f, "Maximum alignment error allowed when snapping. Either end of the cart may attach."); EmergencyBreakawayDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Coupling", "EmergencyBreakawayDistance", 40f, "Safety-only distance at which a coupled cart is released. Normal driving should never reach this."); CouplingGraceSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Coupling", "CouplingGraceSeconds", 2.5f, "Seconds after coupling during which distance-based emergency breakaway is disabled."); VehicleRearPadding = ((BaseUnityPlugin)this).Config.Bind<float>("Anchors", "VehicleRearPadding", 0.1f, "Moves the cached vehicle rear anchor farther behind the vehicle."); CartEndPadding = ((BaseUnityPlugin)this).Config.Bind<float>("Anchors", "CartEndPadding", 0.08f, "Moves the cached cart coupling end outward."); GrabStrength = ((BaseUnityPlugin)this).Config.Bind<float>("Physics", "GrabStrength", 18f, "Spring acceleration pulling the cart's selected end toward the vehicle's rear grab point."); GrabDamping = ((BaseUnityPlugin)this).Config.Bind<float>("Physics", "GrabDamping", 5.5f, "Damping against relative velocity at the virtual hand/cart handle connection."); MaxGrabAcceleration = ((BaseUnityPlugin)this).Config.Bind<float>("Physics", "MaximumGrabAcceleration", 28f, "Maximum horizontal acceleration applied to the cart by the virtual hand."); MaxVerticalAcceleration = ((BaseUnityPlugin)this).Config.Bind<float>("Physics", "MaximumVerticalAcceleration", 1.5f, "Maximum vertical correction. Kept intentionally low so the tow point cannot lift the cart or vehicle into ceilings."); CenteringStrength = ((BaseUnityPlugin)this).Config.Bind<float>("Physics", "BehindCenteringStrength", 20f, "Sideways spring strength that keeps the first cart centered behind the Scout/Hauler instead of swinging into walls."); CenteringDamping = ((BaseUnityPlugin)this).Config.Bind<float>("Physics", "BehindCenteringDamping", 7f, "Sideways damping used by the behind-centering controller."); MaxCenteringAcceleration = ((BaseUnityPlugin)this).Config.Bind<float>("Physics", "MaximumCenteringAcceleration", 20f, "Maximum sideways acceleration used to keep the first cart behind the locomotive."); YawAlignmentStrength = ((BaseUnityPlugin)this).Config.Bind<float>("Physics", "YawAlignmentStrength", 5f, "Gentle yaw-only alignment that encourages the cart to point the same direction as the Scout/Hauler without rigidly locking it."); MaxYawAcceleration = ((BaseUnityPlugin)this).Config.Bind<float>("Physics", "MaximumYawAcceleration", 8f, "Maximum yaw angular acceleration used by the soft alignment controller."); PathSampleSpacing = ((BaseUnityPlugin)this).Config.Bind<float>("Physics", "PathSampleSpacing", 0.1f, "Distance the locomotive rear must travel before another breadcrumb point is recorded for corner-following."); PathGuideStrength = ((BaseUnityPlugin)this).Config.Bind<float>("Physics", "PathGuideStrength", 4.5f, "Velocity guidance toward the locomotive's recent rear path. Higher values make the first cart follow corners more tightly."); MaxPathGuideVelocityChange = ((BaseUnityPlugin)this).Config.Bind<float>("Physics", "MaximumPathGuideVelocityChangePerTick", 0.65f, "Maximum horizontal velocity correction per physics tick used by the breadcrumb path guide."); PoweredCatchupGain = ((BaseUnityPlugin)this).Config.Bind<float>("Physics", "PoweredCatchupGain", 4f, "Extra forward catch-up speed per meter the first cart falls behind. This assist is mass-independent so heavy cargo cannot anchor the locomotive."); MaxPoweredCatchupSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Physics", "MaximumPoweredCatchupSpeed", 8f, "Maximum extra horizontal catch-up speed added to the first cart when it lags behind the Scout/Hauler."); MaxPoweredVelocityChange = ((BaseUnityPlugin)this).Config.Bind<float>("Physics", "MaximumPoweredVelocityChangePerTick", 0.75f, "Maximum horizontal velocity change applied to the first cart each physics tick by the powered tow assist."); IgnoreCoupledCollisions = ((BaseUnityPlugin)this).Config.Bind<bool>("Physics", "IgnoreCoupledVehicleCartCollisions", true, "Ignore collisions between the connected Scout/Hauler and first cart while attached, preventing the loaded cart from physically braking or wedging the locomotive."); DetachKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "DetachKey", (KeyCode)120, "Detach key. Hold Left Shift while pressing this key near a coupled locomotive/cart. This prevents accidental detaches from normal gameplay inputs."); DebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "DebugLogging", false, "Enable verbose logging."); ShowConnectionBeam = ((BaseUnityPlugin)this).Config.Bind<bool>("Visual", "ShowConnectionBeam", true, "Show a visible beam between the Scout/Hauler rear tow point and the connected cart end."); BeamWidth = ((BaseUnityPlugin)this).Config.Bind<float>("Visual", "ConnectionBeamWidth", 0.05f, "Width of the visible tow/hand-hold beam."); _harmony = new Harmony("CandyKane.CartTrainLocomotives"); _harmony.PatchAll(); ((Component)this).gameObject.AddComponent<LocomotiveManager>(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"CartTrain Locomotives 0.3.4 loaded. Optimized event-driven discovery enabled."); } } [HarmonyPatch(typeof(PhysGrabCart), "Start")] internal static class CartStartPatch { [HarmonyPostfix] private static void Postfix(PhysGrabCart __instance) { LocomotiveManager.RegisterCart(__instance); } } [HarmonyPatch(typeof(PhysGrabObject), "Start")] internal static class PhysGrabObjectStartPatch { [HarmonyPostfix] private static void Postfix(PhysGrabObject __instance) { LocomotiveManager.RegisterPotentialVehicle(__instance); } } internal sealed class LocomotiveManager : MonoBehaviour { private sealed class VehicleState { private sealed class ColliderPair { internal readonly Collider A; internal readonly Collider B; internal ColliderPair(Collider a, Collider b) { A = a; B = b; } } internal readonly PhysGrabObject Vehicle; internal readonly Rigidbody Body; internal readonly string DisplayName; internal readonly float HalfLength; internal PhysGrabCart? Cart; internal Rigidbody? CartBody; internal float CartEndSign = 1f; internal float CoupledAt; private GameObject? _beamObject; private LineRenderer? _beam; private static Material? _beamMaterial; private readonly List<ColliderPair> _ignoredCollisionPairs = new List<ColliderPair>(); private readonly List<Vector3> _rearPath = new List<Vector3>(); internal Vector3 RearAnchor => ((Component)Vehicle).transform.position - ((Component)Vehicle).transform.forward * (HalfLength + Plugin.VehicleRearPadding.Value); internal VehicleState(PhysGrabObject vehicle, Rigidbody body, string prefabName) { Vehicle = vehicle; Body = body; DisplayName = (prefabName.EndsWith(" Small", StringComparison.Ordinal) ? "Scout" : "Hauler"); HalfLength = ComputeHalfLength(((Component)vehicle).gameObject, ((Component)vehicle).transform, 0.45f); } internal void ResetRearPath() { _rearPath.Clear(); } internal void RecordRearPath(Vector3 rearPoint) { //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_001f: 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) rearPoint.y = 0f; if (_rearPath.Count == 0) { _rearPath.Add(rearPoint); } else if (!(Vector3.Distance(_rearPath[_rearPath.Count - 1], rearPoint) < Mathf.Max(0.02f, Plugin.PathSampleSpacing.Value))) { _rearPath.Add(rearPoint); if (_rearPath.Count > 160) { _rearPath.RemoveAt(0); } } } internal void GetRearPathTarget(Vector3 currentRear, Vector3 fallbackForward, float distanceBack, out Vector3 target, out Vector3 tangent) { //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_0022: 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_0067: 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_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_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_004d: 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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0082: 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_0089: 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_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_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: 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) //IL_00d9: 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_0100: 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_00b7: 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_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: 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_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_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012a: 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_0137: 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_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0143: 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_014b: Unknown result type (might be due to invalid IL or missing references) currentRear.y = 0f; fallbackForward = Flat(fallbackForward); if (((Vector3)(ref fallbackForward)).sqrMagnitude < 0.0001f) { fallbackForward = Vector3.forward; } ((Vector3)(ref fallbackForward)).Normalize(); if (_rearPath.Count < 2) { target = currentRear - fallbackForward * distanceBack; tangent = fallbackForward; return; } float num = Mathf.Max(0.05f, distanceBack); Vector3 val = currentRear; for (int num2 = _rearPath.Count - 1; num2 >= 0; num2--) { Vector3 val2 = _rearPath[num2]; Vector3 val3 = val - val2; float magnitude = ((Vector3)(ref val3)).magnitude; if (magnitude > 0.0001f) { if (num <= magnitude) { float num3 = num / magnitude; target = Vector3.Lerp(val, val2, num3); tangent = val3 / magnitude; return; } num -= magnitude; } val = val2; } Vector3 val4 = _rearPath[0]; Vector3 val5 = Flat(((_rearPath.Count > 1) ? _rearPath[1] : currentRear) - val4); if (((Vector3)(ref val5)).sqrMagnitude < 0.0001f) { val5 = fallbackForward; } else { ((Vector3)(ref val5)).Normalize(); } target = val4 - val5 * num; tangent = val5; } internal void EnableCoupledCollisionIgnore(PhysGrabCart cart) { RestoreCoupledCollisions(); if (!Plugin.IgnoreCoupledCollisions.Value || (Object)(object)cart == (Object)null) { return; } Collider[] componentsInChildren = ((Component)Vehicle).GetComponentsInChildren<Collider>(true); Collider[] componentsInChildren2 = ((Component)cart).GetComponentsInChildren<Collider>(true); Collider[] array = componentsInChildren; foreach (Collider val in array) { if ((Object)(object)val == (Object)null) { continue; } Collider[] array2 = componentsInChildren2; foreach (Collider val2 in array2) { if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val == (Object)(object)val2)) { Physics.IgnoreCollision(val, val2, true); _ignoredCollisionPairs.Add(new ColliderPair(val, val2)); } } } if (Plugin.DebugLogging.Value) { Plugin.Log.LogDebug((object)$"Ignoring {_ignoredCollisionPairs.Count} vehicle/cart collider pair(s) for {DisplayName} while coupled."); } } internal void RestoreCoupledCollisions() { foreach (ColliderPair ignoredCollisionPair in _ignoredCollisionPairs) { if ((Object)(object)ignoredCollisionPair.A != (Object)null && (Object)(object)ignoredCollisionPair.B != (Object)null) { Physics.IgnoreCollision(ignoredCollisionPair.A, ignoredCollisionPair.B, false); } } _ignoredCollisionPairs.Clear(); } internal void EnsureBeam() { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Expected O, but got Unknown if ((Object)(object)_beam != (Object)null) { ((Renderer)_beam).enabled = Plugin.ShowConnectionBeam.Value && (Object)(object)Cart != (Object)null; return; } _beamObject = new GameObject($"CartTrainBeam_{DisplayName}_{((Object)Vehicle).GetInstanceID()}"); _beam = _beamObject.AddComponent<LineRenderer>(); _beam.positionCount = 2; _beam.useWorldSpace = true; ((Renderer)_beam).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)_beam).receiveShadows = false; ((Renderer)_beam).motionVectorGenerationMode = (MotionVectorGenerationMode)2; _beam.textureMode = (LineTextureMode)0; _beam.alignment = (LineAlignment)0; _beam.numCapVertices = 8; _beam.numCornerVertices = 4; _beam.startWidth = Plugin.BeamWidth.Value; _beam.endWidth = Plugin.BeamWidth.Value * 0.7f; if ((Object)(object)_beamMaterial == (Object)null) { Shader val = Shader.Find("Sprites/Default"); if ((Object)(object)val == (Object)null) { val = Shader.Find("Unlit/Color"); } if ((Object)(object)val != (Object)null) { _beamMaterial = new Material(val); } } if ((Object)(object)_beamMaterial != (Object)null) { ((Renderer)_beam).sharedMaterial = _beamMaterial; } Color startColor = default(Color); ((Color)(ref startColor))..ctor(0.55f, 0.95f, 1f, 0.95f); Color endColor = default(Color); ((Color)(ref endColor))..ctor(0.95f, 1f, 1f, 0.55f); _beam.startColor = startColor; _beam.endColor = endColor; ((Renderer)_beam).enabled = Plugin.ShowConnectionBeam.Value && (Object)(object)Cart != (Object)null; } internal void DisableBeam() { if ((Object)(object)_beam != (Object)null) { ((Renderer)_beam).enabled = false; } } internal void DestroyBeam() { RestoreCoupledCollisions(); if ((Object)(object)_beamObject != (Object)null) { Object.Destroy((Object)(object)_beamObject); _beamObject = null; _beam = null; } } internal void UpdateBeam() { //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: 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_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: 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_00d0: 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_00e7: 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_00e9: 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_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_beam == (Object)null)) { if (!Plugin.ShowConnectionBeam.Value || (Object)(object)Cart == (Object)null) { ((Renderer)_beam).enabled = false; return; } ((Renderer)_beam).enabled = true; float num = 0.92f + Mathf.Sin(Time.time * 8f) * 0.08f; _beam.startWidth = Plugin.BeamWidth.Value * num; _beam.endWidth = Plugin.BeamWidth.Value * 0.7f * num; Vector3 val = RearAnchor - ((Component)Vehicle).transform.forward * Plugin.TowGap.Value; Vector3 val2 = CartEndAnchor(Cart, CartEndSign); Vector3 val3 = Vector3.up * 0.06f; _beam.SetPosition(0, val + val3); _beam.SetPosition(1, val2 + val3 * 0.5f); } } } private static LocomotiveManager? _instance; private static readonly HashSet<PhysGrabCart> Carts = new HashSet<PhysGrabCart>(); private static readonly HashSet<PhysGrabCart> ClaimedFollowers = new HashSet<PhysGrabCart>(); private static readonly Dictionary<PhysGrabCart, float> CartHalfLengths = new Dictionary<PhysGrabCart, float>(); private static readonly HashSet<int> RejectedCartIds = new HashSet<int>(); private const string SupportedCartName = "Item Cart Medium"; private readonly Dictionary<int, VehicleState> _vehicles = new Dictionary<int, VehicleState>(); private float _nextFallbackScan; private float _nextCleanup; private void Awake() { _instance = this; } internal static void RegisterCart(PhysGrabCart cart) { if ((Object)(object)cart == (Object)null) { return; } if (!string.Equals(CleanName(((Object)cart).name), "Item Cart Medium", StringComparison.Ordinal)) { int instanceID = ((Object)((Component)cart).gameObject).GetInstanceID(); if (Plugin.DebugLogging.Value && RejectedCartIds.Add(instanceID)) { Plugin.Log.LogDebug((object)$"Ignoring unsupported PhysGrabCart '{((Object)cart).name}' ({instanceID})."); } } else { Carts.Add(cart); if (!CartHalfLengths.ContainsKey(cart)) { CartHalfLengths[cart] = ComputeHalfLength(((Component)cart).gameObject, ((Component)cart).transform, 0.35f); } } } internal static void RegisterPotentialVehicle(PhysGrabObject pgo) { if (!((Object)(object)_instance == (Object)null) && !((Object)(object)pgo == (Object)null)) { _instance.TryRegisterVehicle(pgo); } } private void Update() { //IL_006e: Unknown result type (might be due to invalid IL or missing references) if (!IsAuthority()) { return; } if (Time.unscaledTime >= _nextFallbackScan) { _nextFallbackScan = Time.unscaledTime + 5f; if (_vehicles.Count == 0) { FallbackDiscover(); } } if (Time.unscaledTime >= _nextCleanup) { _nextCleanup = Time.unscaledTime + 3f; Cleanup(); } if (Input.GetKey((KeyCode)304) && Input.GetKeyDown(Plugin.DetachKey.Value)) { TryToggleHeldConnection(); } UpdateVisuals(); } private void FixedUpdate() { if (!IsAuthority()) { return; } foreach (VehicleState value in _vehicles.Values) { if (!((Object)(object)value.Vehicle == (Object)null) && !((Object)(object)value.Body == (Object)null) && (Object)(object)value.Cart != (Object)null) { DriveFollower(value); } } } private void TryRegisterVehicle(PhysGrabObject pgo) { string text = CleanName(((Object)pgo).name); if (text != "Item Vehicle Semiscooter" && text != "Item Vehicle Semiscooter Small") { return; } int instanceID = ((Object)((Component)pgo).gameObject).GetInstanceID(); if (!_vehicles.ContainsKey(instanceID)) { Rigidbody val = (((Object)(object)pgo.rb != (Object)null) ? pgo.rb : ((Component)pgo).GetComponent<Rigidbody>()); if (!((Object)(object)val == (Object)null)) { _vehicles[instanceID] = new VehicleState(pgo, val, text); Plugin.Log.LogInfo((object)$"Tracking locomotive: {text} ({instanceID})"); } } } private void FallbackDiscover() { PhysGrabObject[] array = Object.FindObjectsOfType<PhysGrabObject>(); foreach (PhysGrabObject pgo in array) { TryRegisterVehicle(pgo); } PhysGrabCart[] array2 = Object.FindObjectsOfType<PhysGrabCart>(); for (int i = 0; i < array2.Length; i++) { RegisterCart(array2[i]); } } private void Cleanup() { Carts.RemoveWhere((PhysGrabCart c) => (Object)(object)c == (Object)null || !IsSupportedCart(c)); ClaimedFollowers.RemoveWhere((PhysGrabCart c) => (Object)(object)c == (Object)null); Dictionary<PhysGrabCart, float> dictionary = new Dictionary<PhysGrabCart, float>(); foreach (KeyValuePair<PhysGrabCart, float> cartHalfLength in CartHalfLengths) { if ((Object)(object)cartHalfLength.Key != (Object)null) { dictionary[cartHalfLength.Key] = cartHalfLength.Value; } } CartHalfLengths.Clear(); foreach (KeyValuePair<PhysGrabCart, float> item in dictionary) { CartHalfLengths[item.Key] = item.Value; } List<int> list = new List<int>(); foreach (KeyValuePair<int, VehicleState> vehicle in _vehicles) { if ((Object)(object)vehicle.Value.Vehicle == (Object)null) { list.Add(vehicle.Key); } } foreach (int item2 in list) { if (_vehicles.TryGetValue(item2, out VehicleState value)) { value.DestroyBeam(); } _vehicles.Remove(item2); } } private void UpdateVisuals() { foreach (VehicleState value in _vehicles.Values) { value.UpdateBeam(); } } private void TryToggleHeldConnection() { //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) foreach (VehicleState value in _vehicles.Values) { if (!((Object)(object)value.Cart == (Object)null) && (IsHeldByLocalPlayer(value.Vehicle) || IsHeldByLocalPlayer(GetCartGrabObject(value.Cart)))) { Detach(value, "manual held-object Shift+" + ((object)Plugin.DetachKey.Value/*cast due to .constrained prefix*/).ToString()); return; } } foreach (VehicleState value2 in _vehicles.Values) { if (IsHeldByLocalPlayer(value2.Vehicle) && TryAttachNearestCartToVehicle(value2)) { return; } } foreach (PhysGrabCart cart in Carts) { if (IsSupportedCart(cart) && IsHeldByLocalPlayer(GetCartGrabObject(cart)) && TryAttachHeldCartToNearestVehicle(cart)) { return; } } if (Plugin.DebugLogging.Value) { Plugin.Log.LogDebug((object)"Shift+X pressed, but no held Scout/Hauler or supported large cart was in attach range."); } } private static bool TryAttachNearestCartToVehicle(VehicleState state) { //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_005b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)state.Cart != (Object)null) { return false; } Vector3 rearAnchor = state.RearAnchor; PhysGrabCart val = null; float num = Plugin.SnapDistance.Value; float cartEndSign = 1f; foreach (PhysGrabCart cart in Carts) { if (IsSupportedCart(cart) && !ClaimedFollowers.Contains(cart) && TryGetAttachCandidate(state, cart, rearAnchor, out var distance, out var sign) && !(distance > num)) { val = cart; num = distance; cartEndSign = sign; } } if ((Object)(object)val == (Object)null) { return false; } Attach(state, val, cartEndSign); return true; } private bool TryAttachHeldCartToNearestVehicle(PhysGrabCart cart) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) if (ClaimedFollowers.Contains(cart)) { return false; } VehicleState vehicleState = null; float num = Plugin.SnapDistance.Value; float cartEndSign = 1f; foreach (VehicleState value in _vehicles.Values) { if (!((Object)(object)value.Cart != (Object)null) && !((Object)(object)value.Vehicle == (Object)null)) { Vector3 rearAnchor = value.RearAnchor; if (TryGetAttachCandidate(value, cart, rearAnchor, out var distance, out var sign) && !(distance > num)) { vehicleState = value; num = distance; cartEndSign = sign; } } } if (vehicleState == null) { return false; } Attach(vehicleState, cart, cartEndSign); return true; } private static bool TryGetAttachCandidate(VehicleState state, PhysGrabCart cart, Vector3 rear, out float distance, out float sign) { //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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0059: 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_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_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_00de: Unknown result type (might be due to invalid IL or missing references) distance = float.MaxValue; sign = 1f; if ((Object)(object)((Component)cart).GetComponent<Rigidbody>() == (Object)null) { return false; } float cartHalfLength = GetCartHalfLength(cart); Vector3 val = ((Component)cart).transform.position + ((Component)cart).transform.forward * (cartHalfLength + Plugin.CartEndPadding.Value); Vector3 val2 = ((Component)cart).transform.position - ((Component)cart).transform.forward * (cartHalfLength + Plugin.CartEndPadding.Value); float num = Vector3.Distance(rear, val); float num2 = Vector3.Distance(rear, val2); sign = ((num <= num2) ? 1f : (-1f)); distance = Mathf.Min(num, num2); Vector3 val3 = Flat(((Component)cart).transform.forward * sign); return Vector3.Angle(Flat(((Component)state.Vehicle).transform.forward), val3) <= Plugin.MaxSnapAngle.Value; } private static PhysGrabObject? GetCartGrabObject(PhysGrabCart cart) { if ((Object)(object)cart == (Object)null) { return null; } PhysGrabObject component = ((Component)cart).GetComponent<PhysGrabObject>(); if ((Object)(object)component != (Object)null) { return component; } component = ((Component)cart).GetComponentInParent<PhysGrabObject>(); if ((Object)(object)component != (Object)null) { return component; } return ((Component)cart).GetComponentInChildren<PhysGrabObject>(); } private static bool IsHeldByLocalPlayer(PhysGrabObject? pgo) { if ((Object)(object)pgo == (Object)null) { return false; } try { Type type = ((object)pgo).GetType(); FieldInfo fieldInfo = AccessTools.Field(type, "grabbedLocal") ?? AccessTools.Field(type, "isGrabbedLocal"); if (fieldInfo != null && fieldInfo.FieldType == typeof(bool)) { return (bool)fieldInfo.GetValue(pgo); } PropertyInfo propertyInfo = AccessTools.Property(type, "grabbedLocal") ?? AccessTools.Property(type, "isGrabbedLocal"); if (propertyInfo != null && propertyInfo.PropertyType == typeof(bool)) { return (bool)propertyInfo.GetValue(pgo, null); } } catch (Exception ex) { if (Plugin.DebugLogging.Value) { Plugin.Log.LogDebug((object)("Could not read local grab state for " + ((Object)pgo).name + ": " + ex.Message)); } } return false; } private static void Attach(VehicleState state, PhysGrabCart cart, float cartEndSign) { if (IsSupportedCart(cart)) { Rigidbody component = ((Component)cart).GetComponent<Rigidbody>(); if (!((Object)(object)component == (Object)null)) { state.Cart = cart; state.CartBody = component; state.CartEndSign = cartEndSign; state.CoupledAt = Time.time; state.ResetRearPath(); component.WakeUp(); state.EnableCoupledCollisionIgnore(cart); state.EnsureBeam(); ClaimedFollowers.Add(cart); Plugin.Log.LogInfo((object)$"Coupled {state.DisplayName} -> {((Object)cart).name} (end sign {cartEndSign:+0;-0})."); } } } private static void Detach(VehicleState state, string reason = "unspecified") { if ((Object)(object)state.Cart != (Object)null) { PhysGrabCart cart = state.Cart; ClaimedFollowers.Remove(cart); state.RestoreCoupledCollisions(); Plugin.Log.LogInfo((object)("Detached " + state.DisplayName + " -> " + ((Object)cart).name + " (reason: " + reason + ")")); } state.Cart = null; state.CartBody = null; state.DisableBeam(); state.CartEndSign = 1f; state.CoupledAt = 0f; state.ResetRearPath(); } private static void DriveFollower(VehicleState state) { //IL_009c: 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_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_0138: 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_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015c: 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_0162: 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_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_0248: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_0250: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_0287: 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_028f: Unknown result type (might be due to invalid IL or missing references) //IL_02a7: 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_02ae: Unknown result type (might be due to invalid IL or missing references) //IL_02b3: Unknown result type (might be due to invalid IL or missing references) //IL_02b7: Unknown result type (might be due to invalid IL or missing references) //IL_02bc: Unknown result type (might be due to invalid IL or missing references) //IL_02be: Unknown result type (might be due to invalid IL or missing references) //IL_02c1: 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_02d2: Unknown result type (might be due to invalid IL or missing references) //IL_02d4: Unknown result type (might be due to invalid IL or missing references) //IL_02e3: 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_02ee: Unknown result type (might be due to invalid IL or missing references) //IL_02f3: Unknown result type (might be due to invalid IL or missing references) //IL_0334: Unknown result type (might be due to invalid IL or missing references) //IL_0338: 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_034f: Unknown result type (might be due to invalid IL or missing references) //IL_0359: Unknown result type (might be due to invalid IL or missing references) //IL_035e: Unknown result type (might be due to invalid IL or missing references) //IL_0360: Unknown result type (might be due to invalid IL or missing references) //IL_036c: Unknown result type (might be due to invalid IL or missing references) //IL_0371: Unknown result type (might be due to invalid IL or missing references) //IL_0374: Unknown result type (might be due to invalid IL or missing references) //IL_037c: Unknown result type (might be due to invalid IL or missing references) //IL_037e: Unknown result type (might be due to invalid IL or missing references) //IL_03b2: Unknown result type (might be due to invalid IL or missing references) //IL_03b7: Unknown result type (might be due to invalid IL or missing references) //IL_03bc: Unknown result type (might be due to invalid IL or missing references) //IL_03c7: Unknown result type (might be due to invalid IL or missing references) //IL_03ce: Unknown result type (might be due to invalid IL or missing references) //IL_03d4: Unknown result type (might be due to invalid IL or missing references) //IL_03d9: Unknown result type (might be due to invalid IL or missing references) //IL_03de: Unknown result type (might be due to invalid IL or missing references) //IL_03e0: Unknown result type (might be due to invalid IL or missing references) //IL_03e2: Unknown result type (might be due to invalid IL or missing references) //IL_03e7: 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_03f5: Unknown result type (might be due to invalid IL or missing references) //IL_03fa: Unknown result type (might be due to invalid IL or missing references) //IL_03fd: Unknown result type (might be due to invalid IL or missing references) //IL_0410: Unknown result type (might be due to invalid IL or missing references) //IL_041c: Unknown result type (might be due to invalid IL or missing references) //IL_0421: Unknown result type (might be due to invalid IL or missing references) //IL_0426: Unknown result type (might be due to invalid IL or missing references) //IL_044b: Unknown result type (might be due to invalid IL or missing references) //IL_044d: Unknown result type (might be due to invalid IL or missing references) //IL_044f: Unknown result type (might be due to invalid IL or missing references) //IL_046b: Unknown result type (might be due to invalid IL or missing references) //IL_0499: Unknown result type (might be due to invalid IL or missing references) //IL_04a0: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)state.Cart == (Object)null) { Detach(state, "cart destroyed/unloaded"); return; } if (!IsSupportedCart(state.Cart)) { Detach(state, "unsupported cart type"); return; } if ((Object)(object)state.CartBody == (Object)null) { state.CartBody = ((Component)state.Cart).GetComponent<Rigidbody>(); if ((Object)(object)state.CartBody == (Object)null) { if (Plugin.DebugLogging.Value) { Plugin.Log.LogDebug((object)("Waiting for Rigidbody to return on " + ((Object)state.Cart).name + "; coupling retained.")); } return; } } float num = Vector3.Distance(((Component)state.Vehicle).transform.position, ((Component)state.Cart).transform.position); if (Time.time - state.CoupledAt >= Plugin.CouplingGraceSeconds.Value && num > Plugin.EmergencyBreakawayDistance.Value) { Plugin.Log.LogWarning((object)$"Emergency breakaway: {state.DisplayName} -> {((Object)state.Cart).name} at {num:0.0}m."); Detach(state, $"emergency breakaway at {num:0.0}m"); return; } Rigidbody cartBody = state.CartBody; Vector3 val = CartEndAnchor(state.Cart, state.CartEndSign); Vector3 val2 = state.RearAnchor - ((Component)state.Vehicle).transform.forward * Plugin.TowGap.Value; Vector3 val3 = val2 - val; Vector3 pointVelocity = cartBody.GetPointVelocity(val); Vector3 val4 = state.Body.GetPointVelocity(val2) - pointVelocity; Vector3 val5 = new Vector3(val3.x, 0f, val3.z); Vector3 val6 = default(Vector3); ((Vector3)(ref val6))..ctor(val4.x, 0f, val4.z); Vector3 val7 = Vector3.ClampMagnitude(val5 * Plugin.GrabStrength.Value + val6 * Plugin.GrabDamping.Value, Plugin.MaxGrabAcceleration.Value); float num2 = Mathf.Clamp(val3.y * (Plugin.GrabStrength.Value * 0.25f) + val4.y * (Plugin.GrabDamping.Value * 0.25f), 0f - Plugin.MaxVerticalAcceleration.Value, Plugin.MaxVerticalAcceleration.Value); Vector3 val8 = val7 + Vector3.up * num2; cartBody.AddForceAtPosition(val8, val, (ForceMode)5); Vector3 val9 = Flat(((Component)state.Vehicle).transform.forward); Vector3 normalized = ((Vector3)(ref val9)).normalized; float cartHalfLength = GetCartHalfLength(state.Cart); state.RecordRearPath(val2); state.GetRearPathTarget(val2, normalized, cartHalfLength + Plugin.CartEndPadding.Value, out var target, out var tangent); val9 = Vector3.Cross(Vector3.up, tangent); Vector3 normalized2 = ((Vector3)(ref val9)).normalized; Vector3 val10 = Flat(target - cartBody.worldCenterOfMass); float num3 = Vector3.Dot(val10, normalized2); float num4 = Vector3.Dot(state.Body.velocity - cartBody.velocity, normalized2); float num5 = Mathf.Clamp(num3 * Plugin.CenteringStrength.Value + num4 * Plugin.CenteringDamping.Value, 0f - Plugin.MaxCenteringAcceleration.Value, Plugin.MaxCenteringAcceleration.Value); cartBody.AddForce(normalized2 * num5, (ForceMode)5); Vector3 val11 = val10 * Plugin.PathGuideStrength.Value * Time.fixedDeltaTime; val11 = Vector3.ClampMagnitude(val11, Plugin.MaxPathGuideVelocityChange.Value); cartBody.AddForce(val11, (ForceMode)2); float num6 = Mathf.Clamp(Vector3.Dot(val10, tangent) * Plugin.PoweredCatchupGain.Value, 0f - Plugin.MaxPoweredCatchupSpeed.Value, Plugin.MaxPoweredCatchupSpeed.Value); val9 = Flat(state.Body.velocity); float magnitude = ((Vector3)(ref val9)).magnitude; Vector3 val12 = tangent * (magnitude + num6); Vector3 val13 = Flat(cartBody.velocity); Vector3 val14 = val12 - val13; val14 = Vector3.ClampMagnitude(val14, Plugin.MaxPoweredVelocityChange.Value); cartBody.AddForce(val14, (ForceMode)2); Vector3 val15 = Flat(((Component)state.Cart).transform.forward * (0f - state.CartEndSign)); if (((Vector3)(ref val15)).sqrMagnitude > 0.0001f && ((Vector3)(ref tangent)).sqrMagnitude > 0.0001f) { ((Vector3)(ref val15)).Normalize(); float num7 = Mathf.Clamp(Vector3.SignedAngle(val15, tangent, Vector3.up) * (MathF.PI / 180f) * Plugin.YawAlignmentStrength.Value - cartBody.angularVelocity.y * 1.5f, 0f - Plugin.MaxYawAcceleration.Value, Plugin.MaxYawAcceleration.Value); cartBody.AddTorque(Vector3.up * num7, (ForceMode)5); } if (Plugin.DebugLogging.Value && Time.frameCount % 120 == 0) { Plugin.Log.LogDebug((object)$"Virtual hand {state.DisplayName}: handle={((Vector3)(ref val3)).magnitude:0.00}m, path={((Vector3)(ref val10)).magnitude:0.00}m, lateral={num3:0.00}m, poweredDV={((Vector3)(ref val14)).magnitude:0.00}, sign={state.CartEndSign:+0;-0}"); } } private static float GetCartHalfLength(PhysGrabCart cart) { if (!CartHalfLengths.TryGetValue(cart, out var value)) { value = ComputeHalfLength(((Component)cart).gameObject, ((Component)cart).transform, 0.35f); CartHalfLengths[cart] = value; } return value; } private static Vector3 CartEndAnchor(PhysGrabCart cart, float sign) { //IL_0006: 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_0017: 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) return ((Component)cart).transform.position + ((Component)cart).transform.forward * sign * (GetCartHalfLength(cart) + Plugin.CartEndPadding.Value); } private static float ComputeHalfLength(GameObject go, Transform t, float fallback) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_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_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: 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_0060: 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_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008c: 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_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) Collider[] componentsInChildren = go.GetComponentsInChildren<Collider>(); if (componentsInChildren.Length == 0) { return fallback; } float num = 0f; float num2 = 0f; Vector3 position = t.position; Vector3 forward = t.forward; Vector3 normalized = ((Vector3)(ref forward)).normalized; Collider[] array = componentsInChildren; foreach (Collider val in array) { if (!((Object)(object)val == (Object)null)) { Bounds bounds = val.bounds; Vector3 extents = ((Bounds)(ref bounds)).extents; float num3 = Vector3.Dot(((Bounds)(ref bounds)).center - position, normalized); float num4 = Mathf.Abs(normalized.x) * extents.x + Mathf.Abs(normalized.y) * extents.y + Mathf.Abs(normalized.z) * extents.z; num = Mathf.Min(num, num3 - num4); num2 = Mathf.Max(num2, num3 + num4); } } return Mathf.Max(fallback, Mathf.Max(Mathf.Abs(num), Mathf.Abs(num2))); } private static bool IsAuthority() { try { return SemiFunc.IsMasterClientOrSingleplayer(); } catch { return true; } } private static bool IsSupportedCart(PhysGrabCart cart) { if ((Object)(object)cart != (Object)null) { return string.Equals(CleanName(((Object)cart).name), "Item Cart Medium", StringComparison.Ordinal); } return false; } private static string CleanName(string name) { if (!string.IsNullOrEmpty(name)) { return name.Replace("Valuable ", string.Empty).Replace("(Clone)", string.Empty).Trim(); } return string.Empty; } private static Vector3 Flat(Vector3 v) { //IL_0000: 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_0011: Unknown result type (might be due to invalid IL or missing references) return new Vector3(v.x, 0f, v.z); } } }