Decompiled source of BodySwapRemote v1.0.0

SwapRemote.dll

Decompiled 13 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using LethalLib.Modules;
using Microsoft.CodeAnalysis;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("SwapRemote")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("SwapRemote")]
[assembly: AssemblyTitle("SwapRemote")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace SwapRemoteMod
{
	[BepInPlugin("markj.swapremote", "SwapRemote", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "markj.swapremote";

		public const string Name = "SwapRemote";

		public const string Version = "1.0.0";

		internal static ManualLogSource Log;

		internal static Item RemoteItem;

		internal static ConfigEntry<int> Price;

		internal static ConfigEntry<int> Uses;

		internal static ConfigEntry<float> ChargeTime;

		internal static ConfigEntry<float> Cooldown;

		internal static ConfigEntry<bool> AllowInsideOutside;

		private void Awake()
		{
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			Price = ((BaseUnityPlugin)this).Config.Bind<int>("General", "Price", 120, "Store price in credits. Everyone in the lobby should use the same value.");
			Uses = ((BaseUnityPlugin)this).Config.Bind<int>("General", "Uses", 1, "How many swaps a remote has before it's used up. (The host's setting is the one that counts.)");
			ChargeTime = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ChargeTime", 1f, "Seconds the button beeps before the swap happens.");
			Cooldown = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Cooldown", 10f, "Seconds between swaps when a remote has more than one use.");
			AllowInsideOutside = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "SwapBetweenInsideAndOutside", true, "Allow swapping with someone on the other side of the facility doors (inside vs outside/ship). (Host's setting counts.)");
			RemoteItem = RemoteFactory.Create();
			Items.RegisterShopItem(RemoteItem, Price.Value);
			new Harmony("markj.swapremote").PatchAll(typeof(Patches));
			Log.LogInfo((object)"SwapRemote 1.0.0 loaded.");
		}
	}
	[HarmonyPatch]
	internal static class Patches
	{
		[HarmonyPatch(typeof(StartOfRound), "Awake")]
		[HarmonyPostfix]
		private static void StartOfRoundAwake(StartOfRound __instance)
		{
			RemoteFactory.ApplyVanillaAssets(__instance);
		}

		[HarmonyPatch(typeof(StartOfRound), "Start")]
		[HarmonyPostfix]
		private static void StartOfRoundStart()
		{
			SwapNetwork.Register();
		}
	}
	internal static class RemoteFactory
	{
		private static readonly List<(Renderer renderer, Color color)> Parts = new List<(Renderer, Color)>();

		private static bool _assetsApplied;

		internal static AudioClip BeepClip;

		internal static AudioClip SwapClip;

		private static readonly Color Body = new Color(0.32f, 0.33f, 0.36f);

		private static readonly Color Dark = new Color(0.08f, 0.08f, 0.09f);

		private static readonly Color Red = new Color(0.85f, 0.06f, 0.05f);

		private static readonly Color Yellow = new Color(0.95f, 0.78f, 0.1f);

		public static Item Create()
		{
			//IL_0033: 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_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00ff: 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_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: Unknown result type (might be due to invalid IL or missing references)
			//IL_035d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0362: Unknown result type (might be due to invalid IL or missing references)
			//IL_0378: Unknown result type (might be due to invalid IL or missing references)
			//IL_037d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0393: Unknown result type (might be due to invalid IL or missing references)
			//IL_0398: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = NetworkPrefabs.CreateNetworkPrefab("SwapRemoteItem");
			val.layer = 6;
			val.tag = "PhysicsProp";
			MeshRenderer mainObjectRenderer = Part(val, (PrimitiveType)3, "Body", new Vector3(0f, 0f, 0f), new Vector3(0.075f, 0.13f, 0.035f), Vector3.zero, Body);
			Part(val, (PrimitiveType)3, "Stripe", new Vector3(0f, -0.045f, 0.018f), new Vector3(0.077f, 0.012f, 0.002f), Vector3.zero, Yellow);
			Part(val, (PrimitiveType)2, "ButtonBase", new Vector3(0f, 0.02f, 0.019f), new Vector3(0.05f, 0.004f, 0.05f), new Vector3(90f, 0f, 0f), Dark);
			MeshRenderer val2 = Part(val, (PrimitiveType)2, "Button", new Vector3(0f, 0.02f, 0.026f), new Vector3(0.038f, 0.007f, 0.038f), new Vector3(90f, 0f, 0f), Red);
			Part(val, (PrimitiveType)3, "Antenna", new Vector3(0.025f, 0.11f, -0.005f), new Vector3(0.006f, 0.09f, 0.006f), Vector3.zero, Dark);
			MeshRenderer val3 = Part(val, (PrimitiveType)0, "AntennaTip", new Vector3(0.025f, 0.158f, -0.005f), new Vector3(0.014f, 0.014f, 0.014f), Vector3.zero, Red);
			BoxCollider obj = val.AddComponent<BoxCollider>();
			((Collider)obj).isTrigger = true;
			obj.center = new Vector3(0f, 0.02f, 0f);
			obj.size = new Vector3(0.1f, 0.22f, 0.08f);
			GameObject val4 = new GameObject("ScanNode")
			{
				layer = 22
			};
			val4.transform.SetParent(val.transform, false);
			BoxCollider obj2 = val4.AddComponent<BoxCollider>();
			((Collider)obj2).isTrigger = true;
			obj2.size = Vector3.one * 0.3f;
			ScanNodeProperties obj3 = val4.AddComponent<ScanNodeProperties>();
			obj3.headerText = "Body Swap Remote";
			obj3.subText = "Do not press. (Press it.)";
			obj3.nodeType = 0;
			obj3.minRange = 1;
			obj3.maxRange = 13;
			obj3.requiresLineOfSight = true;
			obj3.creatureScanID = -1;
			AudioSource val5 = val.AddComponent<AudioSource>();
			val5.playOnAwake = false;
			val5.spatialBlend = 1f;
			val5.rolloffMode = (AudioRolloffMode)1;
			val5.maxDistance = 20f;
			Item val6 = ScriptableObject.CreateInstance<Item>();
			((Object)val6).name = "SwapRemoteItem";
			val6.itemName = "Body Swap Remote";
			val6.creditsWorth = Plugin.Price.Value;
			val6.weight = 1.0190476f;
			val6.isScrap = false;
			val6.twoHanded = false;
			val6.twoHandedAnimation = false;
			val6.holdButtonUse = false;
			val6.requiresBattery = false;
			val6.itemIsTrigger = false;
			val6.canBeGrabbedBeforeGameStart = true;
			val6.isConductiveMetal = true;
			val6.itemSpawnsOnGround = true;
			val6.allowDroppingAheadOfPlayer = true;
			val6.grabAnim = "";
			val6.verticalOffset = 0.06f;
			val6.restingRotation = new Vector3(90f, 0f, 0f);
			val6.positionOffset = new Vector3(0f, 0.02f, 0f);
			val6.rotationOffset = new Vector3(0f, 0f, 0f);
			val6.toolTips = new string[1] { "Swap with a random teammate : [LMB]" };
			val6.spawnPositionTypes = new List<ItemGroup>();
			val6.meshVariants = (Mesh[])(object)new Mesh[0];
			val6.materialVariants = (Material[])(object)new Material[0];
			val6.highestSalePercentage = 80;
			val6.itemIcon = MakeIcon();
			val6.spawnPrefab = val;
			SwapRemoteItem swapRemoteItem = val.AddComponent<SwapRemoteItem>();
			((GrabbableObject)swapRemoteItem).itemProperties = val6;
			((GrabbableObject)swapRemoteItem).grabbable = true;
			((GrabbableObject)swapRemoteItem).grabbableToEnemies = true;
			((GrabbableObject)swapRemoteItem).mainObjectRenderer = mainObjectRenderer;
			swapRemoteItem.audioSource = val5;
			swapRemoteItem.glowParts = (Renderer[])(object)new Renderer[2]
			{
				(Renderer)val2,
				(Renderer)val3
			};
			return val6;
		}

		private static MeshRenderer Part(GameObject parent, PrimitiveType type, string name, Vector3 pos, Vector3 size, Vector3 rot, Color color)
		{
			//IL_0000: 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_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = GameObject.CreatePrimitive(type);
			Object.DestroyImmediate((Object)(object)obj.GetComponent<Collider>());
			((Object)obj).name = name;
			obj.layer = 6;
			obj.transform.SetParent(parent.transform, false);
			obj.transform.localPosition = pos;
			obj.transform.localEulerAngles = rot;
			obj.transform.localScale = size;
			MeshRenderer component = obj.GetComponent<MeshRenderer>();
			Parts.Add(((Renderer)(object)component, color));
			return component;
		}

		private static Sprite MakeIcon()
		{
			//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_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: 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_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(128, 128, (TextureFormat)4, false)
			{
				filterMode = (FilterMode)1,
				wrapMode = (TextureWrapMode)1
			};
			Color32[] array = (Color32[])(object)new Color32[16384];
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(64f, 62f);
			for (int i = 0; i < 128; i++)
			{
				for (int j = 0; j < 128; j++)
				{
					Vector2 val3 = new Vector2((float)j + 0.5f, (float)i + 0.5f);
					bool flag = j >= 40 && j <= 88 && i >= 14 && i <= 96;
					float num = Vector2.Distance(val3, val2);
					bool flag2 = num < 18f && num > 13f;
					bool flag3 = j >= 74 && j <= 80 && i > 96 && i <= 116;
					bool flag4 = Vector2.Distance(val3, new Vector2(77f, 118f)) < 6f;
					bool flag5 = (flag && !flag2) || flag3 || flag4;
					array[i * 128 + j] = (flag5 ? new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue) : new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)0));
				}
			}
			val.SetPixels32(array);
			val.Apply();
			return Sprite.Create(val, new Rect(0f, 0f, 128f, 128f), new Vector2(0.5f, 0.5f), 100f);
		}

		public static void ApplyVanillaAssets(StartOfRound sor)
		{
			//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_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Expected O, but got Unknown
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			if (_assetsApplied || (Object)(object)sor == (Object)null || (Object)(object)sor.allItemsList == (Object)null)
			{
				return;
			}
			try
			{
				List<Item> vanilla = sor.allItemsList.itemsList;
				Material val = null;
				foreach (Item item3 in vanilla)
				{
					if (!((Object)(object)item3 == (Object)null) && !((Object)(object)item3.spawnPrefab == (Object)null) && !((Object)(object)item3 == (Object)(object)Plugin.RemoteItem))
					{
						MeshRenderer componentInChildren = item3.spawnPrefab.GetComponentInChildren<MeshRenderer>(true);
						if ((Object)(object)componentInChildren != (Object)null && (Object)(object)((Renderer)componentInChildren).sharedMaterial != (Object)null && ((Renderer)componentInChildren).sharedMaterial.HasProperty("_BaseColor"))
						{
							val = ((Renderer)componentInChildren).sharedMaterial;
							break;
						}
					}
				}
				if ((Object)(object)val != (Object)null)
				{
					foreach (var part in Parts)
					{
						Renderer item = part.renderer;
						Color item2 = part.color;
						Material val2 = new Material(val)
						{
							name = "Swap_" + ((Object)item).name
						};
						string[] array = new string[4] { "_BaseColorMap", "_NormalMap", "_MaskMap", "_EmissiveColorMap" };
						foreach (string text in array)
						{
							if (val2.HasProperty(text))
							{
								val2.SetTexture(text, (Texture)null);
							}
						}
						val2.DisableKeyword("_NORMALMAP");
						val2.DisableKeyword("_MASKMAP");
						val2.SetColor("_BaseColor", item2);
						if (val2.HasProperty("_Metallic"))
						{
							val2.SetFloat("_Metallic", 0.3f);
						}
						if (val2.HasProperty("_Smoothness"))
						{
							val2.SetFloat("_Smoothness", 0.55f);
						}
						item.sharedMaterial = val2;
					}
				}
				else
				{
					Plugin.Log.LogWarning((object)"Couldn't find a vanilla material to copy; the remote may look pink.");
				}
				Item val3 = new string[3] { "Walkie-talkie", "Flashlight", "Pro-flashlight" }.Select((string n) => ((IEnumerable<Item>)vanilla).FirstOrDefault((Func<Item, bool>)((Item val4) => (Object)(object)val4 != (Object)null && val4.itemName == n))).FirstOrDefault<Item>((Func<Item, bool>)((Item val4) => (Object)(object)val4 != (Object)null));
				if ((Object)(object)val3 != (Object)null)
				{
					Plugin.RemoteItem.grabSFX = val3.grabSFX;
					Plugin.RemoteItem.dropSFX = val3.dropSFX;
					Plugin.RemoteItem.pocketSFX = val3.pocketSFX;
				}
				AudioClip[] clips = Resources.FindObjectsOfTypeAll<AudioClip>();
				BeepClip = FindClip(clips, "beep", "Beep", "click");
				SwapClip = FindClip(clips, "Teleport", "teleport", "Beam", "zap", "Zap");
				Plugin.Log.LogInfo((object)("Remote sounds: beep=" + (((Object)(object)BeepClip != (Object)null) ? ((Object)BeepClip).name : "none") + ", swap=" + (((Object)(object)SwapClip != (Object)null) ? ((Object)SwapClip).name : "none")));
				_assetsApplied = true;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Failed to apply vanilla assets: " + ex));
			}
		}

		private static AudioClip FindClip(AudioClip[] clips, params string[] keys)
		{
			foreach (string k in keys)
			{
				AudioClip val = ((IEnumerable<AudioClip>)clips).FirstOrDefault((Func<AudioClip, bool>)((AudioClip a) => (Object)(object)a != (Object)null && ((Object)a).name.IndexOf(k, StringComparison.Ordinal) >= 0 && a.length < 4f));
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return null;
		}
	}
	internal static class R
	{
		private static readonly HashSet<string> Warned = new HashSet<string>();

		private static void Warn(string what)
		{
			if (Warned.Add(what))
			{
				Plugin.Log.LogWarning((object)("Game member not found (game version difference?): " + what));
			}
		}

		public static object Get(object obj, string name)
		{
			if (obj == null)
			{
				return null;
			}
			FieldInfo fieldInfo = AccessTools.Field(obj.GetType(), name);
			if (fieldInfo != null)
			{
				return fieldInfo.GetValue(obj);
			}
			PropertyInfo propertyInfo = AccessTools.Property(obj.GetType(), name);
			if (propertyInfo != null && propertyInfo.CanRead)
			{
				return propertyInfo.GetValue(obj);
			}
			Warn(obj.GetType().Name + "." + name);
			return null;
		}

		public static void Set(object obj, string name, object value)
		{
			if (obj == null)
			{
				return;
			}
			try
			{
				FieldInfo fieldInfo = AccessTools.Field(obj.GetType(), name);
				if (fieldInfo != null)
				{
					fieldInfo.SetValue(obj, value);
					return;
				}
				PropertyInfo propertyInfo = AccessTools.Property(obj.GetType(), name);
				if (propertyInfo != null && propertyInfo.CanWrite)
				{
					propertyInfo.SetValue(obj, value);
				}
				else
				{
					Warn(obj.GetType().Name + "." + name);
				}
			}
			catch (Exception ex)
			{
				Warn(obj.GetType().Name + "." + name + " (" + ex.Message + ")");
			}
		}

		public static void Call(object obj, string name, params object[] args)
		{
			if (obj == null)
			{
				return;
			}
			try
			{
				MethodInfo methodInfo = AccessTools.GetDeclaredMethods(obj.GetType()).FirstOrDefault((MethodInfo m) => m.Name == name && m.GetParameters().Length >= args.Length && m.GetParameters().Skip(args.Length).All((ParameterInfo pi) => pi.HasDefaultValue));
				if (methodInfo == null)
				{
					Warn(obj.GetType().Name + "." + name + "()");
					return;
				}
				ParameterInfo[] parameters = methodInfo.GetParameters();
				object[] array = new object[parameters.Length];
				for (int num = 0; num < parameters.Length; num++)
				{
					array[num] = ((num < args.Length) ? args[num] : parameters[num].DefaultValue);
				}
				methodInfo.Invoke(obj, array);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)(obj.GetType().Name + "." + name + "() threw: " + (ex.InnerException?.Message ?? ex.Message)));
			}
		}
	}
	internal static class SwapNetwork
	{
		private struct SwapData
		{
			public int A;

			public int B;

			public Vector3 APos;

			public Vector3 BPos;

			public byte AFlags;

			public byte BFlags;

			public int UsesLeft;

			public void Write(FastBufferWriter w)
			{
				//IL_000a: 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_0020: 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_003b: 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_0056: Unknown result type (might be due to invalid IL or missing references)
				//IL_005c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0071: 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_008c: 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_00a7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c2: 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_00d8: 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_00ee: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
				//IL_0104: Unknown result type (might be due to invalid IL or missing references)
				//IL_010a: Unknown result type (might be due to invalid IL or missing references)
				((FastBufferWriter)(ref w)).WriteValueSafe<int>(ref A, default(ForPrimitives));
				((FastBufferWriter)(ref w)).WriteValueSafe<int>(ref B, default(ForPrimitives));
				((FastBufferWriter)(ref w)).WriteValueSafe<float>(ref APos.x, default(ForPrimitives));
				((FastBufferWriter)(ref w)).WriteValueSafe<float>(ref APos.y, default(ForPrimitives));
				((FastBufferWriter)(ref w)).WriteValueSafe<float>(ref APos.z, default(ForPrimitives));
				((FastBufferWriter)(ref w)).WriteValueSafe<float>(ref BPos.x, default(ForPrimitives));
				((FastBufferWriter)(ref w)).WriteValueSafe<float>(ref BPos.y, default(ForPrimitives));
				((FastBufferWriter)(ref w)).WriteValueSafe<float>(ref BPos.z, default(ForPrimitives));
				((FastBufferWriter)(ref w)).WriteValueSafe<byte>(ref AFlags, default(ForPrimitives));
				((FastBufferWriter)(ref w)).WriteValueSafe<byte>(ref BFlags, default(ForPrimitives));
				((FastBufferWriter)(ref w)).WriteValueSafe<int>(ref UsesLeft, default(ForPrimitives));
			}

			public static SwapData Read(FastBufferReader r)
			{
				//IL_0013: Unknown result type (might be due to invalid IL or missing references)
				//IL_0019: Unknown result type (might be due to invalid IL or missing references)
				//IL_002b: 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_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_0051: Unknown result type (might be due to invalid IL or missing references)
				//IL_0057: Unknown result type (might be due to invalid IL or missing references)
				//IL_0064: Unknown result type (might be due to invalid IL or missing references)
				//IL_006a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0077: Unknown result type (might be due to invalid IL or missing references)
				//IL_007d: Unknown result type (might be due to invalid IL or missing references)
				//IL_008a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0090: Unknown result type (might be due to invalid IL or missing references)
				//IL_009d: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
				//IL_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_00e5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
				//IL_0109: Unknown result type (might be due to invalid IL or missing references)
				//IL_010e: Unknown result type (might be due to invalid IL or missing references)
				SwapData result = default(SwapData);
				((FastBufferReader)(ref r)).ReadValueSafe<int>(ref result.A, default(ForPrimitives));
				((FastBufferReader)(ref r)).ReadValueSafe<int>(ref result.B, default(ForPrimitives));
				float num = default(float);
				((FastBufferReader)(ref r)).ReadValueSafe<float>(ref num, default(ForPrimitives));
				float num2 = default(float);
				((FastBufferReader)(ref r)).ReadValueSafe<float>(ref num2, default(ForPrimitives));
				float num3 = default(float);
				((FastBufferReader)(ref r)).ReadValueSafe<float>(ref num3, default(ForPrimitives));
				float num4 = default(float);
				((FastBufferReader)(ref r)).ReadValueSafe<float>(ref num4, default(ForPrimitives));
				float num5 = default(float);
				((FastBufferReader)(ref r)).ReadValueSafe<float>(ref num5, default(ForPrimitives));
				float num6 = default(float);
				((FastBufferReader)(ref r)).ReadValueSafe<float>(ref num6, default(ForPrimitives));
				((FastBufferReader)(ref r)).ReadValueSafe<byte>(ref result.AFlags, default(ForPrimitives));
				((FastBufferReader)(ref r)).ReadValueSafe<byte>(ref result.BFlags, default(ForPrimitives));
				((FastBufferReader)(ref r)).ReadValueSafe<int>(ref result.UsesLeft, default(ForPrimitives));
				result.APos = new Vector3(num, num2, num3);
				result.BPos = new Vector3(num4, num5, num6);
				return result;
			}
		}

		[CompilerGenerated]
		private static class <>O
		{
			public static HandleNamedMessageDelegate <0>__OnRequest;

			public static HandleNamedMessageDelegate <1>__OnSwap;

			public static HandleNamedMessageDelegate <2>__OnFail;
		}

		private const string RequestMsg = "SwapRemote_Request";

		private const string SwapMsg = "SwapRemote_Swap";

		private const string FailMsg = "SwapRemote_Fail";

		private static readonly Dictionary<ulong, int> UsesSpent = new Dictionary<ulong, int>();

		private static readonly Dictionary<ulong, float> LastSwap = new Dictionary<ulong, float>();

		public static void Register()
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			//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_0095: Expected O, but got Unknown
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Expected O, but got Unknown
			NetworkManager singleton = NetworkManager.Singleton;
			CustomMessagingManager val = ((singleton != null) ? singleton.CustomMessagingManager : null);
			if (val != null)
			{
				string[] array = new string[3] { "SwapRemote_Request", "SwapRemote_Swap", "SwapRemote_Fail" };
				foreach (string text in array)
				{
					val.UnregisterNamedMessageHandler(text);
				}
				object obj = <>O.<0>__OnRequest;
				if (obj == null)
				{
					HandleNamedMessageDelegate val2 = OnRequest;
					<>O.<0>__OnRequest = val2;
					obj = (object)val2;
				}
				val.RegisterNamedMessageHandler("SwapRemote_Request", (HandleNamedMessageDelegate)obj);
				object obj2 = <>O.<1>__OnSwap;
				if (obj2 == null)
				{
					HandleNamedMessageDelegate val3 = OnSwap;
					<>O.<1>__OnSwap = val3;
					obj2 = (object)val3;
				}
				val.RegisterNamedMessageHandler("SwapRemote_Swap", (HandleNamedMessageDelegate)obj2);
				object obj3 = <>O.<2>__OnFail;
				if (obj3 == null)
				{
					HandleNamedMessageDelegate val4 = OnFail;
					<>O.<2>__OnFail = val4;
					obj3 = (object)val4;
				}
				val.RegisterNamedMessageHandler("SwapRemote_Fail", (HandleNamedMessageDelegate)obj3);
				UsesSpent.Clear();
				LastSwap.Clear();
				Plugin.Log.LogInfo((object)"Swap remote networking ready.");
			}
		}

		private static bool Busy(PlayerControllerB p)
		{
			if (!p.isClimbingLadder && !p.inTerminalMenu && !p.inSpecialInteractAnimation && !((Object)(object)p.inAnimationWithEnemy != (Object)null))
			{
				object obj = R.Get(p, "inVehicleAnimation");
				bool flag = default(bool);
				int num;
				if (obj is bool)
				{
					flag = (bool)obj;
					num = 1;
				}
				else
				{
					num = 0;
				}
				return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
			}
			return true;
		}

		public static string WhyCantSwap(PlayerControllerB me)
		{
			if (me.isPlayerDead)
			{
				return "You're dead.";
			}
			if (Busy(me))
			{
				return "Can't swap right now. Get off the ladder / out of the animation first.";
			}
			if (!StartOfRound.Instance.allPlayerScripts.Any((PlayerControllerB p) => (Object)(object)p != (Object)null && (Object)(object)p != (Object)(object)me && p.isPlayerControlled && !p.isPlayerDead))
			{
				return "There's nobody else alive to swap with.";
			}
			return null;
		}

		public unsafe static void RequestSwap(PlayerControllerB me)
		{
			//IL_0033: 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_004c: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager singleton = NetworkManager.Singleton;
			int idx = (int)me.playerClientId;
			if (singleton.IsServer)
			{
				ServerHandle(idx, singleton.LocalClientId);
				return;
			}
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(8, (Allocator)2, -1);
			try
			{
				((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref idx, default(ForPrimitives));
				singleton.CustomMessagingManager.SendNamedMessage("SwapRemote_Request", 0uL, val, (NetworkDelivery)2);
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
			}
		}

		private static void OnRequest(ulong sender, FastBufferReader r)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkManager.Singleton.IsServer)
			{
				int idx = default(int);
				((FastBufferReader)(ref r)).ReadValueSafe<int>(ref idx, default(ForPrimitives));
				ServerHandle(idx, sender);
			}
		}

		private unsafe static void ServerHandle(int idx, ulong sender)
		{
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_0270: Unknown result type (might be due to invalid IL or missing references)
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			if (idx < 0 || idx >= allPlayerScripts.Length)
			{
				return;
			}
			PlayerControllerB a = allPlayerScripts[idx];
			if (a.actualClientId != sender || !a.isPlayerControlled || a.isPlayerDead)
			{
				return;
			}
			if (!(a.currentlyHeldObjectServer is SwapRemoteItem swapRemoteItem))
			{
				Fail(sender, "Hold the remote to use it.");
				return;
			}
			ulong networkObjectId = ((NetworkBehaviour)swapRemoteItem).NetworkObjectId;
			if (LastSwap.TryGetValue(networkObjectId, out var value) && Time.time - value < Plugin.Cooldown.Value)
			{
				Fail(sender, $"Recharging... {Mathf.CeilToInt(Plugin.Cooldown.Value - (Time.time - value))}s");
				return;
			}
			if (Busy(a))
			{
				Fail(sender, "Can't swap right now.");
				return;
			}
			List<PlayerControllerB> list = allPlayerScripts.Where((PlayerControllerB p) => (Object)(object)p != (Object)null && (Object)(object)p != (Object)(object)a && p.isPlayerControlled && !p.isPlayerDead && !Busy(p) && (Plugin.AllowInsideOutside.Value || p.isInsideFactory == a.isInsideFactory)).ToList();
			if (list.Count == 0)
			{
				Fail(sender, "Nobody can be swapped with right now.");
				return;
			}
			PlayerControllerB val = list[Random.Range(0, list.Count)];
			UsesSpent.TryGetValue(networkObjectId, out var value2);
			value2++;
			UsesSpent[networkObjectId] = value2;
			LastSwap[networkObjectId] = Time.time;
			int num = Mathf.Max(0, Plugin.Uses.Value - value2);
			SwapData d = new SwapData
			{
				A = idx,
				B = (int)val.playerClientId,
				APos = ((Component)a).transform.position,
				BPos = ((Component)val).transform.position,
				AFlags = Flags(a),
				BFlags = Flags(val),
				UsesLeft = num
			};
			Plugin.Log.LogInfo((object)$"{a.playerUsername} swapped with {val.playerUsername} ({num} uses left).");
			List<ulong> list2 = NetworkManager.Singleton.ConnectedClientsIds.Where((ulong id) => id != 0).ToList();
			if (list2.Count > 0)
			{
				FastBufferWriter val2 = default(FastBufferWriter);
				((FastBufferWriter)(ref val2))..ctor(64, (Allocator)2, -1);
				try
				{
					d.Write(val2);
					NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("SwapRemote_Swap", (IReadOnlyList<ulong>)list2, val2, (NetworkDelivery)2);
				}
				finally
				{
					((IDisposable)(*(FastBufferWriter*)(&val2))/*cast due to .constrained prefix*/).Dispose();
				}
			}
			DoSwap(d);
		}

		private unsafe static void Fail(ulong client, string reason)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			if (client == NetworkManager.Singleton.LocalClientId)
			{
				ShowFail(reason);
				return;
			}
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(512, (Allocator)2, -1);
			try
			{
				((FastBufferWriter)(ref val)).WriteValueSafe(reason, false);
				NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("SwapRemote_Fail", client, val, (NetworkDelivery)2);
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
			}
		}

		private static void OnFail(ulong sender, FastBufferReader r)
		{
			if (sender == 0L)
			{
				string reason = default(string);
				((FastBufferReader)(ref r)).ReadValueSafe(ref reason, false);
				ShowFail(reason);
			}
		}

		private static void ShowFail(string reason)
		{
			HUDManager.Instance.DisplayTip("Body Swap Remote", reason, true, false, "LC_Tip1");
		}

		private static byte Flags(PlayerControllerB p)
		{
			return (byte)((p.isInsideFactory ? 1u : 0u) | (uint)(p.isInElevator ? 2 : 0) | (uint)(p.isInHangarShipRoom ? 4 : 0));
		}

		private static void OnSwap(ulong sender, FastBufferReader r)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			if (sender == 0L)
			{
				DoSwap(SwapData.Read(r));
			}
		}

		private static void DoSwap(SwapData d)
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			if (d.A >= 0 && d.A < allPlayerScripts.Length && d.B >= 0 && d.B < allPlayerScripts.Length)
			{
				PlayerControllerB val = allPlayerScripts[d.A];
				PlayerControllerB val2 = allPlayerScripts[d.B];
				SwapRemoteItem swapRemoteItem = val.currentlyHeldObjectServer as SwapRemoteItem;
				if ((Object)(object)swapRemoteItem != (Object)null)
				{
					swapRemoteItem.PlaySwapSound();
				}
				MovePlayer(val, d.BPos, d.BFlags, val2);
				MovePlayer(val2, d.APos, d.AFlags, val);
				if (d.UsesLeft <= 0 && IsMe(val) && val.currentlyHeldObjectServer is SwapRemoteItem)
				{
					val.DespawnHeldObject();
				}
			}
		}

		private static bool IsMe(PlayerControllerB p)
		{
			if (((NetworkBehaviour)p).IsOwner)
			{
				return p.isPlayerControlled;
			}
			return false;
		}

		private static void MovePlayer(PlayerControllerB p, Vector3 pos, byte flags, PlayerControllerB other)
		{
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			bool isInFactory = (p.isInsideFactory = (flags & 1) != 0);
			p.isInElevator = (flags & 2) != 0;
			p.isInHangarShipRoom = (flags & 4) != 0;
			if (p.ItemSlots != null)
			{
				GrabbableObject[] itemSlots = p.ItemSlots;
				foreach (GrabbableObject val in itemSlots)
				{
					if ((Object)(object)val != (Object)null)
					{
						val.isInFactory = isInFactory;
					}
				}
			}
			if (IsMe(p))
			{
				R.Call(p, "ResetFallGravity");
				R.Set(p, "fallValue", 0f);
				R.Set(p, "fallValueUncapped", 0f);
				p.TeleportPlayer(pos + Vector3.up * 0.05f, false, 0f, false, true);
				HUDManager.Instance.ShakeCamera((ScreenShakeType)1);
				HUDManager.Instance.DisplayTip("SWAPPED!", "You swapped places with " + other.playerUsername + ".", false, false, "LC_Tip1");
			}
		}
	}
	public class SwapRemoteItem : GrabbableObject
	{
		public AudioSource audioSource;

		public Renderer[] glowParts;

		private static readonly int EmissiveId = Shader.PropertyToID("_EmissiveColor");

		private static MaterialPropertyBlock _block;

		private bool _charging;

		private float _nextUse;

		public override void ItemActivate(bool used, bool buttonDown = true)
		{
			((GrabbableObject)this).ItemActivate(used, buttonDown);
			if (buttonDown && ((NetworkBehaviour)this).IsOwner && !((Object)(object)base.playerHeldBy == (Object)null) && !_charging && !(Time.time < _nextUse))
			{
				PlayerControllerB playerHeldBy = base.playerHeldBy;
				string text = SwapNetwork.WhyCantSwap(playerHeldBy);
				if (text != null)
				{
					_nextUse = Time.time + 1f;
					HUDManager.Instance.DisplayTip("Body Swap Remote", text, true, false, "LC_Tip1");
				}
				else
				{
					((MonoBehaviour)this).StartCoroutine(ChargeAndSwap(playerHeldBy));
				}
			}
		}

		private IEnumerator ChargeAndSwap(PlayerControllerB me)
		{
			_charging = true;
			float total = Mathf.Max(0f, Plugin.ChargeTime.Value);
			float t = 0f;
			float nextBeep = 0f;
			while (t < total)
			{
				if (t >= nextBeep)
				{
					if ((Object)(object)RemoteFactory.BeepClip != (Object)null && (Object)(object)audioSource != (Object)null)
					{
						audioSource.PlayOneShot(RemoteFactory.BeepClip, 0.8f);
					}
					nextBeep += 0.25f;
				}
				SetGlow(0.5f + 0.5f * Mathf.Sin(t * 30f));
				t += Time.deltaTime;
				yield return null;
			}
			SetGlow(0f);
			_charging = false;
			_nextUse = Time.time + 1f;
			if (!((Object)(object)base.playerHeldBy != (Object)(object)me) && !base.isPocketed && !me.isPlayerDead)
			{
				SwapNetwork.RequestSwap(me);
			}
		}

		public void PlaySwapSound()
		{
			if ((Object)(object)RemoteFactory.SwapClip != (Object)null && (Object)(object)audioSource != (Object)null)
			{
				audioSource.PlayOneShot(RemoteFactory.SwapClip, 1f);
			}
		}

		private void SetGlow(float amount)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			//IL_0056: 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)
			if (glowParts == null)
			{
				return;
			}
			if (_block == null)
			{
				_block = new MaterialPropertyBlock();
			}
			Renderer[] array = glowParts;
			foreach (Renderer val in array)
			{
				if (!((Object)(object)val == (Object)null))
				{
					val.GetPropertyBlock(_block);
					_block.SetColor(EmissiveId, new Color(1f, 0.1f, 0.05f) * (amount * 12f));
					val.SetPropertyBlock(_block);
				}
			}
		}
	}
}