Decompiled source of OpenSling v1.0.0

Mods/OpenSling.dll

Decompiled 13 hours ago
using System;
using System.Collections;
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 System.Text.Json;
using BoneLib;
using BoneLib.BoneMenu;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSLZ.Marrow;
using Il2CppSLZ.Marrow.Input;
using Il2CppSLZ.Marrow.Pool;
using Il2CppSLZ.Marrow.SceneStreaming;
using Il2CppSLZ.Marrow.Warehouse;
using Il2CppSystem.Collections.Generic;
using LabFusion.Entities;
using LabFusion.Marrow.Extenders;
using LabFusion.Network;
using LabFusion.Network.Serialization;
using LabFusion.Player;
using LabFusion.SDK.Modules;
using LabFusion.Utilities;
using MelonLoader;
using MelonLoader.Preferences;
using MelonLoader.Utils;
using Microsoft.CodeAnalysis;
using OpenSling;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Main), "OpenSling", "1.0.0", "broaj", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: MelonAdditionalDependencies(new string[] { "BoneLib" })]
[assembly: MelonOptionalDependencies(new string[] { "LabFusion" })]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("OpenSling")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("OpenSling")]
[assembly: AssemblyTitle("OpenSling")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.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 OpenSling
{
	internal static class FusionSync
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static PlayerUpdate <>9__2_0;

			internal void <Init>b__2_0(PlayerID _)
			{
				Post(Net.PlayerJoined);
			}
		}

		private static readonly object Gate = new object();

		private static readonly Queue<Action> Inbox = new Queue<Action>();

		internal static bool InServer
		{
			get
			{
				try
				{
					return NetworkInfo.HasServer;
				}
				catch
				{
					return false;
				}
			}
		}

		internal static void Init()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			ModuleMessageManager.RegisterHandler<SlingConfigMessage>();
			ModuleMessageManager.RegisterHandler<SlingRopeMessage>();
			object obj = <>c.<>9__2_0;
			if (obj == null)
			{
				PlayerUpdate val = delegate
				{
					Post(Net.PlayerJoined);
				};
				<>c.<>9__2_0 = val;
				obj = (object)val;
			}
			MultiplayerHooking.OnPlayerJoined += (PlayerUpdate)obj;
		}

		internal static bool TryEntity(Gun gun, out ushort id, out bool owner)
		{
			id = 0;
			owner = true;
			if (!InServer || (Object)(object)gun == (Object)null)
			{
				return false;
			}
			NetworkEntity val = default(NetworkEntity);
			if (!GunExtender.Cache.TryGet(gun, ref val) || val == null)
			{
				return false;
			}
			id = val.ID;
			owner = !val.HasOwner || val.IsOwner;
			return true;
		}

		internal static void SendConfig(ushort id, GunConfig c)
		{
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			if (PlayerIDManager.HasOtherPlayers)
			{
				MessageRelay.RelayModule<SlingConfigMessage, SlingConfigData>(new SlingConfigData
				{
					Entity = id,
					Mode = (byte)c.Mode,
					Style = (byte)(c.Style + 1),
					FrontForward = c.FrontForward,
					FrontUp = c.FrontUp,
					BackForward = c.BackForward,
					BackUp = c.BackUp,
					Length = c.Length,
					Width = c.Width,
					RollFront = c.RollFront,
					RollBack = c.RollBack,
					Swivels = c.Swivels
				}, new MessageRoute((RelayType)3, (NetworkChannel)0));
			}
		}

		internal static void SendRope(ushort id, Vector3[] local)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if (PlayerIDManager.HasOtherPlayers)
			{
				MessageRelay.RelayModule<SlingRopeMessage, SlingRopeData>(new SlingRopeData
				{
					Entity = id,
					Points = local
				}, new MessageRoute((RelayType)3, (NetworkChannel)1));
			}
		}

		internal static void Post(Action a)
		{
			lock (Gate)
			{
				if (Inbox.Count < 512)
				{
					Inbox.Enqueue(a);
				}
			}
		}

		internal static void Drain()
		{
			while (true)
			{
				Action action;
				lock (Gate)
				{
					action = ((Inbox.Count > 0) ? Inbox.Dequeue() : null);
				}
				if (action == null)
				{
					break;
				}
				try
				{
					action();
				}
				catch (Exception e)
				{
					Main.LogOnce("net-inbox", e);
				}
			}
		}
	}
	internal sealed class SlingConfigData : INetSerializable
	{
		public ushort Entity;

		public byte Mode;

		public byte Style;

		public float FrontForward;

		public float FrontUp;

		public float BackForward;

		public float BackUp;

		public float Length;

		public float Width;

		public float RollFront;

		public float RollBack;

		public bool Swivels = true;

		public int? GetSize()
		{
			return 37;
		}

		public void Serialize(INetSerializer s)
		{
			s.SerializeValue(ref Entity);
			s.SerializeValue(ref Mode);
			s.SerializeValue(ref Style);
			s.SerializeValue(ref FrontForward);
			s.SerializeValue(ref FrontUp);
			s.SerializeValue(ref BackForward);
			s.SerializeValue(ref BackUp);
			s.SerializeValue(ref Length);
			s.SerializeValue(ref Width);
			s.SerializeValue(ref RollFront);
			s.SerializeValue(ref RollBack);
			s.SerializeValue(ref Swivels);
		}
	}
	internal sealed class SlingRopeData : INetSerializable
	{
		public ushort Entity;

		public Vector3[] Points = (Vector3[])(object)new Vector3[16];

		public int? GetSize()
		{
			return 194;
		}

		public void Serialize(INetSerializer s)
		{
			s.SerializeValue(ref Entity);
			if (Points == null || Points.Length != 16)
			{
				Points = (Vector3[])(object)new Vector3[16];
			}
			for (int i = 0; i < 16; i++)
			{
				NetSerializerUnityExtensions.SerializeValue(s, ref Points[i]);
			}
		}
	}
	[SkipHandleWhileLoading]
	internal sealed class SlingConfigMessage : ModuleMessageHandler
	{
		protected override void OnHandleMessage(ReceivedMessage received)
		{
			SlingConfigData slingConfigData = ((ReceivedMessage)(ref received)).ReadData<SlingConfigData>();
			GunConfig c = new GunConfig
			{
				Mode = (SlingMode)slingConfigData.Mode,
				Style = (SlingStyle)(slingConfigData.Style - 1),
				FrontForward = slingConfigData.FrontForward,
				FrontUp = slingConfigData.FrontUp,
				BackForward = slingConfigData.BackForward,
				BackUp = slingConfigData.BackUp,
				Length = slingConfigData.Length,
				Width = slingConfigData.Width,
				RollFront = slingConfigData.RollFront,
				RollBack = slingConfigData.RollBack,
				Swivels = slingConfigData.Swivels
			};
			ushort id = slingConfigData.Entity;
			FusionSync.Post(delegate
			{
				Net.OnConfig(id, c);
			});
		}
	}
	[SkipHandleWhileLoading]
	internal sealed class SlingRopeMessage : ModuleMessageHandler
	{
		protected override void OnHandleMessage(ReceivedMessage received)
		{
			SlingRopeData slingRopeData = ((ReceivedMessage)(ref received)).ReadData<SlingRopeData>();
			ushort id = slingRopeData.Entity;
			Vector3[] pts = slingRopeData.Points;
			FusionSync.Post(delegate
			{
				Net.OnRope(id, pts);
			});
		}
	}
	internal enum SlingStyle
	{
		Default = -1,
		Black,
		Leather,
		BlackTightener,
		Green,
		Brown
	}
	internal enum SlingMode
	{
		Auto,
		Always,
		Never
	}
	internal sealed class GunConfig
	{
		public const float DefaultWidth = 0.032f;

		public SlingMode Mode { get; set; }

		public SlingStyle Style { get; set; } = SlingStyle.Default;

		public float FrontForward { get; set; }

		public float FrontUp { get; set; }

		public float BackForward { get; set; }

		public float BackUp { get; set; }

		public float Length { get; set; } = 1f;

		public float Width { get; set; } = 0.032f;

		public float RollFront { get; set; }

		public float RollBack { get; set; }

		public bool Swivels { get; set; } = true;

		public bool IsDefault
		{
			get
			{
				if (Mode == SlingMode.Auto && Style == SlingStyle.Default && FrontForward == 0f && FrontUp == 0f && BackForward == 0f && BackUp == 0f && Mathf.Abs(Length - 1f) < 0.0001f && Mathf.Abs(Width - 0.032f) < 0.0001f && RollFront == 0f && RollBack == 0f)
				{
					return Swivels;
				}
				return false;
			}
		}

		public GunConfig Clone()
		{
			return (GunConfig)MemberwiseClone();
		}

		public void Sanitize()
		{
			FrontForward = C(FrontForward, -0.5f, 0.5f, 0f);
			FrontUp = C(FrontUp, -0.3f, 0.3f, 0f);
			BackForward = C(BackForward, -0.5f, 0.5f, 0f);
			BackUp = C(BackUp, -0.3f, 0.3f, 0f);
			Length = C(Length, 0.3f, 4f, 1f);
			Width = C(Width, 0.012f, 0.07f, 0.032f);
			RollFront = C(RollFront, -180f, 180f, 0f);
			RollBack = C(RollBack, -180f, 180f, 0f);
			if (!Enum.IsDefined(typeof(SlingStyle), Style))
			{
				Style = SlingStyle.Default;
			}
			if (!Enum.IsDefined(typeof(SlingMode), Mode))
			{
				Mode = SlingMode.Auto;
			}
			static float C(float v, float lo, float hi, float d)
			{
				if (!float.IsFinite(v))
				{
					return d;
				}
				return Mathf.Clamp(v, lo, hi);
			}
		}
	}
	internal static class GunStore
	{
		private static readonly Dictionary<string, GunConfig> Guns = new Dictionary<string, GunConfig>();

		private static bool _dirty;

		private static float _saveAt;

		private static string PathName => Path.Combine(MelonEnvironment.UserDataDirectory, "OpenSling_Guns.json");

		internal static string FilePath => PathName;

		internal static GunConfig Get(string barcode)
		{
			if (string.IsNullOrEmpty(barcode) || !Guns.TryGetValue(barcode, out GunConfig value))
			{
				return new GunConfig();
			}
			return value;
		}

		internal static bool Has(string barcode)
		{
			return Guns.ContainsKey(barcode);
		}

		internal static void Set(string barcode, GunConfig config)
		{
			if (!string.IsNullOrEmpty(barcode))
			{
				config.Sanitize();
				if (config.IsDefault)
				{
					Guns.Remove(barcode);
				}
				else
				{
					Guns[barcode] = config.Clone();
				}
				_dirty = true;
				_saveAt = Time.unscaledTime + 0.75f;
			}
		}

		internal static void Reset(string barcode)
		{
			if (Guns.Remove(barcode))
			{
				_dirty = true;
				_saveAt = Time.unscaledTime + 0.25f;
			}
		}

		internal static void Load()
		{
			try
			{
				if (!File.Exists(PathName))
				{
					return;
				}
				Dictionary<string, GunConfig> dictionary = JsonSerializer.Deserialize<Dictionary<string, GunConfig>>(File.ReadAllText(PathName));
				if (dictionary == null)
				{
					return;
				}
				foreach (KeyValuePair<string, GunConfig> item in dictionary)
				{
					if (item.Value != null)
					{
						item.Value.Sanitize();
						Guns[item.Key] = item.Value;
					}
				}
				Main.Log.Msg($"Loaded sling settings for {Guns.Count} gun(s).");
			}
			catch (Exception ex)
			{
				Main.Log.Warning("Couldn't read " + PathName + ": " + ex.Message);
			}
		}

		internal static void SaveIfDirty()
		{
			if (_dirty && Time.unscaledTime >= _saveAt)
			{
				SaveNow();
			}
		}

		internal static void SaveNow()
		{
			if (!_dirty)
			{
				return;
			}
			_dirty = false;
			try
			{
				File.WriteAllText(PathName, JsonSerializer.Serialize(Guns, new JsonSerializerOptions
				{
					WriteIndented = true
				}));
			}
			catch (Exception e)
			{
				Main.LogOnce("save", e);
			}
		}
	}
	internal static class LitShader
	{
		private static Shader? _cached;

		private static readonly string[] Preferred = new string[5] { "Universal Render Pipeline/Lit", "Universal Render Pipeline/Lit (PBR Workflow)", "SLZ/LitMAS/LitMAS Opaque", "SLZ/LitMAS/LitMAS Standard", "Universal Render Pipeline/Simple Lit" };

		internal static string Info { get; private set; } = "";

		private static bool Ok(Shader? s)
		{
			try
			{
				return (Object)(object)s != (Object)null && !((Il2CppObjectBase)s).WasCollected && s.isSupported;
			}
			catch
			{
				return false;
			}
		}

		internal static Shader? Get()
		{
			if (Ok(_cached))
			{
				return _cached;
			}
			_cached = null;
			try
			{
				string[] preferred = Preferred;
				for (int i = 0; i < preferred.Length; i++)
				{
					Shader val = Shader.Find(preferred[i]);
					if (Ok(val))
					{
						return Pick(val, "found");
					}
				}
				Il2CppArrayBase<Shader> val2 = Resources.FindObjectsOfTypeAll<Shader>();
				preferred = Preferred;
				foreach (string text in preferred)
				{
					foreach (Shader item in val2)
					{
						if (Ok(item) && ((Object)item).name == text)
						{
							return Pick(item, "loaded");
						}
					}
				}
				foreach (Shader item2 in val2)
				{
					if (Ok(item2) && ((Object)item2).name.Contains("LitMAS") && !((Object)item2).name.Contains("Transparent"))
					{
						return Pick(item2, "loaded");
					}
				}
				RigManager rigManager = Player.RigManager;
				if ((Object)(object)rigManager != (Object)null)
				{
					foreach (Renderer componentsInChild in ((Component)rigManager).GetComponentsInChildren<Renderer>(true))
					{
						if ((Object)(object)componentsInChild == (Object)null)
						{
							continue;
						}
						foreach (Material item3 in (Il2CppArrayBase<Material>)(object)componentsInChild.sharedMaterials)
						{
							if ((Object)(object)item3 != (Object)null && Ok(item3.shader) && item3.renderQueue < 2500 && (item3.HasProperty("_BaseColor") || item3.HasProperty("_Color")))
							{
								return Pick(item3.shader, "player's");
							}
						}
					}
				}
			}
			catch (Exception e)
			{
				Main.LogOnce("lit-shader", e);
			}
			Info = "no lit shader found";
			return null;
		}

		private static Shader Pick(Shader sh, string how)
		{
			_cached = sh;
			Info = ((Object)sh).name + " (" + how + ")";
			Main.Log.Msg("Sling shader: " + Info);
			return sh;
		}
	}
	public sealed class Main : MelonMod
	{
		internal static Instance Log = null;

		private static readonly HashSet<string> Logged = new HashSet<string>();

		public override void OnInitializeMelon()
		{
			Log = ((MelonBase)this).LoggerInstance;
			Settings.Create();
			GunStore.Load();
			Settings.BuildMenu();
			Net.Init();
			SelfTest.OnInit();
			Hooking.OnLevelLoaded += delegate
			{
				SlingManager.Clear();
				SelfTest.OnLevelLoaded();
			};
			Hooking.OnLevelUnloaded += SlingManager.Clear;
			Log.Msg("Loaded" + (Net.FusionAvailable ? " (Fusion sync on)" : "") + ". BoneMenu > OpenSling.");
		}

		public override void OnUpdate()
		{
			SelfTest.DriveInput();
			SlingManager.Update();
			GunStore.SaveIfDirty();
			Net.Tick();
		}

		public override void OnFixedUpdate()
		{
			SelfTest.FixedTick();
			SlingManager.FixedUpdate();
		}

		public override void OnLateUpdate()
		{
			SelfTest.DriveInput();
			SlingManager.LateUpdate();
		}

		public override void OnApplicationQuit()
		{
			GunStore.SaveNow();
		}

		internal static void LogOnce(string key, Exception e)
		{
			if (Logged.Add(key))
			{
				Log.Error($"[{key}] {e}");
			}
		}
	}
	internal static class Net
	{
		private static readonly Dictionary<ushort, GunConfig> RemoteConfigs = new Dictionary<ushort, GunConfig>();

		private static float _nextConfigResend;

		internal static bool FusionAvailable { get; private set; }

		internal static bool InServer
		{
			get
			{
				if (FusionAvailable)
				{
					return FusionInServer();
				}
				return false;
			}
		}

		internal static void Init()
		{
			try
			{
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				for (int i = 0; i < assemblies.Length; i++)
				{
					if (assemblies[i].GetName().Name == "LabFusion")
					{
						InitFusion();
						FusionAvailable = true;
						break;
					}
				}
			}
			catch (Exception ex)
			{
				Main.Log.Warning("Fusion sync unavailable: " + ex.Message);
				FusionAvailable = false;
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void InitFusion()
		{
			FusionSync.Init();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static bool FusionInServer()
		{
			return FusionSync.InServer;
		}

		internal static GunConfig? RemoteConfig(ushort id)
		{
			if (!RemoteConfigs.TryGetValue(id, out GunConfig value))
			{
				return null;
			}
			return value;
		}

		internal static void Attach(Sling s)
		{
			Refresh(s);
		}

		internal static void Refresh(Sling s)
		{
			if (!FusionAvailable)
			{
				s.Networked = false;
				s.IsOwner = true;
				return;
			}
			bool isOwner = s.IsOwner;
			bool networked = s.Networked;
			ushort entityId = s.EntityId;
			if (!FusionEntity(s, out var id, out var owner))
			{
				s.Networked = false;
				s.IsOwner = true;
				return;
			}
			s.Networked = true;
			s.EntityId = id;
			s.IsOwner = owner;
			if (owner && (!isOwner || !networked || entityId != id))
			{
				ConfigChanged(s);
			}
			if (!owner && RemoteConfigs.TryGetValue(id, out GunConfig value) && !Same(value, s.Config))
			{
				s.Apply(value);
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static bool FusionEntity(Sling s, out ushort id, out bool owner)
		{
			id = 0;
			owner = true;
			try
			{
				return FusionSync.TryEntity(s.Gun, out id, out owner);
			}
			catch
			{
				return false;
			}
		}

		internal static void ConfigChanged(Sling s)
		{
			if (!InServer || !s.Networked || !s.IsOwner)
			{
				return;
			}
			try
			{
				SendConfig(s.EntityId, GunStore.Get(s.Barcode));
			}
			catch (Exception e)
			{
				Main.LogOnce("send-config", e);
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void SendConfig(ushort id, GunConfig c)
		{
			FusionSync.SendConfig(id, c);
		}

		internal static void SendRope(Sling s)
		{
			//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_005d: 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_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			if (!s.Networked || !s.IsOwner || Time.time < s.NextSend || !InServer)
			{
				return;
			}
			s.NextSend = Time.time + 0.1f;
			bool flag = false;
			Vector3[] array = (Vector3[])(object)new Vector3[16];
			for (int i = 0; i < 16; i++)
			{
				array[i] = s.T.InverseTransformPoint(s.P[i]);
				Vector3 val = array[i] - s.SentLocal[i];
				if (((Vector3)(ref val)).sqrMagnitude > 4.0000004E-06f)
				{
					flag = true;
				}
			}
			if (!flag)
			{
				return;
			}
			Array.Copy(array, s.SentLocal, 16);
			try
			{
				SendRopeFusion(s.EntityId, array);
			}
			catch (Exception e)
			{
				Main.LogOnce("send-rope", e);
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void SendRopeFusion(ushort id, Vector3[] local)
		{
			FusionSync.SendRope(id, local);
		}

		internal static void Tick()
		{
			if (!FusionAvailable)
			{
				return;
			}
			if (!InServer)
			{
				if (RemoteConfigs.Count > 0)
				{
					RemoteConfigs.Clear();
				}
				return;
			}
			FusionDrain();
			if (!(Time.unscaledTime >= _nextConfigResend))
			{
				return;
			}
			_nextConfigResend = Time.unscaledTime + 10f;
			foreach (Sling item in SlingManager.All)
			{
				ConfigChanged(item);
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void FusionDrain()
		{
			FusionSync.Drain();
		}

		internal static void PlayerJoined()
		{
			_nextConfigResend = 0f;
		}

		internal static void OnConfig(ushort id, GunConfig c)
		{
			c.Sanitize();
			RemoteConfigs[id] = c;
			Sling sling = SlingManager.FindByEntity(id);
			if (sling != null && !sling.IsOwner)
			{
				if (c.Mode == SlingMode.Never)
				{
					SlingManager.Rescan();
				}
				else
				{
					sling.Apply(c);
				}
			}
		}

		internal static void OnRope(ushort id, Vector3[] local)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: 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_0039: Unknown result type (might be due to invalid IL or missing references)
			Sling sling = SlingManager.FindByEntity(id);
			if (sling == null || sling.IsOwner)
			{
				return;
			}
			for (int i = 0; i < 16 && i < local.Length; i++)
			{
				Vector3 val = local[i];
				if (!float.IsFinite(val.x) || !float.IsFinite(val.y) || !float.IsFinite(val.z) || ((Vector3)(ref val)).sqrMagnitude > 25f)
				{
					return;
				}
			}
			Array.Copy(local, sling.RemoteLocal, 16);
			sling.RemoteTime = Time.time;
		}

		private static bool Same(GunConfig a, GunConfig b)
		{
			if (a.Mode == b.Mode && a.Style == b.Style && a.FrontForward == b.FrontForward && a.FrontUp == b.FrontUp && a.BackForward == b.BackForward && a.BackUp == b.BackUp && a.Length == b.Length && a.Width == b.Width && a.RollFront == b.RollFront && a.RollBack == b.RollBack)
			{
				return a.Swivels == b.Swivels;
			}
			return false;
		}
	}
	internal static class SelfTest
	{
		private sealed class MoveRun
		{
			public bool Sling;

			public float Walked;

			public float HandGap;

			public float Jitter;

			public float Pull;

			public float MaxStretch;

			public int Samples;

			public int Over4;

			public readonly List<float> Jumps = new List<float>();
		}

		private static readonly List<string> Report = new List<string>();

		private static int pass;

		private static int fail;

		private static int shotIndex;

		private static bool running;

		private static bool loadRequested;

		private static Vector3 shotTarget;

		private const int Ground = 1089;

		private static Vector2 _move;

		private static bool _jump;

		private static bool _driving;

		private static int _jumpFrame = -1;

		private static int _releaseFrame = -1;

		private static int _gripFrame = -1;

		private static bool _grip;

		private static Rigidbody? _push;

		private static Vector3 _pushAccel;

		private static string Flag => Path.Combine(MelonEnvironment.UserDataDirectory, "OpenSling_AutoTest.txt");

		private static string ReportPath => Path.Combine(MelonEnvironment.UserDataDirectory, "OpenSling_SelfTest.txt");

		private static string ShotDir => Path.Combine(MelonEnvironment.UserDataDirectory, "OpenSling_Shots");

		internal static void OnInit()
		{
			if (File.Exists(Flag))
			{
				Application.runInBackground = true;
			}
		}

		internal static void OnLevelLoaded()
		{
			if (File.Exists(Flag) && !running)
			{
				string text = "";
				try
				{
					text = ((Scannable)SceneStreamer.Session.Level).Barcode.ID;
				}
				catch
				{
				}
				if (text == "c2534c5a-61b3-4f97-9059-79155363656e")
				{
					running = true;
					MelonCoroutines.Start(Run());
				}
				else if (!loadRequested)
				{
					loadRequested = true;
					MelonCoroutines.Start(LoadBaseline());
				}
			}
		}

		private static IEnumerator LoadBaseline()
		{
			yield return (object)new WaitForSeconds(5f);
			try
			{
				SceneStreamer.Load(new Barcode("c2534c5a-61b3-4f97-9059-79155363656e"), (Barcode)null);
			}
			catch
			{
			}
		}

		private static void Check(string name, bool ok, string detail = "")
		{
			if (ok)
			{
				pass++;
			}
			else
			{
				fail++;
			}
			string text = (ok ? "PASS" : "FAIL") + "  " + name + ((detail.Length > 0) ? ("  -- " + detail) : "");
			Report.Add(text);
			Main.Log.Msg("[SelfTest] " + text);
		}

		private static void Note(string text)
		{
			Report.Add("      " + text);
			Main.Log.Msg("[SelfTest] " + text);
		}

		private static void Shot(string name, float dist = 1.4f)
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: 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)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: 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_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Expected O, but got Unknown
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: 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_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: 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_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: 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_0150: Expected O, but got Unknown
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Expected O, but got Unknown
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = null;
			RenderTexture val2 = null;
			Texture2D val3 = null;
			try
			{
				Directory.CreateDirectory(ShotDir);
				string path = Path.Combine(ShotDir, $"{shotIndex++:D2}_{name}.png");
				Vector3 val4 = (((Object)(object)Player.Head != (Object)null) ? Player.Head.position : (shotTarget + Vector3.back)) - shotTarget;
				val4.y = 0f;
				val4 = ((((Vector3)(ref val4)).sqrMagnitude > 0.01f) ? ((Vector3)(ref val4)).normalized : Vector3.back);
				val = new GameObject("OpenSlingTestCam");
				Camera val5 = val.AddComponent<Camera>();
				val.transform.position = shotTarget + val4 * dist + Vector3.up * 0.35f + Vector3.Cross(Vector3.up, val4) * 0.5f;
				val.transform.LookAt(shotTarget);
				val5.fieldOfView = 55f;
				val2 = (val5.targetTexture = new RenderTexture(1280, 720, 24));
				val5.Render();
				RenderTexture active = RenderTexture.active;
				RenderTexture.active = val2;
				val3 = new Texture2D(1280, 720, (TextureFormat)3, false);
				val3.ReadPixels(new Rect(0f, 0f, 1280f, 720f), 0, 0);
				val3.Apply();
				RenderTexture.active = active;
				val5.targetTexture = null;
				File.WriteAllBytes(path, Il2CppArrayBase<byte>.op_Implicit((Il2CppArrayBase<byte>)(object)ImageConversion.EncodeToPNG(val3)));
				Note("screenshot " + Path.GetFileName(path));
			}
			catch (Exception ex)
			{
				Note("screenshot failed: " + ex.Message);
			}
			finally
			{
				if ((Object)(object)val != (Object)null)
				{
					Object.Destroy((Object)(object)val);
				}
				if ((Object)(object)val2 != (Object)null)
				{
					val2.Release();
					Object.Destroy((Object)(object)val2);
				}
				if ((Object)(object)val3 != (Object)null)
				{
					Object.Destroy((Object)(object)val3);
				}
			}
		}

		private static float Floor(Vector3 p)
		{
			//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_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)
			//IL_0015: 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_002e: Unknown result type (might be due to invalid IL or missing references)
			RaycastHit val = default(RaycastHit);
			if (!Physics.Raycast(p + Vector3.up * 0.5f, Vector3.down, ref val, 5f, 1089, (QueryTriggerInteraction)1))
			{
				return p.y - 1f;
			}
			return ((RaycastHit)(ref val)).point.y;
		}

		private static IEnumerator Spawn(string barcode, Vector3 pos, Action<Gun?> done)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			HashSet<IntPtr> before = new HashSet<IntPtr>(((IEnumerable<Gun>)Object.FindObjectsOfType<Gun>()).Select((Gun g) => ((Il2CppObjectBase)g).Pointer));
			GameObject go = null;
			HelperMethods.SpawnCrate(barcode, pos, Quaternion.LookRotation(Vector3.right), Vector3.one, true, (Action<GameObject>)delegate(GameObject g)
			{
				go = g;
			}, (Action<GameObject>)null);
			float until = Time.time + 20f;
			Gun found = null;
			while ((Object)(object)found == (Object)null && Time.time < until)
			{
				if ((Object)(object)go != (Object)null)
				{
					found = ((IEnumerable<Gun>)go.GetComponentsInChildren<Gun>(true)).FirstOrDefault((Func<Gun, bool>)((Gun g) => (Object)(object)Sling.FirePoint(g) != (Object)null));
				}
				if ((Object)(object)found == (Object)null && Time.frameCount % 15 == 0)
				{
					foreach (Gun item in Object.FindObjectsOfType<Gun>())
					{
						if ((Object)(object)item != (Object)null && (Object)(object)Sling.FirePoint(item) != (Object)null && !before.Contains(((Il2CppObjectBase)item).Pointer))
						{
							Vector3 val = ((Component)item).transform.position - pos;
							if (((Vector3)(ref val)).sqrMagnitude < 4f)
							{
								found = item;
								break;
							}
						}
					}
				}
				yield return null;
			}
			yield return (object)new WaitForSeconds(0.5f);
			done(found);
		}

		private static IEnumerator Run()
		{
			while (HelperMethods.IsLoading() || (Object)(object)Player.RigManager == (Object)null)
			{
				yield return null;
			}
			yield return (object)new WaitForSeconds(6f);
			Report.Clear();
			fail = 0;
			pass = 0;
			Note("===== OpenSling self test =====");
			bool savedAuto = Settings.AutoSling.Value;
			Settings.AutoSling.Value = true;
			Vector3 head = Player.Head.position;
			Vector3 fwd = Player.Head.forward;
			fwd.y = 0f;
			((Vector3)(ref fwd)).Normalize();
			Vector3 side = Vector3.Cross(Vector3.up, fwd);
			Vector3 spot = head + fwd * 1.3f;
			spot.y = Floor(spot) + 0.6f;
			Gun rifle = null;
			Gun pistol = null;
			yield return Spawn("c1534c5a-a6b5-4177-beb8-04d947756e41", spot, delegate(Gun? val10)
			{
				rifle = val10;
			});
			yield return Spawn("c1534c5a-fcfc-4f43-8fb0-d29531393131", spot + side * 0.8f, delegate(Gun? val10)
			{
				pistol = val10;
			});
			Check("rifle and pistol spawned", (Object)(object)rifle != (Object)null && (Object)(object)pistol != (Object)null);
			if ((Object)(object)rifle == (Object)null)
			{
				Finish(savedAuto);
				yield break;
			}
			yield return (object)new WaitForSeconds(3f);
			Sling sling = SlingManager.Ensure(rifle);
			Check("rifle got a sling", sling != null, SlingManager.Explain(rifle));
			Check("pistol didn't (pistols are left alone)", (Object)(object)pistol == (Object)null || SlingManager.Find(pistol) == null);
			if (sling == null)
			{
				Finish(savedAuto);
				yield break;
			}
			SlingManager.Describe(rifle, out string barcode, out string title, out List<string> tags);
			Note($"rifle: {title} [{string.Join(", ", tags)}], length {sling.GunLength:0.00} m, sling {sling.Rest:0.00} m");
			Vector3 forward = Sling.FirePoint(rifle).forward;
			float num = Vector3.Dot(sling.Front - Sling.FirePoint(rifle).position, forward);
			float num2 = Vector3.Dot(sling.Back - Sling.FirePoint(rifle).position, forward);
			Check("front swivel toward the muzzle, back at the stock", num > num2 + 0.3f, $"front {num:0.00} m, back {num2:0.00} m along the barrel");
			Vector3 val = sling.T.TransformDirection(sling.Up);
			_ = sling.T.position;
			Check("swivels on the underside", Vector3.Dot(sling.Front - Sling.FirePoint(rifle).position, val) < 0.02f && Vector3.Dot(sling.Back - Sling.FirePoint(rifle).position, val) < 0.02f);
			float floorY = spot.y - 0.6f;
			float num3 = sling.P.Min((Vector3 p) => p.y);
			Check("strap rests on the floor, not through it", num3 > floorY - 0.015f, $"lowest point {num3 - floorY:0.000} m above the floor");
			shotTarget = sling.T.position;
			Shot("A_rifle_on_floor");
			GameObject viewRoot = sling.ViewRoot;
			int num4 = (((Object)(object)viewRoot != (Object)null) ? viewRoot.GetComponentsInChildren<Collider>(true).Length : (-1));
			int num5 = (((Object)(object)viewRoot != (Object)null) ? viewRoot.GetComponentsInChildren<Grip>(true).Length : (-1));
			Check("sling has no colliders or grips (not grabbable)", num4 == 0 && num5 == 0, $"{num4} colliders, {num5} grips");
			GameObject bar = GameObject.CreatePrimitive((PrimitiveType)3);
			((Object)bar).name = "OpenSling_TestBar";
			Vector3 barPos = spot + Vector3.up * 1.2f;
			bar.transform.position = barPos;
			bar.transform.localScale = new Vector3(0.08f, 0.08f, 1.5f);
			bar.transform.rotation = Quaternion.LookRotation(fwd);
			yield return (object)new WaitForSeconds(0.2f);
			Rigidbody rb = sling.Rb;
			float num6 = Vector3.Distance(sling.FrontLocal, sling.BackLocal) * 0.5f;
			float num7 = Mathf.Sqrt(Mathf.Max(0.01f, Mathf.Pow(sling.Rest * 0.49f, 2f) - num6 * num6)) - 0.04f;
			rb.velocity = Vector3.zero;
			rb.angularVelocity = Vector3.zero;
			((Component)rb).transform.SetPositionAndRotation(barPos + Vector3.down * num7, Quaternion.LookRotation(side, Vector3.up));
			rb.position = ((Component)rb).transform.position;
			rb.rotation = ((Component)rb).transform.rotation;
			yield return null;
			Vector3 val2 = barPos + Vector3.up * 0.055f;
			Vector3[] array = (Vector3[])(object)new Vector3[16];
			for (int num8 = 0; num8 < 16; num8++)
			{
				float num9 = (float)num8 / 15f;
				array[num8] = ((num9 < 0.5f) ? Vector3.Lerp(sling.Front, val2, num9 * 2f) : Vector3.Lerp(val2, sling.Back, (num9 - 0.5f) * 2f));
			}
			sling.SetPoints(array);
			float startY = rb.position.y;
			Note($"  apex set {sling.P[8].y - floorY:0.000}, bar seen by queries at apex: {((IEnumerable<Collider>)Physics.OverlapSphere(val2 + Vector3.down * 0.02f, 0.03f, Sling.Mask, (QueryTriggerInteraction)1)).Any((Collider x) => (Object)(object)((Component)x).gameObject == (Object)(object)bar)}");
			for (int k = 0; k < 4; k++)
			{
				yield return null;
				Note($"  frame {k}: apex {sling.P[8].y - floorY:0.000} gun {rb.position.y - floorY:0.000} stretch {sling.Stretch * 100f:0.0}% pull {sling.LastForce:0}");
			}
			for (int k = 0; k < 12; k++)
			{
				yield return (object)new WaitForSeconds(0.5f);
				int num10 = 0;
				for (int num11 = 1; num11 < 16; num11++)
				{
					if (sling.P[num11].y > sling.P[num10].y)
					{
						num10 = num11;
					}
				}
				Note($"  hang t={(float)k * 0.5f + 0.5f:0.0}s gun y {rb.position.y - floorY:0.00} rope top {sling.P[num10].y - floorY:0.00} (bar top {barPos.y + 0.04f - floorY:0.00}) stretch {sling.Stretch * 100f:0.0}% pull {sling.LastForce:0} N kin {rb.isKinematic}");
			}
			float y = rb.position.y;
			Check("hung over a bar, it holds the gun up", y > floorY + 0.5f && Mathf.Abs(y - startY) < 0.35f, $"gun {y - floorY:0.00} m off the floor (moved {y - startY:+0.00;-0.00} m), stretch {sling.Stretch * 100f:0.0}%, pull {sling.LastForce:0} N");
			shotTarget = barPos + Vector3.down * 0.3f;
			Shot("B_hung_on_bar", 1.6f);
			float maxStretch = 0f;
			List<float> yank = new List<float>();
			float tYank = Time.time + 1f;
			while (Time.time < tYank)
			{
				_push = rb;
				_pushAccel = Vector3.down * 9.81f * 3f;
				maxStretch = Mathf.Max(maxStretch, sling.Stretch);
				yank.Add(sling.Stretch);
				yield return null;
			}
			_push = null;
			yank.Sort();
			Note($"  yank stretch: median {yank[yank.Count / 2] * 100f:0.0}%, 90% of the time under {yank[(int)((float)yank.Count * 0.9f)] * 100f:0.0}%, peak {maxStretch * 100f:0.0}%");
			float num12 = yank[(int)((float)yank.Count * 0.9f)];
			Check("can't be stretched much (holds at its limit)", num12 < 0.12f && maxStretch < 0.2f, $"90% of the time under {num12 * 100f:0.0}%, peak {maxStretch * 100f:0.0}% (limit {6f:0}%) under 4x the gun's weight");
			Object.Destroy((Object)(object)bar);
			yield return (object)new WaitForSeconds(1.5f);
			Vector3 frontLocal = sling.FrontLocal;
			EditMode.ApplyTo(barcode, delegate(GunConfig cfg)
			{
				cfg.FrontForward = 0.05f;
			});
			Sling sling2 = SlingManager.Find(rifle);
			float num13 = ((sling2 != null) ? (Vector3.Dot(sling2.FrontLocal - frontLocal, sling2.Fwd) * sling2.T.lossyScale.x) : (-1f));
			Check("edit: front swivel moves", Mathf.Abs(num13 - 0.05f) < 0.005f, $"moved {num13 * 100f:0.0} cm");
			GunStore.SaveNow();
			bool ok = File.Exists(GunStore.FilePath) && File.ReadAllText(GunStore.FilePath).Contains(barcode);
			Check("edit is saved", ok, GunStore.FilePath);
			EditMode.ApplyTo(barcode, delegate(GunConfig cfg)
			{
				cfg.Length = 1.5f;
			});
			sling2 = SlingManager.Find(rifle);
			Check("edit: sling length", sling2 != null && Mathf.Abs(sling2.Rest - sling2.BaseLength * 1.5f) < 0.01f, $"{sling2?.Rest ?? 0f:0.00} m");
			GunStore.Reset(barcode);
			EditMode.Refresh(barcode);
			sling2 = SlingManager.Find(rifle);
			Check("reset gun puts it back", sling2 != null && Vector3.Distance(sling2.FrontLocal, frontLocal) < 0.001f && Mathf.Abs(sling2.Rest - sling2.BaseLength) < 0.001f);
			rb.velocity = Vector3.zero;
			((Component)rb).transform.SetPositionAndRotation(spot + Vector3.up * 0.3f, Quaternion.LookRotation(side, Vector3.up));
			rb.position = ((Component)rb).transform.position;
			rb.isKinematic = true;
			yield return (object)new WaitForSeconds(1.5f);
			SlingStyle[] array2 = new SlingStyle[5]
			{
				SlingStyle.Black,
				SlingStyle.Leather,
				SlingStyle.BlackTightener,
				SlingStyle.Green,
				SlingStyle.Brown
			};
			for (int k = 0; k < array2.Length; k++)
			{
				SlingStyle st = array2[k];
				EditMode.ApplyTo(barcode, delegate(GunConfig cfg)
				{
					cfg.Style = st;
				});
				yield return (object)new WaitForSeconds(0.4f);
				shotTarget = rb.position + Vector3.down * 0.15f;
				Shot("C_style_" + st, 1.1f);
			}
			GunStore.Reset(barcode);
			EditMode.Refresh(barcode);
			rb.isKinematic = false;
			EditMode.ApplyTo(barcode, delegate(GunConfig cfg)
			{
				cfg.Mode = SlingMode.Never;
			});
			Check("excluded gun loses its sling", SlingManager.Find(rifle) == null);
			GunStore.Reset(barcode);
			EditMode.Refresh(barcode);
			Check("un-excluded, it's back", SlingManager.Ensure(rifle) != null);
			Settings.AutoSling.Value = false;
			SlingManager.Rescan();
			yield return (object)new WaitForSeconds(1.2f);
			Check("Auto Sling off: no slings on guns", SlingManager.Find(rifle) == null);
			EditMode.ApplyTo(barcode, delegate(GunConfig cfg)
			{
				cfg.Mode = SlingMode.Always;
			});
			Check("...unless set to Always for that gun", SlingManager.Ensure(rifle) != null);
			GunStore.Reset(barcode);
			EditMode.ApplyTo(barcode, delegate(GunConfig cfg)
			{
				cfg.Mode = SlingMode.Always;
				cfg.Width = 0.05f;
				cfg.RollFront = 90f;
			});
			Sling sw = SlingManager.Find(rifle);
			Check("edit: width", sw != null && Mathf.Abs(sw.Config.Width - 0.05f) < 0.0001f);
			Vector3 val5;
			if (sw != null)
			{
				Vector3 outFrontWorld = sw.OutFrontWorld;
				Vector3 val3 = sw.T.TransformDirection(sw.Up);
				Vector3 val4 = sw.T.TransformDirection(sw.Fwd);
				val5 = Vector3.Cross(val3, val4);
				Vector3 normalized = ((Vector3)(ref val5)).normalized;
				float num14 = Mathf.Abs(Vector3.Dot(outFrontWorld, normalized));
				float num15 = Vector3.Dot(outFrontWorld, -val3);
				Vector3 val6 = sw.SocketFrontWorld - (Sling.FirePoint(rifle).position + val4 * Vector3.Dot(sw.SocketFrontWorld - Sling.FirePoint(rifle).position, val4));
				Check("front rotation 90: swivel on the side of the gun", num14 > 0.95f && Mathf.Abs(num15) < 0.2f, $"points {num14:0.00} sideways, {num15:0.00} down; socket {Vector3.Dot(val6, normalized) * 100f:0.0} cm to the side of the barrel line");
				Check("back end unchanged (rotation is per end)", Vector3.Dot(sw.OutBackWorld, -val3) > 0.95f);
				rb.isKinematic = true;
				((Component)rb).transform.SetPositionAndRotation(spot + Vector3.up * 0.3f, Quaternion.LookRotation(side, Vector3.up));
				rb.position = ((Component)rb).transform.position;
				yield return (object)new WaitForSeconds(1.2f);
				shotTarget = sw.SocketFrontWorld;
				Shot("D_front_rotated_90", 0.45f);
				rb.isKinematic = false;
			}
			EditMode.ApplyTo(barcode, delegate(GunConfig cfg)
			{
				cfg.Mode = SlingMode.Always;
				cfg.Swivels = false;
			});
			Sling sling3 = SlingManager.Find(rifle);
			Check("swivels off (per gun): strap meets the gun", sling3 != null && !sling3.Config.Swivels && Vector3.Distance(sling3.Front, sling3.SocketFrontWorld) < 0.01f);
			Check("textures: every style has its picture", (Object)(object)Materials.For(SlingStyle.Leather).mainTexture != (Object)null && (Object)(object)Materials.For(SlingStyle.Brown).mainTexture != (Object)null && (Object)(object)Materials.For(SlingStyle.Green).mainTexture != (Object)null && (Object)(object)Materials.For(SlingStyle.Black).mainTexture != (Object)null);
			GunStore.Reset(barcode);
			EditMode.Refresh(barcode);
			EditMode.ApplyTo(barcode, delegate(GunConfig cfg)
			{
				cfg.Mode = SlingMode.Always;
			});
			rb.isKinematic = true;
			((Component)rb).transform.SetPositionAndRotation(spot + Vector3.up * 0.3f, Quaternion.LookRotation(side, Vector3.up));
			rb.position = ((Component)rb).transform.position;
			yield return (object)new WaitForSeconds(1.5f);
			Sling sling4 = SlingManager.Find(rifle);
			if (sling4 != null)
			{
				shotTarget = sling4.SocketBackWorld;
				Shot("D_swivel_closeup", 0.35f);
				shotTarget = sling4.SocketFrontWorld;
				Shot("D_swivel_front", 0.35f);
			}
			rb.isKinematic = false;
			Hand hand = Player.RightHand;
			Grip grip = rifle.triggerGrip;
			bool[] array3;
			if ((Object)(object)hand != (Object)null && (Object)(object)grip != (Object)null && Controllers(out XRController right, out XRController left))
			{
				List<MoveRun> runs = new List<MoveRun>();
				EditMode.ApplyTo(barcode, delegate(GunConfig cfg)
				{
					cfg.Mode = SlingMode.Always;
				});
				rb.isKinematic = true;
				((Component)rb).transform.position = spot + Vector3.up * 1.5f;
				rb.position = ((Component)rb).transform.position;
				Vector3 val7 = head - Vector3.up * 1.6f + Vector3.up * 0.05f - side * 1.5f - fwd * 1f;
				Player.RigManager.Teleport(val7, fwd, true);
				yield return (object)new WaitForSeconds(1f);
				_move = Vector2.zero;
				_jump = false;
				_driving = true;
				for (int k = 0; k < 8; k++)
				{
					_grip = false;
					yield return (object)new WaitForSeconds(0.2f);
					rb.isKinematic = true;
					Vector3 val8 = ((Component)hand).transform.position - ((Component)grip).transform.position;
					Transform transform = ((Component)rb).transform;
					transform.position += val8;
					rb.position = ((Component)rb).transform.position;
					yield return (object)new WaitForSeconds(0.15f);
					_grip = true;
					_gripFrame = Time.frameCount;
					yield return (object)new WaitForSeconds(0.15f);
					try
					{
						if (!hand.HasAttachedObject())
						{
							grip.OnGrabConfirm(hand, true);
						}
					}
					catch (Exception ex)
					{
						Note("grab confirm failed: " + ex.Message);
					}
					yield return (object)new WaitForSeconds(0.2f);
					rb.isKinematic = false;
					yield return (object)new WaitForSeconds(0.5f);
					bool flag = false;
					try
					{
						int num16;
						if (hand.HasAttachedObject())
						{
							val5 = ((Component)grip).transform.position - ((Component)hand).transform.position;
							num16 = ((((Vector3)(ref val5)).magnitude < 0.4f) ? 1 : 0);
						}
						else
						{
							num16 = 0;
						}
						flag = (byte)num16 != 0;
					}
					catch
					{
					}
					DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(49, 3);
					defaultInterpolatedStringHandler.AppendLiteral("  grab attempt ");
					defaultInterpolatedStringHandler.AppendFormatted(k + 1);
					defaultInterpolatedStringHandler.AppendLiteral(": holding ");
					defaultInterpolatedStringHandler.AppendFormatted(((Object)(object)hand.m_CurrentAttachedGO != (Object)null) ? ((Object)hand.m_CurrentAttachedGO).name : "nothing");
					defaultInterpolatedStringHandler.AppendLiteral(", grip ");
					val5 = ((Component)grip).transform.position - ((Component)hand).transform.position;
					defaultInterpolatedStringHandler.AppendFormatted(((Vector3)(ref val5)).magnitude * 100f, "0");
					defaultInterpolatedStringHandler.AppendLiteral(" cm from the hand");
					Note(defaultInterpolatedStringHandler.ToStringAndClear());
					if (flag)
					{
						break;
					}
				}
				array3 = new bool[2] { true, false };
				foreach (bool withSling in array3)
				{
					EditMode.ApplyTo(barcode, delegate(GunConfig cfg)
					{
						cfg.Mode = (withSling ? SlingMode.Always : SlingMode.Never);
					});
					yield return (object)new WaitForSeconds(1f);
					Sling sling5 = SlingManager.Find(rifle);
					bool flag2 = false;
					try
					{
						int num17;
						if (hand.HasAttachedObject())
						{
							val5 = ((Component)grip).transform.position - ((Component)hand).transform.position;
							num17 = ((((Vector3)(ref val5)).magnitude < 0.4f) ? 1 : 0);
						}
						else
						{
							num17 = 0;
						}
						flag2 = (byte)num17 != 0;
					}
					catch
					{
					}
					if (withSling)
					{
						Check("holding the rifle (sling on it, and it knows it's held)", flag2 && sling5 != null && sling5.Held);
					}
					else
					{
						Check("holding the rifle again (no sling this time)", flag2 && sling5 == null);
					}
					MoveRun run = new MoveRun
					{
						Sling = withSling
					};
					yield return Move(run, rifle, ((Component)grip).transform, ((Component)hand).transform, sling5);
					runs.Add(run);
					Note($"  {(withSling ? "with sling   " : "without sling")}: walked {run.Walked:0.00} m in 2.5 s, jumps {string.Join(" / ", run.Jumps.Select((float j) => j.ToString("0.00")))} m, gun in hand: avg {run.HandGap * 100f:0.0} cm off, jitter {run.Jitter * 1000f:0.0} mm/frame, strap pull while held {run.Pull:0} N, most stretch {run.MaxStretch * 100f:0.0}% (over 4% in {run.Over4} of {run.Samples} frames)");
					if (withSling)
					{
						shotTarget = ((Component)rifle).transform.position;
						Shot("E_walking_with_sling", 1.6f);
					}
				}
				_driving = false;
				try
				{
					hand.DetachObject();
				}
				catch
				{
				}
				MoveRun moveRun = runs[0];
				MoveRun moveRun2 = runs[1];
				Check("walking speed the same with the sling", moveRun2.Walked > 0.3f && Mathf.Abs(moveRun.Walked - moveRun2.Walked) / moveRun2.Walked < 0.05f, $"{moveRun.Walked:0.00} m vs {moveRun2.Walked:0.00} m");
				float num18 = Median(moveRun.Jumps);
				float num19 = Median(moveRun2.Jumps);
				Check("jumping not held back by the sling", num19 > 0.1f && num18 >= num19 * 0.92f, $"{num18:0.00} m vs {num19:0.00} m");
				Check("the sling never pulls on a held gun", moveRun.Pull <= 0.001f, $"{moveRun.Pull:0.0} N");
				Check("strap barely stretches while walking and jumping", moveRun.MaxStretch < 0.04f, $"most {moveRun.MaxStretch * 100f:0.0}%");
				Check("gun stays smooth in the hand with the sling", moveRun.Jitter <= moveRun2.Jitter * 1.3f + 0.002f && moveRun.HandGap <= moveRun2.HandGap + 0.01f, $"jitter {moveRun.Jitter * 1000f:0.0} vs {moveRun2.Jitter * 1000f:0.0} mm/frame, gap {moveRun.HandGap * 100f:0.0} vs {moveRun2.HandGap * 100f:0.0} cm");
			}
			else
			{
				Check("could drive the player (FlatPlayer controllers, hand, gun grip)", ok: false, $"hand {(Object)(object)hand != (Object)null}, grip {(Object)(object)grip != (Object)null}, controllers {Controllers(out left, out right)}");
			}
			GunStore.Reset(barcode);
			EditMode.Refresh(barcode);
			List<float> times = new List<float>();
			Hand fhand = Player.RightHand;
			Rigidbody componentInParent = ((Component)rifle).GetComponentInParent<Rigidbody>();
			ForcePullGrip fpg = ((componentInParent != null) ? ((Component)componentInParent).GetComponentInChildren<ForcePullGrip>(true) : null);
			bool sawPulling = false;
			array3 = new bool[2] { true, false };
			float took;
			float t0;
			foreach (bool withSling2 in array3)
			{
				EditMode.ApplyTo(barcode, delegate(GunConfig cfg)
				{
					cfg.Mode = (withSling2 ? SlingMode.Always : SlingMode.Never);
				});
				try
				{
					if (fhand != null)
					{
						fhand.DetachObject();
					}
				}
				catch
				{
				}
				rb.isKinematic = false;
				rb.velocity = Vector3.zero;
				rb.angularVelocity = Vector3.zero;
				Vector3 val9 = Player.Head.position + fwd * 2.2f;
				val9.y = Floor(val9) + 0.1f;
				((Component)rb).transform.SetPositionAndRotation(val9, Quaternion.LookRotation(side, Vector3.up));
				rb.position = ((Component)rb).transform.position;
				yield return (object)new WaitForSeconds(2.5f);
				if ((Object)(object)fpg == (Object)null || (Object)(object)fhand == (Object)null)
				{
					break;
				}
				_move = Vector2.zero;
				_jump = false;
				_grip = true;
				_gripFrame = Time.frameCount;
				_driving = true;
				t0 = Time.time;
				took = 9f;
				try
				{
					fpg.Pull(fhand);
				}
				catch (Exception ex2)
				{
					Note("force pull failed: " + ex2.Message);
				}
				Sling sp = SlingManager.Find(rifle);
				while (Time.time - t0 < 3f)
				{
					if (sp != null && sp.Pulling)
					{
						sawPulling = true;
					}
					bool flag3 = false;
					try
					{
						int num20;
						if (!fhand.HasAttachedObject())
						{
							val5 = rb.position - ((Component)fhand).transform.position;
							num20 = ((((Vector3)(ref val5)).magnitude < 0.25f) ? 1 : 0);
						}
						else
						{
							num20 = 1;
						}
						flag3 = (byte)num20 != 0;
					}
					catch
					{
					}
					if (flag3)
					{
						took = Time.time - t0;
						break;
					}
					yield return null;
				}
				times.Add(took);
				_driving = false;
				_grip = false;
				try
				{
					fhand.DetachObject();
				}
				catch
				{
				}
				yield return (object)new WaitForSeconds(0.5f);
			}
			if (times.Count == 2)
			{
				Check("force grab: comes to the hand as fast with the sling", times[1] < 3f && times[0] <= times[1] * 1.25f + 0.15f, $"{times[0]:0.00} s with the sling, {times[1]:0.00} s without (sling saw the pull: {sawPulling})");
			}
			else
			{
				Check("force grab: could force pull (ForcePullGrip, hand)", ok: false, $"grip {(Object)(object)fpg != (Object)null}, hand {(Object)(object)fhand != (Object)null}");
			}
			EditMode.ApplyTo(barcode, delegate(GunConfig cfg)
			{
				cfg.Mode = SlingMode.Always;
			});
			_driving = false;
			_grip = false;
			try
			{
				Hand rightHand = Player.RightHand;
				if (rightHand != null)
				{
					rightHand.DetachObject();
				}
				Hand leftHand = Player.LeftHand;
				if (leftHand != null)
				{
					leftHand.DetachObject();
				}
			}
			catch
			{
			}
			yield return (object)new WaitForSeconds(1f);
			Sling sling6 = SlingManager.Find(rifle);
			Note($"  before dropping: held {sling6?.Held ?? false}, right hand holding {(Object)(object)Player.RightHand != (Object)null && Player.RightHand.HasAttachedObject()}");
			took = 0f;
			t0 = 0f;
			for (int k = 0; k < 5; k++)
			{
				rb.isKinematic = false;
				rb.velocity = Vector3.zero;
				rb.angularVelocity = Random.insideUnitSphere * 3f;
				((Component)rb).transform.SetPositionAndRotation(spot + Vector3.up * 1.4f + side * (0.3f * (float)k - 0.6f), Random.rotation);
				rb.position = ((Component)rb).transform.position;
				rb.rotation = ((Component)rb).transform.rotation;
				float tEnd = Time.time + 2.2f;
				while (Time.time < tEnd)
				{
					float num21 = took;
					val5 = rb.velocity;
					took = Mathf.Max(num21, ((Vector3)(ref val5)).magnitude);
					yield return null;
				}
				yield return (object)new WaitForSeconds(1.3f);
				float num22 = t0;
				val5 = rb.velocity;
				float magnitude = ((Vector3)(ref val5)).magnitude;
				val5 = rb.angularVelocity;
				t0 = Mathf.Max(num22, magnitude + ((Vector3)(ref val5)).magnitude * 0.1f);
			}
			Check("dropped 5 times: never flung by the strap", took < 6.5f, $"fastest {took:0.0} m/s");
			Check("dropped 5 times: settles still (no jitter)", t0 < 0.08f, $"still moving {t0:0.000} after 3.5 s");
			Sling sling7 = SlingManager.Find(rifle);
			if (sling7 != null)
			{
				int samples;
				float num23 = sling7.FlatScore(out samples);
				Check("strap lies flat on the floor", samples < 3 || num23 > 0.8f, $"face-down {num23:0.00} over {samples} resting points");
				shotTarget = sling7.Front;
				Shot("F_looped_end", 0.3f);
				shotTarget = (sling7.Front + sling7.Back) * 0.5f;
				Shot("F_lying_flat", 1f);
			}
			try
			{
				SceneStreamer.Load(new Barcode("c2534c5a-2c4c-4b44-b076-203b5363656e"), (Barcode)null);
			}
			catch (Exception ex3)
			{
				Note("level load failed: " + ex3.Message);
			}
			t0 = Time.realtimeSinceStartup + 20f;
			while (!HelperMethods.IsLoading() && Time.realtimeSinceStartup < t0)
			{
				yield return null;
			}
			t0 = Time.realtimeSinceStartup + 120f;
			while (HelperMethods.IsLoading() && Time.realtimeSinceStartup < t0)
			{
				yield return null;
			}
			yield return (object)new WaitForSeconds(8f);
			Vector3 position = Player.Head.position;
			Vector3 f2 = Player.Head.forward;
			f2.y = 0f;
			((Vector3)(ref f2)).Normalize();
			Vector3 sp2 = position + f2 * 1.2f;
			sp2.y = Floor(sp2) + 0.7f;
			Gun g2 = null;
			yield return Spawn("c1534c5a-a6b5-4177-beb8-04d947756e41", sp2, delegate(Gun? val10)
			{
				g2 = val10;
			});
			if ((Object)(object)g2 != (Object)null)
			{
				EditMode.ApplyTo(barcode, delegate(GunConfig cfg)
				{
					cfg.Mode = SlingMode.Always;
					cfg.Style = SlingStyle.Leather;
				});
				Sling sp = SlingManager.Ensure(g2);
				Rigidbody componentInParent2 = ((Component)g2).GetComponentInParent<Rigidbody>();
				if ((Object)(object)componentInParent2 != (Object)null)
				{
					componentInParent2.isKinematic = true;
					((Component)componentInParent2).transform.SetPositionAndRotation(sp2 + Vector3.up * 0.5f, Quaternion.LookRotation(Vector3.Cross(Vector3.up, f2), Vector3.up));
					componentInParent2.position = ((Component)componentInParent2).transform.position;
				}
				yield return (object)new WaitForSeconds(1.5f);
				bool flag4 = sp != null && !Materials.Broken(Materials.For(SlingStyle.Leather)) && (Object)(object)Materials.For(SlingStyle.Leather).mainTexture != (Object)null;
				bool flag5 = !Materials.Broken(Materials.Metal);
				Check("after a level change: textured strap and swivels still draw", flag4 && flag5, $"strap {(flag4 ? "ok" : "broken")}, swivels {(flag5 ? "ok" : "broken")}, shader {LitShader.Info}");
				if (sp != null)
				{
					shotTarget = (sp.Front + sp.Back) * 0.5f + Vector3.down * 0.15f;
					Shot("G_tuscany_leather", 1f);
				}
				GunStore.Reset(barcode);
			}
			else
			{
				Check("spawn a rifle in Tuscany", ok: false);
			}
			Note($"PERF  slings step avg {((SlingManager.StepSamples > 0) ? (SlingManager.StepMs / (double)SlingManager.StepSamples) : 0.0):0.000} ms, max {SlingManager.StepMsMax:0.00} ms ({SlingManager.Count} slings)");
			Note("Fusion sync: " + (Net.FusionAvailable ? "available" : "LabFusion not loaded"));
			Finish(savedAuto);
			static float Median(List<float> l)
			{
				List<float> list = l.OrderBy((float x) => x).ToList();
				if (list.Count <= 0)
				{
					return 0f;
				}
				return list[list.Count / 2];
			}
		}

		private static bool Controllers(out XRController? left, out XRController? right)
		{
			left = (right = null);
			try
			{
				Type type = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == "FlatPlayer")?.GetType("FlatPlayer.FlatBooter");
				object? obj = type?.GetField("LeftController", BindingFlags.Static | BindingFlags.Public)?.GetValue(null);
				object? obj2 = ((obj is Il2CppObjectBase) ? obj : null);
				left = ((obj2 != null) ? ((Il2CppObjectBase)obj2).TryCast<XRController>() : null);
				object? obj3 = type?.GetField("RightController", BindingFlags.Static | BindingFlags.Public)?.GetValue(null);
				object? obj4 = ((obj3 is Il2CppObjectBase) ? obj3 : null);
				right = ((obj4 != null) ? ((Il2CppObjectBase)obj4).TryCast<XRController>() : null);
			}
			catch
			{
			}
			if (left != null)
			{
				return right != null;
			}
			return false;
		}

		internal static void DriveInput()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			if (_driving && Controllers(out XRController left, out XRController right))
			{
				left.Joystick2DAxis = _move;
				right.AButton = _jump;
				right.AButtonDown = _jump && Time.frameCount - _jumpFrame <= 3;
				right.AButtonUp = !_jump && Time.frameCount - _releaseFrame <= 3;
				float num = (_grip ? 1f : 0f);
				float gripForce = (right.Grip = num);
				right.GripForce = gripForce;
				right.GripButton = _grip;
				right.GripButtonDown = _grip && Time.frameCount - _gripFrame <= 4;
				right.GripButtonUp = false;
			}
		}

		private static IEnumerator Move(MoveRun run, Gun gun, Transform grip, Transform hand, Sling? sling)
		{
			Transform pelvis = ((Rig)Player.RigManager.physicsRig).m_pelvis;
			_driving = true;
			yield return (object)new WaitForSeconds(0.5f);
			Vector3 start = pelvis.position;
			float gapSum = 0f;
			float jitSum = 0f;
			int n = 0;
			Vector3 lastOff = grip.position - hand.position;
			_move = new Vector2(0f, 1f);
			float until = Time.time + 2.5f;
			while (Time.time < until)
			{
				Sample();
				yield return null;
			}
			_move = Vector2.zero;
			Vector3 val = pelvis.position - start;
			val.y = 0f;
			run.Walked = ((Vector3)(ref val)).magnitude;
			yield return (object)new WaitForSeconds(0.8f);
			for (int j = 0; j < 5; j++)
			{
				float baseY = pelvis.position.y;
				float peak = baseY;
				_jump = true;
				_jumpFrame = Time.frameCount;
				float release = Time.time + 0.35f;
				float end = Time.time + 2.2f;
				while (Time.time < end)
				{
					if (_jump && Time.time >= release)
					{
						_jump = false;
						_releaseFrame = Time.frameCount;
					}
					peak = Mathf.Max(peak, pelvis.position.y);
					Sample();
					yield return null;
				}
				run.Jumps.Add(peak - baseY);
			}
			_jump = false;
			run.HandGap = ((n > 0) ? (gapSum / (float)n) : 0f);
			run.Jitter = ((n > 0) ? (jitSum / (float)n) : 0f);
			void Sample()
			{
				//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_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_0037: 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_0052: Unknown result type (might be due to invalid IL or missing references)
				//IL_0053: Unknown result type (might be due to invalid IL or missing references)
				Vector3 val2 = grip.position - hand.position;
				gapSum += ((Vector3)(ref val2)).magnitude;
				float num = jitSum;
				Vector3 val3 = val2 - lastOff;
				jitSum = num + ((Vector3)(ref val3)).magnitude;
				lastOff = val2;
				n++;
				if (sling != null)
				{
					run.Pull += sling.LastForce;
					run.MaxStretch = Mathf.Max(run.MaxStretch, sling.Stretch);
					run.Samples++;
					if (sling.Stretch > 0.04f)
					{
						run.Over4++;
					}
				}
			}
		}

		internal static void FixedTick()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_push != (Object)null && !((Il2CppObjectBase)_push).WasCollected)
			{
				_push.AddForce(_pushAccel, (ForceMode)5);
			}
		}

		private static void Finish(bool savedAuto)
		{
			Settings.AutoSling.Value = savedAuto;
			SlingManager.Rescan();
			GunStore.SaveNow();
			Note($"===== DONE: {pass} passed, {fail} failed =====");
			try
			{
				File.WriteAllLines(ReportPath, Report);
			}
			catch
			{
			}
			running = false;
			try
			{
				if (File.Exists(Flag) && File.ReadAllText(Flag).Contains("quit"))
				{
					Application.Quit();
				}
			}
			catch
			{
			}
		}
	}
	internal sealed class WaitForFixedUpdateFrames : IEnumerator
	{
		private int frames = 3;

		public object? Current => null;

		public bool MoveNext()
		{
			return frames-- > 0;
		}

		public void Reset()
		{
		}
	}
	internal static class Settings
	{
		private static MelonPreferences_Category _cat;

		internal static MelonPreferences_Entry<bool> Enabled;

		internal static MelonPreferences_Entry<bool> AutoSling;

		internal static MelonPreferences_Entry<int> Style;

		private static MelonPreferences_Entry<int> _version;

		internal static SlingStyle DefaultStyle
		{
			get
			{
				SlingStyle value = (SlingStyle)Style.Value;
				if (!Enum.IsDefined(typeof(SlingStyle), value) || value == SlingStyle.Default)
				{
					return SlingStyle.Black;
				}
				return value;
			}
		}

		internal static void Create()
		{
			_cat = MelonPreferences.CreateCategory("OpenSling");
			Enabled = _cat.CreateEntry<bool>("Enabled", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			AutoSling = _cat.CreateEntry<bool>("AutoSling", false, (string)null, "Every long gun gets a sling (pistols and utility tools never do). Off: add one per gun in Edit Mode.", false, false, (ValueValidator)null, (string)null);
			Style = _cat.CreateEntry<int>("DefaultStyle", 0, (string)null, "0 Black, 1 Leather, 2 Black with tightener, 3 Green, 4 Brown", false, false, (ValueValidator)null, (string)null);
			_version = _cat.CreateEntry<int>("SettingsVersion", 1, (string)null, (string)null, true, false, (ValueValidator)null, (string)null);
			if (_version.Value < 2)
			{
				AutoSling.Value = false;
				_version.Value = 2;
				_cat.SaveToFile(false);
			}
		}

		private static void Save()
		{
			_cat.SaveToFile(false);
		}

		internal static void BuildMenu()
		{
			//IL_0019: 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_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			Page obj = Page.Root.CreatePage("OpenSling", new Color(0.55f, 0.35f, 0.2f), 0, true);
			obj.CreateBool("Enabled", Color.white, Enabled.Value, (Action<bool>)delegate(bool v)
			{
				Enabled.Value = v;
				Save();
				SlingManager.Rescan();
			});
			obj.CreateBool("Auto Sling Guns", Color.green, AutoSling.Value, (Action<bool>)delegate(bool v)
			{
				AutoSling.Value = v;
				Save();
				SlingManager.Rescan();
			});
			obj.CreateEnum("Default Style", Color.yellow, (Enum)DefaultStyle, (Action<Enum>)delegate(Enum v)
			{
				Style.Value = (int)(SlingStyle)(object)v;
				Save();
				SlingManager.Rescan();
			});
			EditMode.Build(obj);
		}
	}
	internal static class EditMode
	{
		internal static bool On;

		internal static Sling? Held;

		private static Gun? _heldGun;

		private static string _heldBarcode = "";

		private static float _nextCheck;

		private static FunctionElement? _label;

		private static EnumElement? _mode;

		private static EnumElement? _style;

		private static BoolElement? _swivels;

		private static FloatElement? _ff;

		private static FloatElement? _fu;

		private static FloatElement? _bf;

		private static FloatElement? _bu;

		private static FloatElement? _len;

		private static FloatElement? _width;

		private static FloatElement? _rollF;

		private static FloatElement? _rollB;

		internal static void Build(Page root)
		{
			//IL_0006: 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_0049: 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_00b7: 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_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_0259: 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_02d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_031e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0365: Unknown result type (might be due to invalid IL or missing references)
			root.CreateBool("Edit Mode", Color.cyan, false, (Action<bool>)delegate(bool v)
			{
				On = v;
				_nextCheck = 0f;
			});
			Page obj = root.CreatePage("Edit Held Gun", Color.cyan, 0, true);
			_label = obj.CreateFunction("Gun: (hold one)", Color.white, (Action)delegate
			{
				_nextCheck = 0f;
			});
			_mode = obj.CreateEnum("Sling On This Gun", Color.green, (Enum)SlingMode.Auto, (Action<Enum>)delegate(Enum v)
			{
				Change(delegate(GunConfig c)
				{
					c.Mode = (SlingMode)(object)v;
				});
			});
			_style = obj.CreateEnum("Style", Color.yellow, (Enum)SlingStyle.Default, (Action<Enum>)delegate(Enum v)
			{
				Change(delegate(GunConfig c)
				{
					c.Style = (SlingStyle)(object)v;
				});
			});
			_ff = obj.CreateFloat("Front Forward/Back", Color.green, 0f, 0.01f, -0.5f, 0.5f, (Action<float>)delegate(float v)
			{
				Change(delegate(GunConfig c)
				{
					c.FrontForward = v;
				});
			});
			_fu = obj.CreateFloat("Front Up/Down", Color.green, 0f, 0.005f, -0.3f, 0.3f, (Action<float>)delegate(float v)
			{
				Change(delegate(GunConfig c)
				{
					c.FrontUp = v;
				});
			});
			_bf = obj.CreateFloat("Back Forward/Back", Color.red, 0f, 0.01f, -0.5f, 0.5f, (Action<float>)delegate(float v)
			{
				Change(delegate(GunConfig c)
				{
					c.BackForward = v;
				});
			});
			_bu = obj.CreateFloat("Back Up/Down", Color.red, 0f, 0.005f, -0.3f, 0.3f, (Action<float>)delegate(float v)
			{
				Change(delegate(GunConfig c)
				{
					c.BackUp = v;
				});
			});
			_len = obj.CreateFloat("Sling Length", Color.magenta, 1f, 0.05f, 0.3f, 4f, (Action<float>)delegate(float v)
			{
				Change(delegate(GunConfig c)
				{
					c.Length = v;
				});
			});
			_width = obj.CreateFloat("Sling Width (m)", Color.magenta, 0.032f, 0.002f, 0.012f, 0.07f, (Action<float>)delegate(float v)
			{
				Change(delegate(GunConfig c)
				{
					c.Width = v;
				});
			});
			_swivels = obj.CreateBool("Show Swivels", Color.gray, true, (Action<bool>)delegate(bool v)
			{
				Change(delegate(GunConfig c)
				{
					c.Swivels = v;
				});
			});
			_rollF = obj.CreateFloat("Front Rotation (deg)", Color.green, 0f, 15f, -180f, 180f, (Action<float>)delegate(float v)
			{
				Change(delegate(GunConfig c)
				{
					c.RollFront = v;
				});
			});
			_rollB = obj.CreateFloat("Back Rotation (deg)", Color.red, 0f, 15f, -180f, 180f, (Action<float>)delegate(float v)
			{
				Change(delegate(GunConfig c)
				{
					c.RollBack = v;
				});
			});
			obj.CreateFunction("Reset This Gun", Color.red, (Action)ResetHeld);
		}

		private static Gun? HeldGun()
		{
			try
			{
				Gun componentInHand = Player.GetComponentInHand<Gun>(Player.RightHand);
				if ((Object)(object)componentInHand == (Object)null)
				{
					componentInHand = Player.GetComponentInHand<Gun>(Player.LeftHand);
				}
				return componentInHand;
			}
			catch
			{
				return null;
			}
		}

		internal static void Update()
		{
			if (Time.unscaledTime < _nextCheck)
			{
				return;
			}
			_nextCheck = Time.unscaledTime + 0.25f;
			Gun val = HeldGun();
			if ((Object)(object)val != (Object)null && (Object)(object)_heldGun != (Object)null && ((Il2CppObjectBase)val).Pointer == ((Il2CppObjectBase)_heldGun).Pointer)
			{
				Held = SlingManager.Find(val);
				return;
			}
			_heldGun = val;
			Held = (((Object)(object)val != (Object)null) ? SlingManager.Find(val) : null);
			_heldBarcode = "";
			if ((Object)(object)val != (Object)null && SlingManager.Describe(val, out string barcode, out string title, out List<string> _))
			{
				_heldBarcode = barcode;
				SetLabel("Gun: " + title);
				Show(GunStore.Get(barcode));
			}
			else
			{
				SetLabel("Gun: (hold one)");
			}
		}

		private static void SetLabel(string text)
		{
			try
			{
				if (_label != null)
				{
					((Element)_label).ElementName = text;
				}
			}
			catch
			{
			}
		}

		private static void Show(GunConfig c)
		{
			try
			{
				if (_mode != null)
				{
					_mode.Value = c.Mode;
				}
				if (_style != null)
				{
					_style.Value = c.Style;
				}
				if (_ff != null)
				{
					_ff.Value = c.FrontForward;
				}
				if (_fu != null)
				{
					_fu.Value = c.FrontUp;
				}
				if (_bf != null)
				{
					_bf.Value = c.BackForward;
				}
				if (_bu != null)
				{
					_bu.Value = c.BackUp;
				}
				if (_len != null)
				{
					_len.Value = c.Length;
				}
				if (_width != null)
				{
					_width.Value = c.Width;
				}
				if (_rollF != null)
				{
					_rollF.Value = c.RollFront;
				}
				if (_swivels != null)
				{
					_swivels.Value = c.Swivels;
				}
				if (_rollB != null)
				{
					_rollB.Value = c.RollBack;
				}
			}
			catch (Exception e)
			{
				Main.LogOnce("edit-show", e);
			}
		}

		private static void Change(Action<GunConfig> edit)
		{
			if (On && !string.IsNullOrEmpty(_heldBarcode))
			{
				ApplyTo(_heldBarcode, edit);
			}
		}

		internal static void ApplyTo(string barcode, Action<GunConfig> edit)
		{
			GunConfig gunConfig = GunStore.Get(barcode).Clone();
			edit(gunConfig);
			GunStore.Set(barcode, gunConfig);
			Refresh(barcode);
		}

		private static void ResetHeld()
		{
			if (!string.IsNullOrEmpty(_heldBarcode))
			{
				GunStore.Reset(_heldBarcode);
				Show(new GunConfig());
				Refresh(_heldBarcode);
			}
		}

		internal static void Refresh(string barcode)
		{
			SlingManager.Rescan();
			foreach (Sling item in SlingManager.All)
			{
				if (item.Barcode == barcode)
				{
					Net.ConfigChanged(item);
				}
			}
			if ((Object)(object)_heldGun != (Object)null)
			{
				SlingManager.Ensure(_heldGun);
			}
		}
	}
	internal sealed class Sling
	{
		internal const int N = 16;

		internal const float Radius = 0.012f;

		internal const float MaxStretch = 0.06f;

		private const float EndGive = 0.35f;

		public readonly Gun Gun;

		public readonly Rigidbody? Rb;

		public readonly Transform T;

		public readonly string Barcode;

		public readonly string Title;

		public readonly bool TooShort;

		public Vector3 FrontBase;

		public Vector3 BackBase;

		public Vector3 Fwd;

		public Vector3 Up;

		public float BaseLength;

		public float GunLength;

		public GunConfig Config = new GunConfig();

		public SlingStyle Style;

		public Vector3 FrontLocal;

		public Vector3 BackLocal;

		public float Rest;

		internal readonly Vector3[] P = (Vector3[])(object)new Vector3[16];

		internal readonly Vector3[] Prev = (Vector3[])(object)new Vector3[16];

		internal readonly Vector3[] Last = (Vector3[])(object)new Vector3[16];

		private readonly bool[] contact = new bool[16];

		internal readonly Vector3[] ContactNormal = (Vector3[])(object)new Vector3[16];

		private readonly bool[] contactSolid = new bool[16];

		private readonly string[] contactWhat = new string[16];

		internal string LastSupportBy = "";

		private readonly Vector3[] Mid = (Vector3[])(object)new Vector3[16];

		private readonly bool[] held = new bool[16];

		private float endGive = 0.35f;

		private bool placed;

		private bool visible;

		private int stillSteps;

		private bool asleep;

		private Vector3 sleepPos;

		private Quaternion sleepRot;

		private int sleepCheck;

		private int sleepHits;

		internal float Stretch;

		internal float LastForce;

		internal float LastSupport;

		internal bool Networked;

		internal bool IsOwner = true;

		internal ushort EntityId;

		internal readonly Vector3[] RemoteLocal = (Vector3[])(object)new Vector3[16];

		internal float RemoteTime = -10f;

		internal readonly Vector3[] SentLocal = (Vector3[])(object)new Vector3[16];

		internal float NextSend;

		private readonly HashSet<IntPtr> own = new HashSet<IntPtr>();

		private readonly Il2CppArrayBase<Grip> grips;

		private readonly Il2CppArrayBase<InteractableHost> hostsAll;

		internal const float StrapMass = 0.15f;

		internal float HeldForce;

		private readonly SlingView view;

		private static readonly Il2CppStructArray<RaycastHit> Hits = new Il2CppStructArray<RaycastHit>(8L);

		private static readonly Il2CppReferenceArray<Collider> Overlaps = new Il2CppReferenceArray<Collider>(16L);

		private static int _mask = -1;

		private List<Collider> fitCols = new List<Collider>();

		private Vector3 fitOrigin;

		private float fitMidU;

		private float fitReach;

		public float FrontF;

		public float BackF;

		public Vector3 SocketFront;

		public Vector3 SocketBack;

		public Vector3 OutFront;

		public Vector3 OutBack;

		internal const float SwivelDrop = 0.03f;

		private static SphereCollider? _probe;

		public bool Pulling
		{
			get
			{
				try
				{
					foreach (InteractableHost item in hostsAll)
					{
						if ((Object)(object)item != (Object)null && item.IsPulling)
						{
							return true;
						}
					}
				}
				catch
				{
				}
				return false;
			}
		}

		public Vector3 Front => T.TransformPoint(FrontLocal);

		public Vector3 Back => T.TransformPoint(BackLocal);

		public Vector3 SocketFrontWorld => T.TransformPoint(SocketFront);

		public Vector3 SocketBackWorld => T.TransformPoint(SocketBack);

		public Vector3 OutFrontWorld => T.TransformDirection(OutFront);

		public Vector3 OutBackWorld => T.TransformDirection(OutBack);

		public bool Held
		{
			get
			{
				try
				{
					foreach (Grip grip in grips)
					{
						if ((Object)(object)grip != (Object)null && grip.attachedHands != null && grip.attachedHands.Count > 0)
						{
							return true;
						}
					}
				}
				catch
				{
				}
				return false;
			}
		}

		internal static int Mask
		{
			get
			{
				if (_mask == -1)
				{
					int num = -1;
					string[] array = new string[4] { "Ignore Raycast", "UI", "TransparentFX", "Water" };
					for (int i = 0; i < array.Length; i++)
					{
						int num2 = LayerMask.NameToLayer(array[i]);
						if (num2 >= 0)
						{
							num &= ~(1 << num2);
						}
					}
					_mask = num;
				}
				return _mask;
			}
		}

		public bool Active
		{
			get
			{
				if ((Object)(object)Gun != (Object)null && !((Il2CppObjectBase)Gun).WasCollected)
				{
					return ((Component)Gun).gameObject.activeInHierarchy;
				}
				return false;
			}
		}

		private static SphereCollider Probe
		{
			get
			{
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0023: Unknown result type (might be due to invalid IL or missing references)
				//IL_0029: Expected O, but got Unknown
				//IL_0034: 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_0057: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)_probe == (Object)null || ((Il2CppObjectBase)_probe).WasCollected)
				{
					GameObject val = new GameObject("OpenSling_Probe");
					Object.DontDestroyOnLoad((Object)val);
					int num = LayerMask.NameToLayer("Ignore Raycast");
					val.layer = ((num >= 0) ? num : 2);
					val.transform.position = new Vector3(0f, -10000f, 0f);
					_probe = val.AddComponent<SphereCollider>();
					((Collider)_probe).isTrigger = true;
					_probe.radius = 0.012f;
				}
				return _probe;
			}
		}

		internal GameObject? ViewRoot => view.Root;

		private bool Solid(Collider col)
		{
			try
			{
				Rigidbody attachedRigidbody = col.attachedRigidbody;
				if ((Object)(object)attachedRigidbody == (Object)null || attachedRigidbody.isKinematic)
				{
					return true;
				}
				if ((Object)(object)Rb != (Object)null && ((Il2CppObjectBase)attachedRigidbody).Pointer == ((Il2CppObjectBase)Rb).Pointer)
				{
					return false;
				}
				return (Object)(object)Rb == (Object)null || attachedRigidbody.mass >= Rb.mass * 2f;
			}
			catch
			{
				return false;
			}
		}

		internal bool Touching(int i)
		{
			return contact[i];
		}

		internal static Transform? FirePoint(Gun gun)
		{
			try
			{
				return gun.firePointTransform;
			}
			catch
			{
				return null;
			}
		}

		public Sling(Gun gun, string barcode, string title, Rigidbody? rb)
		{
			Gun = gun;
			Barcode = barcode;
			Title = title;
			Rb = rb;
			T = (((Object)(object)rb != (Object)null) ? ((Component)rb).transform : ((Component)gun).transform);
			foreach (Collider componentsInChild in ((Component)T).GetComponentsInChildren<Collider>(true))
			{
				if ((Object)(object)componentsInChild != (Object)null)
				{
					own.Add(((Il2CppObjectBase)componentsInChild).Pointer);
				}
			}
			grips = ((Component)T).GetComponentsInChildren<Grip>(true);
			hostsAll = ((Component)T).GetComponentsInChildren<InteractableHost>(true);
			Fit();
			TooShort = GunLength < 0.32f;
			view = new SlingView(this);
		}

		private void Fit()
		{
			//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_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0055: 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_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: 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_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: 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_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: 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_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: 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_029f: 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_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			Transform val = (Transform)(((Object)(object)FirePoint(Gun) != (Object)null) ? ((object)FirePoint(Gun)) : ((object)T));
			Vector3 forward = val.forward;
			Vector3 val2 = Vector3.ProjectOnPlane(T.up, forward);
			if (((Vector3)(ref val2)).sqrMagnitude < 0.01f)
			{
				val2 = Vector3.ProjectOnPlane(val.up, forward);
			}
			((Vector3)(ref val2)).Normalize();
			Vector3.Cross(val2, forward);
			Vector3 position = val.position;
			float num = float.MaxValue;
			float num2 = float.MinValue;
			float num3 = float.MaxValue;
			float num4 = float.MinValue;
			List<Collider> list = new List<Collider>();
			foreach (Collider componentsInChild in ((Component)T).GetComponentsInChildren<Collider>(true))
			{
				if (!((Object)(object)componentsInChild == (Object)null) && !componentsInChild.isTrigger && Corners(componentsInChild, out Vector3[] world))
				{
					list.Add(componentsInChild);
					Vector3[] array = world;
					for (int i = 0; i < array.Length; i++)
					{
						Vector3 val3 = array[i] - position;
						float num5 = Vector3.Dot(val3, forward);
						float num6 = Vector3.Dot(val3, val2);
						num = Mathf.Min(num, num5);
						num2 = Mathf.Max(num2, num5);
						num3 = Mathf.Min(num3, num6);
						num4 = Mathf.Max(num4, num6);
					}
				}
			}
			if (list.Count == 0 || num > num2)
			{
				num = -0.5f;
				num2 = 0f;
				num3 = -0.08f;
				num4 = 0.04f;
			}
			GunLength = num2 - num;
			fitCols = list;
			fitOrigin = T.InverseTransformPoint(position);
			fitMidU = (num3 + num4) * 0.5f;
			fitReach = Mathf.Max(0.2f, num4 - num3 + 0.2f);
			Vector3 outward = T.InverseTransformDirection(forward);
			Fwd = ((Vector3)(ref outward)).normalized;
			outward = T.InverseTransformDirection(val2);
			Up = ((Vector3)(ref outward)).normalized;
			FrontF = num2 - Mathf.Clamp(GunLength * 0.22f, 0.06f, 0.3f);
			BackF = num + Mathf.Clamp(GunLength * 0.06f, 0.02f, 0.08f);
			FrontBase = Surface(FrontF, 0f, out outward);
			BackBase = Surface(BackF, 0f, out outward);
			float num7 = Vector3.Distance(FrontBase, BackBase) * T.lossyScale.x;
			BaseLength = Mathf.Max(num7 * 1.35f, 0.8f);
		}

		internal Vector3 Surface(float f, float rotation, out Vector3 outward)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: 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_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: 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_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_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_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: 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_008c: 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)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: 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_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_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_0148: 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_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = T.TransformDirection(Fwd);
			Vector3 val2 = T.TransformDirection(Up);
			Vector3 val3 = Quaternion.AngleAxis(rotation, val) * -val2;
			Vector3 val4 = T.TransformPoint(fitOrigin) + val * f + val2 * fitMidU;
			Ray val5 = default(Ray);
			((Ray)(ref val5))..ctor(val4 + val3 * fitReach, -val3);
			float num = float.MaxValue;
			Vector3 val6 = val4 + val3 * 0.02f;
			RaycastHit val7 = default(RaycastHit);
			foreach (Collider fitCol in fitCols)
			{
				try
				{
					if ((Object)(object)fitCol != (Object)null && fitCol.Raycast(val5, ref val7, fitReach * 2f) && ((RaycastHit)(ref val7)).distance < num)
					{
						num = ((RaycastHit)(ref val7)).distance;
						val6 = ((RaycastHit)(ref val7)).point;
					}
				}
				catch
				{
				}
			}
			Vector3 val8 = T.InverseTransformDirection(val3);
			outward = ((Vector3)(ref val8)).normalized;
			return T.InverseTransformPoint(val6 - val3 * 0.002f);
		}

		private static bool Corners(Collider c, out Vector3[] world)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: 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_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_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: 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_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: 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_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			world = Array.Empty<Vector3>();
			BoxCollider val = ((Il2CppObjectBase)c).TryCast<BoxCollider>();
			Vector3 center;
			Vector3 val2;
			if (val != null)
			{
				center = val.center;
				val2 = val.size;
			}
			else
			{
				SphereCollider val3 = ((Il2CppObjectBase)c).TryCast<SphereCollider>();
				if (val3 != null)
				{
					center = val3.center;
					val2 = Vector3.one * val3.radius * 2f;
				}
				else
				{
					CapsuleCollider val4 = ((Il2CppObjectBase)c).TryCast<CapsuleCollider>();
					if (val4 != null)
					{
						center = val4.center;
						val2 = Vector3.one * val4.radius * 2f;
						((Vector3)(ref val2))[val4.direction] = Mathf.Max(val4.height, val4.radius * 2f);
					}
					else
					{
						MeshCollider val5 = ((Il2CppObjectBase)c).TryCast<MeshCollider>();
						if (val5 == null || !((Object)(object)val5.sharedMesh != (Object)null))
						{
							return false;
						}
						Bounds bounds = val5.sharedMesh.bounds;
						center = ((Bounds)(ref bounds)).center;
						bounds = val5.sharedMesh.bounds;
						val2 = ((Bounds)(ref bounds)).size;
					}
				}
			}
			Transform transform = ((Component)c).transform;
			world = (Vector3[])(object)new Vector3[8];
			int num = 0;
			for (int i = -1; i <= 1; i += 2)
			{
				for (int j = -1; j <= 1; j += 2)
				{
					for (int k = -1; k <= 1; k += 2)
					{
						world[num++] = transform.TransformPoint(center + Vector3.Scale(val2 * 0.5f, new Vector3((float)i, (float)j, (float)k)));
					}
				}
			}
			return true;
		}

		public void Apply(GunConfig config)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: 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)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			Config = config;
			Style = ((config.Style == SlingStyle.Default) ? Settings.DefaultStyle : config.Style);
			SocketFront = Surface(FrontF + config.FrontForward, config.RollFront, out OutFront) + Up * config.FrontUp;
			SocketBack = Surface(BackF + config.BackForward, config.RollBack, out OutBack) + Up * config.BackUp;
			float num = (config.Swivels ? 0.03f : 0.004f);
			FrontLocal = SocketFront + OutFront * num;
			BackLocal = SocketBack + OutBack * num;
			float num2 = BaseLength * config.Length;
			bool num3 = Mathf.Abs(num2 - Rest) > 0.001f;
			Rest = num2;
			view.SetStyle(Style);
			if (num3)
			{
				Wake();
			}
		}

		public void Place()
		{
			//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_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_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: 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_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: 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_00b1: 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)
			Vector3 front = Front;
			Vector3 back = Back;
			float num = Vector3.Distance(front, back);
			float num2 = ((num < Rest) ? Mathf.Sqrt(3f * num * Mathf.Max(0f, Rest - num) / 8f) : 0f);
			for (int i = 0; i < 16; i++)
			{
				float num3 = (float)i / 15f;
				P[i] = (Prev[i] = (Last[i] = Vector3.Lerp(front, back, num3) + Vector3.down * (num2 * 4f * num3 * (1f - num3))));
				contact[i] = false;
			}
			placed = true;
			Wake();
		}

		public void Wake()
		{
			asleep = false;
			stillSteps = 0;
		}

		internal void SetPoints(Vector3[] pts)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: 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_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0030: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < 16; i++)
			{
				P[i] = (Prev[i] = (Last[i] = pts[i]));
			}
			placed = true;
			Wake();
		}

		public void Step(float dt, bool nearPlayer)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: 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_0059: 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_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: 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_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to i