Decompiled source of BetterBetterTeleporter v1.2.1

BepInEx/plugins/BetterBetterTeleporter.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using BetterBetterTeleporter.Adapters;
using BetterBetterTeleporter.Integrations;
using BetterBetterTeleporter.Networking;
using BetterBetterTeleporter.Utility;
using GameNetcodeStuff;
using HarmonyLib;
using LethalConfig;
using LethalConfig.ConfigItems;
using LethalConfig.ConfigItems.Options;
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("BetterBetterTeleporter")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("A fully configurable Teleporter and Inverse Teleporter mod with advanced item filtering.")]
[assembly: AssemblyFileVersion("1.2.1.0")]
[assembly: AssemblyInformationalVersion("1.2.1+d37e07a298aaff945ed5accff2ecb04ceed2f374")]
[assembly: AssemblyProduct("BetterBetterTeleporter")]
[assembly: AssemblyTitle("BetterBetterTeleporter")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.2.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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 BetterBetterTeleporter
{
	public enum ItemTeleportBehavior
	{
		Keep,
		Drop
	}
	public class ModConfig
	{
		public SyncedEntry<bool> ResetCooldownOnOrbit;

		public SyncedEntry<int> TeleporterCooldown;

		public SyncedEntry<ItemTeleportBehavior> TeleporterBehavior;

		public SyncedEntry<string> TeleporterAlwaysKeep;

		public SyncedEntry<string> TeleporterAlwaysDrop;

		public SyncedEntry<int> InverseTeleporterCooldown;

		public SyncedEntry<ItemTeleportBehavior> InverseTeleporterBehavior;

		public SyncedEntry<string> InverseTeleporterAlwaysKeep;

		public SyncedEntry<string> InverseTeleporterAlwaysDrop;

		public SyncedEntry<int> BatteryDrainPercent;

		public ModConfig(ConfigFile config)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Expected O, but got Unknown
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Expected O, but got Unknown
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Expected O, but got Unknown
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Expected O, but got Unknown
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Expected O, but got Unknown
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Expected O, but got Unknown
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Expected O, but got Unknown
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Expected O, but got Unknown
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Expected O, but got Unknown
			config.SaveOnConfigSet = false;
			ResetCooldownOnOrbit = config.BindSynced("General", "ResetCooldownOnOrbit", value: false, new ConfigDescription("Resets the cooldown time on teleporters between days.", (AcceptableValueBase)null, Array.Empty<object>()));
			TeleporterCooldown = config.BindSynced("Teleporter", "TeleporterCooldown", 10, new ConfigDescription("Cooldown time (in seconds) for using the Teleporter.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, int.MaxValue), Array.Empty<object>()));
			TeleporterBehavior = config.BindSynced("Teleporter", "TeleporterBehavior", ItemTeleportBehavior.Drop, new ConfigDescription("Makes the Teleporter \"Drop\" or \"Keep\" items on teleport.", (AcceptableValueBase)null, Array.Empty<object>()));
			TeleporterAlwaysKeep = config.BindSynced("Teleporter", "TeleporterAlwaysKeep", "", new ConfigDescription("Keep these items regardless of Teleporter behavior (comma-separated item names).\n\nDoes nothing if TeleporterBehavior is set to \"Keep\".", (AcceptableValueBase)null, Array.Empty<object>()));
			TeleporterAlwaysDrop = config.BindSynced("Teleporter", "TeleporterAlwaysDrop", "", new ConfigDescription("Drop these items regardless of Teleporter behavior (comma-separated item names).\n\nDoes nothing if TeleporterBehavior is set to \"Drop\".", (AcceptableValueBase)null, Array.Empty<object>()));
			InverseTeleporterCooldown = config.BindSynced("Inverse Teleporter", "InverseTeleporterCooldown", 210, new ConfigDescription("Cooldown time (in seconds) for using the Inverse Teleporter.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, int.MaxValue), Array.Empty<object>()));
			InverseTeleporterBehavior = config.BindSynced("Inverse Teleporter", "InverseTeleporterBehavior", ItemTeleportBehavior.Drop, new ConfigDescription("Makes the Inverse Teleporter \"Drop\" or \"Keep\" items on teleport.", (AcceptableValueBase)null, Array.Empty<object>()));
			InverseTeleporterAlwaysKeep = config.BindSynced("Inverse Teleporter", "InverseTeleporterAlwaysKeep", "", new ConfigDescription("Keep these items regardless of Inverse Teleporter behavior (comma-separated item names).\n\nDoes nothing if InverseTeleporterBehavior is set to \"Keep\".", (AcceptableValueBase)null, Array.Empty<object>()));
			InverseTeleporterAlwaysDrop = config.BindSynced("Inverse Teleporter", "InverseTeleporterAlwaysDrop", "", new ConfigDescription("Drop these items regardless of Inverse Teleporter behavior (comma-separated item names).\n\nDoes nothing if InverseTeleporterBehavior is set to \"Drop\".", (AcceptableValueBase)null, Array.Empty<object>()));
			BatteryDrainPercent = config.BindSynced("Inverse Teleporter", "BatteryDrainPercent", 0, new ConfigDescription("Drains all held battery items by a percentage when using the Inverse Teleporter.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			((Dictionary<ConfigDefinition, string>)AccessTools.Property(typeof(ConfigFile), "OrphanedEntries").GetValue(config)).Clear();
			config.Save();
			config.SaveOnConfigSet = true;
		}
	}
	[BepInPlugin("BetterBetterTeleporter", "BetterBetterTeleporter", "1.2.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Logger { get; private set; }

		public static Plugin Instance { get; private set; }

		public static ModConfig ModConfig { get; private set; }

		internal void Awake()
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)Instance != (Object)null))
			{
				Instance = this;
				Logger = ((BaseUnityPlugin)this).Logger;
				ModConfig = new ModConfig(((BaseUnityPlugin)this).Config);
				InitSoftDependencyIntegrations();
				new Harmony("BetterBetterTeleporter").PatchAll();
				Logger.LogInfo((object)"BetterBetterTeleporter loaded successfully.");
			}
		}

		private void InitSoftDependencyIntegrations()
		{
			if (Chainloader.PluginInfos.ContainsKey("ainavt.lc.lethalconfig"))
			{
				LethalConfigIntegration.Initialize();
			}
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "BetterBetterTeleporter";

		public const string PLUGIN_NAME = "BetterBetterTeleporter";

		public const string PLUGIN_VERSION = "1.2.1";
	}
}
namespace BetterBetterTeleporter.Utility
{
	public static class ItemParser
	{
		public static List<ItemRule> ParseConfig(string source)
		{
			if (string.IsNullOrEmpty(source))
			{
				return new List<ItemRule>();
			}
			List<ItemRule> list = new List<ItemRule>();
			if (!IndexOfUnescaped(source, ',').HasValue)
			{
				return new List<ItemRule>(1) { ParseItemRule(source) };
			}
			foreach (string item in SplitCurrentGeneration(source))
			{
				list.Add(ParseItemRule(item));
			}
			return list;
		}

		private static ItemRule ParseItemRule(string source)
		{
			if (source[0] == '[')
			{
				if (source[source.Length - 1] == ']')
				{
					string text = source;
					string[] array = text.Substring(1, text.Length - 1 - 1).ToLowerInvariant().Split(":", 2, StringSplitOptions.RemoveEmptyEntries);
					bool flag = false;
					List<ItemRule> rules = new List<ItemRule>();
					if (array.Length > 1)
					{
						int num;
						if (array[1].StartsWith("not("))
						{
							string obj = array[1];
							num = ((obj[obj.Length - 1] == ')') ? 1 : 0);
						}
						else
						{
							num = 0;
						}
						flag = (byte)num != 0;
						object source2;
						if (!flag)
						{
							source2 = array[1];
						}
						else
						{
							text = array[1];
							source2 = text.Substring(4, text.Length - 1 - 4);
						}
						rules = ParseConfig((string)source2);
					}
					return ItemRules.FromId(Unescape(array[0]), new ItemFilterList(flag, rules));
				}
			}
			return new ItemNameRule(Unescape(source));
		}

		private static List<string> SplitCurrentGeneration(string source)
		{
			List<string> list = new List<string>();
			int num = 0;
			int num2 = 0;
			for (int i = 0; i < source.Length; i++)
			{
				switch (source[i])
				{
				case '[':
					num++;
					break;
				case ']':
					num = Math.Max(num - 1, 0);
					break;
				case ',':
					if (num == 0)
					{
						if (i - num2 > 0)
						{
							int num3 = num2;
							list.Add(source.Substring(num3, i - num3));
						}
						num2 = i + 1;
					}
					break;
				}
			}
			if (num2 < source.Length)
			{
				int num3 = num2;
				list.Add(source.Substring(num3, source.Length - num3));
			}
			return list;
		}

		private static int? IndexOfUnescaped(string source, char delimiter, char escapeChar = '\\')
		{
			if (string.IsNullOrEmpty(source))
			{
				return null;
			}
			bool flag = false;
			for (int i = 0; i < source.Length; i++)
			{
				if (source[i] == escapeChar)
				{
					flag = !flag;
					continue;
				}
				if (source[i] == delimiter && !flag)
				{
					return i;
				}
				flag = false;
			}
			return null;
		}

		private static string Unescape(string source, char escapeChar = '\\')
		{
			bool flag = false;
			for (int i = 0; i < source.Length; i++)
			{
				if (source[i] == escapeChar && !flag)
				{
					flag = !flag;
				}
				else if (source[i] == escapeChar)
				{
					source = source.Remove(i, 1);
				}
				else
				{
					flag = false;
				}
			}
			return source;
		}
	}
	public static class ItemRules
	{
		public static bool ShouldDropItem(this IPlayerInfo player, IItemInfo item, TeleporterConfigState state)
		{
			bool isDropDefault = state.Behavior == ItemTeleportBehavior.Drop;
			return player.ShouldDropItem(item, isDropDefault, state.Rules);
		}

		public static bool ShouldDropItem(this IPlayerInfo player, IItemInfo item, bool isDropDefault, List<ItemRule> rules)
		{
			if (item != null)
			{
				return isDropDefault ^ rules.Any((ItemRule rule) => rule.IsMatch(player, item));
			}
			return false;
		}

		public static ItemRule FromId(string id, ItemFilterList itemList)
		{
			switch (id)
			{
			case "all":
				return new AllFilter(itemList);
			case "none":
				return new NoneFilter(itemList);
			case "held":
				return new HeldItemFilter(itemList);
			case "pocketed":
				return new PocketedItemFilter(itemList);
			case "scrap":
				return new ScrapItemFilter(itemList);
			case "nonscrap":
				return new NonScrapItemFilter(itemList);
			case "value":
				return new ValueItemFilter(itemList);
			case "worthless":
				return new WorthlessItemFilter(itemList);
			case "metal":
				return new MetalItemFilter(itemList);
			case "nonmetal":
				return new NonMetalItemFilter(itemList);
			case "weapon":
				return new WeaponItemFilter(itemList);
			case "nonweapon":
				return new NonWeaponItemFilter(itemList);
			case "battery":
				return new BatteryItemFilter(itemList);
			case "nonbattery":
				return new NonBatteryItemFilter(itemList);
			case "charged":
				return new ChargedItemFilter(itemList);
			case "discharged":
				return new DischargedItemFilter(itemList);
			case "onehanded":
				return new OneHandedItemFilter(itemList);
			case "twohanded":
				return new TwoHandedItemFilter(itemList);
			case "weighted":
				return new WeightedItemFilter(itemList);
			case "weightless":
				return new WeightlessItemFilter(itemList);
			case "gordion":
				return new GordionFilter(itemList);
			case "gordioff":
				return new GordioffFilter(itemList);
			default:
			{
				ManualLogSource logger = Plugin.Logger;
				if (logger != null)
				{
					logger.LogWarning((object)("Unknown item filter: " + id + ". Falling back to item name matching."));
				}
				return new ItemNameRule(id);
			}
			}
		}
	}
	public abstract class ItemRule
	{
		[CompilerGenerated]
		private string <id>P;

		protected ItemRule(string id)
		{
			<id>P = id;
			base..ctor();
		}

		public abstract bool IsMatch(IPlayerInfo player, IItemInfo item);

		public override string ToString()
		{
			return <id>P;
		}
	}
	public class ItemNameRule : ItemRule
	{
		private const StringComparison caseInsensitive = StringComparison.OrdinalIgnoreCase;

		private readonly string name;

		public ItemNameRule(string name)
		{
			this.name = name;
			base..ctor(name);
		}

		public override bool IsMatch(IPlayerInfo player, IItemInfo item)
		{
			if (item.Name.Equals(name, StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			if (item.TypeName.Equals(name, StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			if (item.DisplayName.Equals(name, StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			return false;
		}
	}
	public record ItemFilterList
	{
		public bool IsExclusive { get; set; }

		public List<ItemRule> Rules { get; set; }

		public ItemFilterList(bool isExclusive, List<ItemRule> rules)
		{
			IsExclusive = isExclusive;
			Rules = rules;
		}
	}
	public abstract class ItemFilter : ItemRule
	{
		[CompilerGenerated]
		private ItemFilterList <itemList>P;

		protected ItemFilter(string id, ItemFilterList itemList)
		{
			<itemList>P = itemList;
			base..ctor(id);
		}

		public override bool IsMatch(IPlayerInfo player, IItemInfo item)
		{
			if (<itemList>P.Rules.Count == 0)
			{
				return true;
			}
			return <itemList>P.IsExclusive ^ <itemList>P.Rules.Any((ItemRule rule) => rule.IsMatch(player, item));
		}
	}
	public class AllFilter : ItemFilter
	{
		public const string Id = "all";

		public AllFilter(ItemFilterList except)
			: base("all", except)
		{
		}

		public override bool IsMatch(IPlayerInfo player, IItemInfo item)
		{
			return base.IsMatch(player, item);
		}
	}
	public class NoneFilter : ItemFilter
	{
		public const string Id = "none";

		public NoneFilter(ItemFilterList except)
			: base("none", except)
		{
		}

		public override bool IsMatch(IPlayerInfo player, IItemInfo item)
		{
			return !base.IsMatch(player, item);
		}
	}
	public class HeldItemFilter : ItemFilter
	{
		public const string Id = "held";

		public HeldItemFilter(ItemFilterList except)
			: base("held", except)
		{
		}

		public override bool IsMatch(IPlayerInfo player, IItemInfo item)
		{
			if (!item.IsPocketed.HasValue)
			{
				Plugin.Logger.LogWarning((object)"Unable to use filter [held] due to read issues on GrabbableObject. Skipping filter.");
				return false;
			}
			if (!item.IsPocketed.Value)
			{
				return base.IsMatch(player, item);
			}
			return false;
		}
	}
	public class PocketedItemFilter : ItemFilter
	{
		public const string Id = "pocketed";

		public PocketedItemFilter(ItemFilterList except)
			: base("pocketed", except)
		{
		}

		public override bool IsMatch(IPlayerInfo player, IItemInfo item)
		{
			if (!item.IsPocketed.HasValue)
			{
				Plugin.Logger.LogWarning((object)"Unable to use filter [pocketed] due to read issues on GrabbableObject. Skipping filter.");
				return false;
			}
			if (item.IsPocketed.Value)
			{
				return base.IsMatch(player, item);
			}
			return false;
		}
	}
	public class ScrapItemFilter : ItemFilter
	{
		public const string Id = "scrap";

		public ScrapItemFilter(ItemFilterList except)
			: base("scrap", except)
		{
		}

		public override bool IsMatch(IPlayerInfo player, IItemInfo item)
		{
			if (!item.IsScrap.HasValue)
			{
				Plugin.Logger.LogWarning((object)"Unable to use filter [scrap] due to read issues on GrabbableObject. Skipping filter.");
				return false;
			}
			if (item.IsScrap.Value)
			{
				return base.IsMatch(player, item);
			}
			return false;
		}
	}
	public class NonScrapItemFilter : ItemFilter
	{
		public const string Id = "nonscrap";

		public NonScrapItemFilter(ItemFilterList except)
			: base("nonscrap", except)
		{
		}

		public override bool IsMatch(IPlayerInfo player, IItemInfo item)
		{
			if (!item.IsScrap.HasValue)
			{
				Plugin.Logger.LogWarning((object)"Unable to use filter [nonscrap] due to read issues on GrabbableObject. Skipping filter.");
				return false;
			}
			if (!item.IsScrap.Value)
			{
				return base.IsMatch(player, item);
			}
			return false;
		}
	}
	public class ValueItemFilter : ItemFilter
	{
		public const string Id = "value";

		public ValueItemFilter(ItemFilterList except)
			: base("value", except)
		{
		}

		public override bool IsMatch(IPlayerInfo player, IItemInfo item)
		{
			if (!item.IsScrap.HasValue || !item.Value.HasValue)
			{
				Plugin.Logger.LogWarning((object)"Unable to use filter [value] due to read issues on GrabbableObject. Skipping filter.");
				return false;
			}
			if (item.IsScrap.Value && item.Value.Value > 0)
			{
				return base.IsMatch(player, item);
			}
			return false;
		}
	}
	public class WorthlessItemFilter : ItemFilter
	{
		public const string Id = "worthless";

		public WorthlessItemFilter(ItemFilterList except)
			: base("worthless", except)
		{
		}

		public override bool IsMatch(IPlayerInfo player, IItemInfo item)
		{
			if (!item.IsScrap.HasValue || !item.Value.HasValue)
			{
				Plugin.Logger.LogWarning((object)"Unable to use filter [worthless] due to read issues on GrabbableObject. Skipping filter.");
				return false;
			}
			if (!item.IsScrap.Value || item.Value.Value == 0)
			{
				return base.IsMatch(player, item);
			}
			return false;
		}
	}
	public class MetalItemFilter : ItemFilter
	{
		public const string Id = "metal";

		public MetalItemFilter(ItemFilterList except)
			: base("metal", except)
		{
		}

		public override bool IsMatch(IPlayerInfo player, IItemInfo item)
		{
			if (!item.IsMetal.HasValue)
			{
				Plugin.Logger.LogWarning((object)"Unable to use filter [metal] due to read issues on GrabbableObject. Skipping filter.");
				return false;
			}
			if (item.IsMetal.Value)
			{
				return base.IsMatch(player, item);
			}
			return false;
		}
	}
	public class NonMetalItemFilter : ItemFilter
	{
		public const string Id = "nonmetal";

		public NonMetalItemFilter(ItemFilterList except)
			: base("nonmetal", except)
		{
		}

		public override bool IsMatch(IPlayerInfo player, IItemInfo item)
		{
			if (!item.IsMetal.HasValue)
			{
				Plugin.Logger.LogWarning((object)"Unable to use filter [nonmetal] due to read issues on GrabbableObject. Skipping filter.");
				return false;
			}
			if (!item.IsMetal.Value)
			{
				return base.IsMatch(player, item);
			}
			return false;
		}
	}
	public class WeaponItemFilter : ItemFilter
	{
		public const string Id = "weapon";

		public WeaponItemFilter(ItemFilterList except)
			: base("weapon", except)
		{
		}

		public override bool IsMatch(IPlayerInfo player, IItemInfo item)
		{
			if (!item.IsWeapon.HasValue)
			{
				Plugin.Logger.LogWarning((object)"Unable to use filter [weapon] due to read issues on GrabbableObject. Skipping filter.");
				return false;
			}
			if (item.IsWeapon.Value)
			{
				return base.IsMatch(player, item);
			}
			return false;
		}
	}
	public class NonWeaponItemFilter : ItemFilter
	{
		public const string Id = "nonweapon";

		public NonWeaponItemFilter(ItemFilterList except)
			: base("nonweapon", except)
		{
		}

		public override bool IsMatch(IPlayerInfo player, IItemInfo item)
		{
			if (!item.IsWeapon.HasValue)
			{
				Plugin.Logger.LogWarning((object)"Unable to use filter [nonweapon] due to read issues on GrabbableObject. Skipping filter.");
				return false;
			}
			if (!item.IsWeapon.Value)
			{
				return base.IsMatch(player, item);
			}
			return false;
		}
	}
	public class BatteryItemFilter : ItemFilter
	{
		public const string Id = "battery";

		public BatteryItemFilter(ItemFilterList except)
			: base("battery", except)
		{
		}

		public override bool IsMatch(IPlayerInfo player, IItemInfo item)
		{
			if (!item.HasBattery.HasValue)
			{
				Plugin.Logger.LogWarning((object)"Unable to use filter [battery] due to read issues on GrabbableObject. Skipping filter.");
				return false;
			}
			if (item.HasBattery.Value)
			{
				return base.IsMatch(player, item);
			}
			return false;
		}
	}
	public class NonBatteryItemFilter : ItemFilter
	{
		public const string Id = "nonbattery";

		public NonBatteryItemFilter(ItemFilterList except)
			: base("nonbattery", except)
		{
		}

		public override bool IsMatch(IPlayerInfo player, IItemInfo item)
		{
			if (!item.HasBattery.HasValue)
			{
				Plugin.Logger.LogWarning((object)"Unable to use filter [nonbattery] due to read issues on GrabbableObject. Skipping filter.");
				return false;
			}
			if (!item.HasBattery.Value)
			{
				return base.IsMatch(player, item);
			}
			return false;
		}
	}
	public class ChargedItemFilter : ItemFilter
	{
		public const string Id = "charged";

		public ChargedItemFilter(ItemFilterList except)
			: base("charged", except)
		{
		}

		public override bool IsMatch(IPlayerInfo player, IItemInfo item)
		{
			if (!item.HasBattery.HasValue || !item.BatteryCharge.HasValue)
			{
				Plugin.Logger.LogWarning((object)"Unable to use filter [charged] due to read issues on GrabbableObject. Skipping filter.");
				return false;
			}
			if (item.HasBattery.Value && item.BatteryCharge.Value > 0f)
			{
				return base.IsMatch(player, item);
			}
			return false;
		}
	}
	public class DischargedItemFilter : ItemFilter
	{
		public const string Id = "discharged";

		public DischargedItemFilter(ItemFilterList except)
			: base("discharged", except)
		{
		}

		public override bool IsMatch(IPlayerInfo player, IItemInfo item)
		{
			if (!item.HasBattery.HasValue || !item.BatteryCharge.HasValue)
			{
				Plugin.Logger.LogWarning((object)"Unable to use filter [discharged] due to read issues on GrabbableObject. Skipping filter.");
				return false;
			}
			if (item.HasBattery.Value && item.BatteryCharge.Value == 0f)
			{
				return base.IsMatch(player, item);
			}
			return false;
		}
	}
	public class OneHandedItemFilter : ItemFilter
	{
		public const string Id = "onehanded";

		public OneHandedItemFilter(ItemFilterList except)
			: base("onehanded", except)
		{
		}

		public override bool IsMatch(IPlayerInfo player, IItemInfo item)
		{
			if (!item.IsTwoHanded.HasValue)
			{
				Plugin.Logger.LogWarning((object)"Unable to use filter [onehanded] due to read issues on GrabbableObject. Skipping filter.");
				return false;
			}
			if (!item.IsTwoHanded.Value)
			{
				return base.IsMatch(player, item);
			}
			return false;
		}
	}
	public class TwoHandedItemFilter : ItemFilter
	{
		public const string Id = "twohanded";

		public TwoHandedItemFilter(ItemFilterList except)
			: base("twohanded", except)
		{
		}

		public override bool IsMatch(IPlayerInfo player, IItemInfo item)
		{
			if (!item.IsTwoHanded.HasValue)
			{
				Plugin.Logger.LogWarning((object)"Unable to use filter [twohanded] due to read issues on GrabbableObject. Skipping filter.");
				return false;
			}
			if (item.IsTwoHanded.Value)
			{
				return base.IsMatch(player, item);
			}
			return false;
		}
	}
	public class WeightedItemFilter : ItemFilter
	{
		public const string Id = "weighted";

		public WeightedItemFilter(ItemFilterList except)
			: base("weighted", except)
		{
		}

		public override bool IsMatch(IPlayerInfo player, IItemInfo item)
		{
			if (!item.Weight.HasValue)
			{
				Plugin.Logger.LogWarning((object)"Unable to use filter [weighted] due to read issues on GrabbableObject. Skipping filter.");
				return false;
			}
			if (item.Weight.Value > 1f)
			{
				return base.IsMatch(player, item);
			}
			return false;
		}
	}
	public class WeightlessItemFilter : ItemFilter
	{
		public const string Id = "weightless";

		public WeightlessItemFilter(ItemFilterList except)
			: base("weightless", except)
		{
		}

		public override bool IsMatch(IPlayerInfo player, IItemInfo item)
		{
			if (!item.Weight.HasValue)
			{
				Plugin.Logger.LogWarning((object)"Unable to use filter [weightless] due to read issues on GrabbableObject. Skipping filter.");
				return false;
			}
			if (item.Weight.Value <= 1f)
			{
				return base.IsMatch(player, item);
			}
			return false;
		}
	}
	public class GordionFilter : ItemFilter
	{
		public const string Id = "gordion";

		public GordionFilter(ItemFilterList except)
			: base("gordion", except)
		{
		}

		public override bool IsMatch(IPlayerInfo player, IItemInfo item)
		{
			try
			{
				return !StartOfRound.Instance.inShipPhase && StartOfRound.Instance.currentLevel.levelID == 3 && base.IsMatch(player, item);
			}
			catch
			{
				Plugin.Logger.LogWarning((object)"Unable to use filter [gordion] due to read issues on StartOfRound. Skipping filter.");
				return false;
			}
		}
	}
	public class GordioffFilter : ItemFilter
	{
		public const string Id = "gordioff";

		public GordioffFilter(ItemFilterList except)
			: base("gordioff", except)
		{
		}

		public override bool IsMatch(IPlayerInfo player, IItemInfo item)
		{
			try
			{
				return !StartOfRound.Instance.inShipPhase && StartOfRound.Instance.currentLevel.levelID != 3 && base.IsMatch(player, item);
			}
			catch
			{
				Plugin.Logger.LogWarning((object)"Unable to use filter [gordioff] due to read issues on StartOfRound. Skipping filter.");
				return false;
			}
		}
	}
	public static class ReflectionHelper
	{
		private static FieldInfo _cooldownTimeField;

		private static bool _cooldownTimeFieldChecked;

		public static FieldInfo GetShipTeleporterCooldownTimeField()
		{
			if (_cooldownTimeFieldChecked)
			{
				return _cooldownTimeField;
			}
			_cooldownTimeFieldChecked = true;
			try
			{
				_cooldownTimeField = typeof(ShipTeleporter).GetField("cooldownTime", BindingFlags.Instance | BindingFlags.NonPublic);
				if (_cooldownTimeField == null)
				{
					Plugin.Logger.LogWarning((object)"Reflection failed: Could not find ShipTeleporter.cooldownTime field. Teleporter cooldown features will be disabled.");
				}
			}
			catch (Exception arg)
			{
				Plugin.Logger.LogError((object)$"Reflection error finding ShipTeleporter.cooldownTime: {arg}");
				_cooldownTimeField = null;
			}
			return _cooldownTimeField;
		}
	}
	public class TeleporterConfigState
	{
		public readonly ItemTeleportBehavior Behavior;

		public readonly List<ItemRule> Rules;

		private static bool _init;

		private static readonly (Func<string> Raw, List<ItemRule> Rules)[,] _cache = new(Func<string>, List<ItemRule>)[2, 2];

		public TeleporterConfigState(bool inverse)
		{
			ModConfig config = Plugin.ModConfig;
			if (!_init)
			{
				_init = true;
				_cache[0, 0] = (() => config.TeleporterAlwaysKeep.Value, null);
				_cache[0, 1] = (() => config.TeleporterAlwaysDrop.Value, null);
				_cache[1, 0] = (() => config.InverseTeleporterAlwaysKeep.Value, null);
				_cache[1, 1] = (() => config.InverseTeleporterAlwaysDrop.Value, null);
				SyncedEntry<string> teleporterAlwaysKeep = config.TeleporterAlwaysKeep;
				teleporterAlwaysKeep.OnChanged = (Action<string, string>)Delegate.Combine(teleporterAlwaysKeep.OnChanged, (Action<string, string>)delegate
				{
					Reparse(ref _cache[0, 0]);
				});
				SyncedEntry<string> teleporterAlwaysDrop = config.TeleporterAlwaysDrop;
				teleporterAlwaysDrop.OnChanged = (Action<string, string>)Delegate.Combine(teleporterAlwaysDrop.OnChanged, (Action<string, string>)delegate
				{
					Reparse(ref _cache[0, 1]);
				});
				SyncedEntry<string> inverseTeleporterAlwaysKeep = config.InverseTeleporterAlwaysKeep;
				inverseTeleporterAlwaysKeep.OnChanged = (Action<string, string>)Delegate.Combine(inverseTeleporterAlwaysKeep.OnChanged, (Action<string, string>)delegate
				{
					Reparse(ref _cache[1, 0]);
				});
				SyncedEntry<string> inverseTeleporterAlwaysDrop = config.InverseTeleporterAlwaysDrop;
				inverseTeleporterAlwaysDrop.OnChanged = (Action<string, string>)Delegate.Combine(inverseTeleporterAlwaysDrop.OnChanged, (Action<string, string>)delegate
				{
					Reparse(ref _cache[1, 1]);
				});
			}
			Behavior = (inverse ? config.InverseTeleporterBehavior.Value : config.TeleporterBehavior.Value);
			int num = (inverse ? 1 : 0);
			int num2 = ((Behavior == ItemTeleportBehavior.Keep) ? 1 : 0);
			ref(Func<string>, List<ItemRule>) reference = ref _cache[num, num2];
			ref List<ItemRule> item = ref reference.Item2;
			Rules = item ?? (item = ItemParser.ParseConfig(reference.Item1()));
		}

		private static void Reparse(ref (Func<string> Raw, List<ItemRule> Rules) entry)
		{
			entry.Rules = ItemParser.ParseConfig(entry.Raw());
		}
	}
}
namespace BetterBetterTeleporter.Patches
{
	[HarmonyPatch]
	public class FixTeleporterBugsPatch
	{
		[CompilerGenerated]
		private sealed class <DelayedForceSync>d__3 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public PlayerControllerB player;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <DelayedForceSync>d__3(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0023: Unknown result type (might be due to invalid IL or missing references)
				//IL_002d: Expected O, but got Unknown
				//IL_005f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0069: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForFixedUpdate();
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					UpdatePositionForNewlyJoinedClient?.SetValue(player, true);
					<>2__current = (object)new WaitForSecondsRealtime(0.2f);
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -1;
					UpdatePositionForNewlyJoinedClient?.SetValue(player, true);
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private static readonly FieldInfo UpdatePositionForNewlyJoinedClient = AccessTools.Field(typeof(PlayerControllerB), "updatePositionForNewlyJoinedClient");

		private static bool HasFailedToDirtyTeleportPosition = false;

		[HarmonyPatch(typeof(PlayerControllerB), "TeleportPlayer")]
		[HarmonyPrefix]
		public static void TeleportPlayer(PlayerControllerB __instance, ref Vector3 pos)
		{
			if (HasFailedToDirtyTeleportPosition || !TeleportDetectionPatch.IsRegularTeleporting())
			{
				return;
			}
			try
			{
				pos.y -= 0.5f;
				((MonoBehaviour)__instance).StartCoroutine(DelayedForceSync(__instance));
			}
			catch
			{
				Plugin.Logger.LogWarning((object)"Failed to apply teleport positioning fix. Disabling future attempts.");
				HasFailedToDirtyTeleportPosition = true;
			}
		}

		[IteratorStateMachine(typeof(<DelayedForceSync>d__3))]
		private static IEnumerator DelayedForceSync(PlayerControllerB player)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <DelayedForceSync>d__3(0)
			{
				player = player
			};
		}
	}
	[HarmonyPatch(typeof(ShipTeleporter), "TeleportPlayerOutWithInverseTeleporter")]
	public static class InverseTeleporterBatteryDrainPatch
	{
		[HarmonyPostfix]
		public static void TeleportPlayerOutWithInverseTeleporterPostfix(int playerObj, Vector3 teleportPos)
		{
			float num = (float)Plugin.ModConfig.BatteryDrainPercent.Value / 100f;
			if (num == 0f)
			{
				return;
			}
			try
			{
				GrabbableObject[] itemSlots = StartOfRound.Instance.allPlayerScripts[playerObj].ItemSlots;
				foreach (GrabbableObject val in itemSlots)
				{
					Battery val2 = val?.insertedBattery;
					if (val2 != null)
					{
						val2.charge = Mathf.Max(0f, val2.charge - num);
						val.SyncBatteryServerRpc((int)(val2.charge * 100f));
					}
				}
				Plugin.Logger.LogDebug((object)$"Client {playerObj} batteries drained by {num}.");
			}
			catch (Exception arg)
			{
				Plugin.Logger.LogError((object)$"Failed to drain batteries after inverse teleport: {arg}");
			}
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB), "DropAllHeldItems")]
	public static class KeepItemsOnTeleporterPatch
	{
		private static readonly Dictionary<PlayerControllerB, GrabbableObject[]> tempInventories = new Dictionary<PlayerControllerB, GrabbableObject[]>();

		private static readonly MethodInfo SwitchToItemSlotMethod = AccessTools.Method(typeof(PlayerControllerB), "SwitchToItemSlot", (Type[])null, (Type[])null);

		[HarmonyPrefix]
		public static void DropAllHeldItemsPrefix(PlayerControllerB __instance)
		{
			if (!TeleportDetectionPatch.IsTeleporting(__instance))
			{
				return;
			}
			GrabbableObject[] array = (GrabbableObject[])__instance.ItemSlots.Clone();
			try
			{
				PlayerInfo playerInfo = new PlayerInfo(__instance);
				TeleporterConfigState teleportState = GetTeleportState(__instance);
				GrabbableObject[] array2 = (GrabbableObject[])__instance.ItemSlots.Clone();
				for (int i = 0; i < __instance.ItemSlots.Length; i++)
				{
					if (playerInfo.ShouldDropItem(playerInfo.Slots[i], teleportState))
					{
						array2[i] = null;
					}
					else
					{
						__instance.ItemSlots[i] = null;
					}
				}
				__instance.isHoldingObject = (Object)(object)__instance.ItemSlots[__instance.currentItemSlot] != (Object)null;
				tempInventories[__instance] = array2;
			}
			catch (Exception arg)
			{
				Plugin.Logger.LogError((object)$"Failed to intercept DropAllHeldItems (Prefix). Falling back to native behavior. Error: {arg}");
				tempInventories.Remove(__instance);
				for (int j = 0; j < __instance.ItemSlots.Length; j++)
				{
					__instance.ItemSlots[j] = array[j];
				}
			}
		}

		[HarmonyPostfix]
		public static void DropAllHeldItemsPostfix(PlayerControllerB __instance)
		{
			if (!tempInventories.ContainsKey(__instance))
			{
				return;
			}
			GrabbableObject[] array = tempInventories[__instance];
			tempInventories.Remove(__instance);
			try
			{
				float num = 0f;
				for (int i = 0; i < __instance.ItemSlots.Length; i++)
				{
					GrabbableObject val = array[i];
					if (!((Object)(object)val == (Object)null))
					{
						__instance.ItemSlots[i] = val;
						num += val.itemProperties.weight - 1f;
					}
				}
				__instance.carryWeight = Mathf.Clamp(__instance.carryWeight + num, 1f, 10f);
			}
			catch (Exception arg)
			{
				Plugin.Logger.LogError((object)$"Failed to reset carry weight. Error: {arg}");
			}
			try
			{
				__instance.isHoldingObject = (Object)(object)__instance.ItemSlots[__instance.currentItemSlot] != (Object)null;
				SwitchToItemSlotMethod.Invoke(__instance, new object[2] { __instance.currentItemSlot, null });
			}
			catch (Exception arg2)
			{
				Plugin.Logger.LogWarning((object)$"Unable to verify current item is being held correctly. Error: {arg2}");
			}
		}

		private static TeleporterConfigState GetTeleportState(PlayerControllerB player)
		{
			return new TeleporterConfigState(TeleportDetectionPatch.IsInverseTeleporting(player));
		}
	}
	[HarmonyPatch(typeof(StartOfRound))]
	public static class ResetCooldownOnOrbitPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("StartGame")]
		[HarmonyPatch("EndOfGame")]
		[HarmonyPatch("EndOfGameClientRpc")]
		private static void ResetCooldowns()
		{
			if (!Plugin.ModConfig.ResetCooldownOnOrbit.Value)
			{
				return;
			}
			FieldInfo shipTeleporterCooldownTimeField = ReflectionHelper.GetShipTeleporterCooldownTimeField();
			if (shipTeleporterCooldownTimeField == null)
			{
				return;
			}
			ShipTeleporter[] array = Object.FindObjectsOfType<ShipTeleporter>();
			foreach (ShipTeleporter val in array)
			{
				try
				{
					if ((float)shipTeleporterCooldownTimeField.GetValue(val) > 0f)
					{
						shipTeleporterCooldownTimeField.SetValue(val, 0);
						Plugin.Logger.LogDebug((object)("Reset cooldown on " + (val.isInverseTeleporter ? "Inverse Teleporter" : "Teleporter") + "."));
					}
				}
				catch (Exception ex)
				{
					Plugin.Logger.LogError((object)("Error resetting cooldown on teleporter " + ((Object)val).name + ": " + ex.Message));
				}
			}
		}
	}
	[HarmonyPatch(typeof(ShipTeleporter))]
	public static class TeleportDetectionPatch
	{
		[CompilerGenerated]
		private sealed class <TeleporterTranspiler>d__2 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private CodeInstruction <>2__current;

			private int <>l__initialThreadId;

			private IEnumerable<CodeInstruction> instructions;

			public IEnumerable<CodeInstruction> <>3__instructions;

			private MethodInfo <dropAllHeldItemsMethod>5__2;

			private MethodInfo <beforeMethod>5__3;

			private IEnumerator<CodeInstruction> <>7__wrap3;

			private CodeInstruction <instruction>5__5;

			CodeInstruction IEnumerator<CodeInstruction>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <TeleporterTranspiler>d__2(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || (uint)(num - 1) <= 1u)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<dropAllHeldItemsMethod>5__2 = null;
				<beforeMethod>5__3 = null;
				<>7__wrap3 = null;
				<instruction>5__5 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b4: Expected O, but got Unknown
				try
				{
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						<dropAllHeldItemsMethod>5__2 = AccessTools.Method(typeof(PlayerControllerB), "DropAllHeldItems", (Type[])null, (Type[])null);
						<beforeMethod>5__3 = AccessTools.Method(typeof(TeleportDetectionPatch), "BeforeTeleporterDropAllHeldItems", (Type[])null, (Type[])null);
						<>7__wrap3 = instructions.GetEnumerator();
						<>1__state = -3;
						goto IL_00ed;
					case 1:
						<>1__state = -3;
						goto IL_00c7;
					case 2:
						{
							<>1__state = -3;
							<instruction>5__5 = null;
							goto IL_00ed;
						}
						IL_00ed:
						if (<>7__wrap3.MoveNext())
						{
							<instruction>5__5 = <>7__wrap3.Current;
							if (CodeInstructionExtensions.Calls(<instruction>5__5, <dropAllHeldItemsMethod>5__2))
							{
								<>2__current = new CodeInstruction(OpCodes.Call, (object)<beforeMethod>5__3);
								<>1__state = 1;
								return true;
							}
							goto IL_00c7;
						}
						<>m__Finally1();
						<>7__wrap3 = null;
						return false;
						IL_00c7:
						<>2__current = <instruction>5__5;
						<>1__state = 2;
						return true;
					}
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				if (<>7__wrap3 != null)
				{
					<>7__wrap3.Dispose();
				}
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator()
			{
				<TeleporterTranspiler>d__2 <TeleporterTranspiler>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<TeleporterTranspiler>d__ = this;
				}
				else
				{
					<TeleporterTranspiler>d__ = new <TeleporterTranspiler>d__2(0);
				}
				<TeleporterTranspiler>d__.instructions = <>3__instructions;
				return <TeleporterTranspiler>d__;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<CodeInstruction>)this).GetEnumerator();
			}
		}

		private static bool isTeleporting;

		private static readonly HashSet<int> InverseTeleportingPlayers = new HashSet<int>();

		public static bool IsTeleporting(PlayerControllerB player)
		{
			if (!StartOfRound.Instance.ClientPlayerList.ContainsKey(player.actualClientId))
			{
				return false;
			}
			if (IsRegularTeleporting())
			{
				return true;
			}
			if (IsInverseTeleporting(player))
			{
				return true;
			}
			return false;
		}

		[IteratorStateMachine(typeof(<TeleporterTranspiler>d__2))]
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> TeleporterTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <TeleporterTranspiler>d__2(-2)
			{
				<>3__instructions = instructions
			};
		}

		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyFinalizer]
		private static Exception TeleporterFinalizer(Exception __exception)
		{
			AfterTeleporterDropAllHeldItems();
			return __exception;
		}

		public static void BeforeTeleporterDropAllHeldItems()
		{
			isTeleporting = true;
		}

		public static void AfterTeleporterDropAllHeldItems()
		{
			isTeleporting = false;
		}

		public static bool IsRegularTeleporting()
		{
			return isTeleporting;
		}

		public static bool IsInverseTeleporting(PlayerControllerB player)
		{
			return InverseTeleportingPlayers.Contains((int)player.playerClientId);
		}

		[HarmonyPatch("TeleportPlayerOutWithInverseTeleporter")]
		[HarmonyPrefix]
		public static void TeleportPlayerOutWithInverseTeleporterPrefix(int playerObj)
		{
			InverseTeleportingPlayers.Add(playerObj);
		}

		[HarmonyPatch("TeleportPlayerOutWithInverseTeleporter")]
		[HarmonyPostfix]
		public static void TeleportPlayerOutWithInverseTeleporterPostfix(int playerObj)
		{
			InverseTeleportingPlayers.Remove(playerObj);
		}
	}
	[HarmonyPatch(typeof(ShipTeleporter))]
	public static class TeleporterCooldownPatch
	{
		static TeleporterCooldownPatch()
		{
			SyncedEntry<int> teleporterCooldown = Plugin.ModConfig.TeleporterCooldown;
			teleporterCooldown.OnChanged = (Action<int, int>)Delegate.Combine(teleporterCooldown.OnChanged, new Action<int, int>(UpdateAllTeleporterCooldowns));
			SyncedEntry<int> inverseTeleporterCooldown = Plugin.ModConfig.InverseTeleporterCooldown;
			inverseTeleporterCooldown.OnChanged = (Action<int, int>)Delegate.Combine(inverseTeleporterCooldown.OnChanged, new Action<int, int>(UpdateAllTeleporterCooldowns));
		}

		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		public static void AwakePostfix(ShipTeleporter __instance)
		{
			(int inverse, int regular) cooldowns = GetCooldowns();
			int item = cooldowns.inverse;
			int item2 = cooldowns.regular;
			__instance.cooldownAmount = (__instance.isInverseTeleporter ? item : item2);
		}

		private static void UpdateAllTeleporterCooldowns(int oldValue, int newValue)
		{
			if (oldValue == newValue)
			{
				return;
			}
			FieldInfo shipTeleporterCooldownTimeField = ReflectionHelper.GetShipTeleporterCooldownTimeField();
			if (shipTeleporterCooldownTimeField == null)
			{
				return;
			}
			(int inverse, int regular) cooldowns = GetCooldowns();
			int item = cooldowns.inverse;
			int item2 = cooldowns.regular;
			ShipTeleporter[] array = Object.FindObjectsOfType<ShipTeleporter>();
			foreach (ShipTeleporter val in array)
			{
				try
				{
					val.cooldownAmount = (val.isInverseTeleporter ? item : item2);
					shipTeleporterCooldownTimeField.SetValue(val, Mathf.Min(val.cooldownAmount, (float)(shipTeleporterCooldownTimeField.GetValue(val) ?? ((object)0))));
				}
				catch (Exception ex)
				{
					Plugin.Logger.LogError((object)$"Error setting cooldown on teleporter {val.teleporterId}: {ex.Message}");
				}
			}
		}

		private static (int inverse, int regular) GetCooldowns()
		{
			return (Plugin.ModConfig.InverseTeleporterCooldown.Value, Plugin.ModConfig.TeleporterCooldown.Value);
		}
	}
}
namespace BetterBetterTeleporter.Networking
{
	public interface ISyncable
	{
		int GetSize();

		void ResetValue();

		void SetFromReader(FastBufferReader reader);

		void WriteToWriter(FastBufferWriter writer);
	}
	[HarmonyPatch]
	public static class PlayerConnectionPatch
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static HandleNamedMessageDelegate <>9__1_0;

			internal void <ConnectClientToPlayerObject>b__1_0(ulong clientId, FastBufferReader reader)
			{
				SyncedEntries.SendAllToClient(clientId);
			}
		}

		private const string MessageName = "BetterBetterTeleporter.Connect";

		[HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")]
		[HarmonyPostfix]
		public static void ConnectClientToPlayerObject()
		{
			//IL_005f: 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_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			CustomMessagingManager customMessagingManager = NetworkManager.Singleton.CustomMessagingManager;
			if (NetworkManager.Singleton.IsServer)
			{
				SyncedEntries.ResetToLocalConfig();
				object obj = <>c.<>9__1_0;
				if (obj == null)
				{
					HandleNamedMessageDelegate val = delegate(ulong clientId, FastBufferReader reader)
					{
						SyncedEntries.SendAllToClient(clientId);
					};
					<>c.<>9__1_0 = val;
					obj = (object)val;
				}
				customMessagingManager.RegisterNamedMessageHandler("BetterBetterTeleporter.Connect", (HandleNamedMessageDelegate)obj);
				return;
			}
			SyncedEntries.BeginListening();
			FastBufferWriter val2 = default(FastBufferWriter);
			((FastBufferWriter)(ref val2))..ctor(0, (Allocator)2, -1);
			try
			{
				customMessagingManager.SendNamedMessage("BetterBetterTeleporter.Connect", 0uL, val2, (NetworkDelivery)3);
			}
			finally
			{
				((IDisposable)(FastBufferWriter)(ref val2)).Dispose();
			}
		}

		[HarmonyPatch(typeof(GameNetworkManager), "StartDisconnect")]
		[HarmonyPostfix]
		public static void PlayerLeave()
		{
			SyncedEntries.StopListening();
		}
	}
	public static class SyncedEntries
	{
		private class PayloadChunk
		{
			public int Size;

			public ICollection<KeyValuePair<byte, ISyncable>> Items = new List<KeyValuePair<byte, ISyncable>>();
		}

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

		[CompilerGenerated]
		private sealed class <Broadcast>d__8 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <Broadcast>d__8(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSecondsRealtime(0.05f);
					<>1__state = 1;
					return true;
				case 1:
				{
					<>1__state = -1;
					if (!Object.op_Implicit((Object)(object)NetworkManager.Singleton) || !NetworkManager.Singleton.IsServer || NetworkManager.Singleton.ConnectedClientsList.Count <= 1)
					{
						_isBroadcasting = false;
						return false;
					}
					KeyValuePair<byte, ISyncable>[] payload = AllEntries.Where((KeyValuePair<byte, ISyncable> x) => UnsyncedEntries.Contains(x.Key)).ToArray();
					SendPayload("BetterBetterTeleporter.ConfigSync", payload, NetworkManager.Singleton.ConnectedClientsIds.ToArray()[1..]);
					UnsyncedEntries.Clear();
					_isBroadcasting = false;
					return false;
				}
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private static byte _idGen = 0;

		private const string SyncMessage = "BetterBetterTeleporter.ConfigSync";

		private static readonly Dictionary<byte, ISyncable> AllEntries = new Dictionary<byte, ISyncable>();

		private static readonly HashSet<byte> UnsyncedEntries = new HashSet<byte>();

		private static bool _isBroadcasting = false;

		private static SyncedEntry<T> Add<T>(SyncedEntry<T> item)
		{
			byte id = _idGen++;
			AllEntries.Add(id, item);
			item.Entry.SettingChanged += delegate
			{
				ConfigEntryChanged(id, item);
			};
			return item;
		}

		private static void ConfigEntryChanged<T>(byte key, SyncedEntry<T> item)
		{
			if (!Object.op_Implicit((Object)(object)NetworkManager.Singleton) || !NetworkManager.Singleton.IsConnectedClient)
			{
				item.Value = item.Entry.Value;
			}
			else if (NetworkManager.Singleton.IsServer)
			{
				ScheduleBroadcastFor(key, item);
			}
		}

		private static void ScheduleBroadcastFor<T>(byte id, SyncedEntry<T> item)
		{
			if (!Object.op_Implicit((Object)(object)NetworkManager.Singleton) || !NetworkManager.Singleton.IsServer)
			{
				return;
			}
			item.Value = item.Entry.Value;
			if (NetworkManager.Singleton.ConnectedClientsList.Count > 1)
			{
				UnsyncedEntries.Add(id);
				if (!_isBroadcasting)
				{
					_isBroadcasting = true;
					((MonoBehaviour)NetworkManager.Singleton).StartCoroutine(Broadcast());
				}
			}
		}

		[IteratorStateMachine(typeof(<Broadcast>d__8))]
		private static IEnumerator Broadcast()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <Broadcast>d__8(0);
		}

		public static void SendAllToClient(ulong clientId)
		{
			if (clientId != 0L)
			{
				SendPayload("BetterBetterTeleporter.ConfigSync", AllEntries, clientId);
			}
		}

		private static void SendPayload(string messageName, ICollection<KeyValuePair<byte, ISyncable>> payload, params ulong[] clients)
		{
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			List<PayloadChunk> list = new List<PayloadChunk>(new <>z__ReadOnlySingleElementList<PayloadChunk>(new PayloadChunk()));
			foreach (KeyValuePair<byte, ISyncable> item in payload)
			{
				int num = 1 + item.Value.GetSize();
				if (num + list[list.Count - 1].Size > 1024)
				{
					list.Add(new PayloadChunk());
				}
				list[list.Count - 1].Size += num;
				list[list.Count - 1].Items.Add(item);
			}
			FastBufferWriter val = default(FastBufferWriter);
			foreach (PayloadChunk item2 in list)
			{
				((FastBufferWriter)(ref val))..ctor(item2.Size, (Allocator)2, -1);
				try
				{
					foreach (KeyValuePair<byte, ISyncable> item3 in item2.Items)
					{
						((FastBufferWriter)(ref val)).WriteByteSafe(item3.Key);
						item3.Value.WriteToWriter(val);
					}
					NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage(messageName, (IReadOnlyList<ulong>)clients, val, (NetworkDelivery)3);
				}
				finally
				{
					((IDisposable)(FastBufferWriter)(ref val)).Dispose();
				}
			}
		}

		public static bool BeginListening()
		{
			//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_003f: Expected O, but got Unknown
			NetworkManager singleton = NetworkManager.Singleton;
			if (((singleton != null) ? singleton.CustomMessagingManager : null) == null)
			{
				return false;
			}
			CustomMessagingManager customMessagingManager = NetworkManager.Singleton.CustomMessagingManager;
			object obj = <>O.<0>__ReadPayload;
			if (obj == null)
			{
				HandleNamedMessageDelegate val = ReadPayload;
				<>O.<0>__ReadPayload = val;
				obj = (object)val;
			}
			customMessagingManager.RegisterNamedMessageHandler("BetterBetterTeleporter.ConfigSync", (HandleNamedMessageDelegate)obj);
			return true;
		}

		private static void ReadPayload(ulong clientId, FastBufferReader reader)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)NetworkManager.Singleton) && !NetworkManager.Singleton.IsServer)
			{
				byte key = default(byte);
				while (((FastBufferReader)(ref reader)).TryBeginRead(1))
				{
					((FastBufferReader)(ref reader)).ReadByteSafe(ref key);
					AllEntries[key].SetFromReader(reader);
				}
			}
		}

		public static void ResetToLocalConfig()
		{
			foreach (ISyncable value in AllEntries.Values)
			{
				value.ResetValue();
			}
		}

		public static void StopListening(bool resetToLocalConfig = true)
		{
			if (resetToLocalConfig)
			{
				ResetToLocalConfig();
			}
			UnsyncedEntries.Clear();
			NetworkManager singleton = NetworkManager.Singleton;
			if (((singleton != null) ? singleton.CustomMessagingManager : null) != null)
			{
				NetworkManager.Singleton.CustomMessagingManager.UnregisterNamedMessageHandler("BetterBetterTeleporter.ConfigSync");
			}
		}

		public static SyncedEntry<int> BindSynced(this ConfigFile config, string section, string key, int value, ConfigDescription description)
		{
			return Add(new SyncedEntry<int>(config.Bind<int>(section, key, value, description), (int _) => 4, delegate(FastBufferReader reader)
			{
				//IL_0006: 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)
				int result = default(int);
				((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref result, default(ForPrimitives));
				return result;
			}, delegate(FastBufferWriter writer, int value)
			{
				//IL_0006: 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)
				((FastBufferWriter)(ref writer)).WriteValueSafe<int>(ref value, default(ForPrimitives));
			}));
		}

		public static SyncedEntry<float> BindSynced(this ConfigFile config, string section, string key, float value, ConfigDescription description)
		{
			return Add(new SyncedEntry<float>(config.Bind<float>(section, key, value, description), (float _) => 4, delegate(FastBufferReader reader)
			{
				//IL_0006: 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)
				float result = default(float);
				((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref result, default(ForPrimitives));
				return result;
			}, delegate(FastBufferWriter writer, float value)
			{
				//IL_0006: 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)
				((FastBufferWriter)(ref writer)).WriteValueSafe<float>(ref value, default(ForPrimitives));
			}));
		}

		public static SyncedEntry<bool> BindSynced(this ConfigFile config, string section, string key, bool value, ConfigDescription description)
		{
			return Add(new SyncedEntry<bool>(config.Bind<bool>(section, key, value, description), (bool _) => 1, delegate(FastBufferReader reader)
			{
				//IL_0006: 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)
				bool result = default(bool);
				((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref result, default(ForPrimitives));
				return result;
			}, delegate(FastBufferWriter writer, bool value)
			{
				//IL_0006: 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)
				((FastBufferWriter)(ref writer)).WriteValueSafe<bool>(ref value, default(ForPrimitives));
			}));
		}

		public static SyncedEntry<string> BindSynced(this ConfigFile config, string section, string key, string value, ConfigDescription description)
		{
			return Add(new SyncedEntry<string>(config.Bind<string>(section, key, value, description), (string value) => FastBufferWriter.GetWriteSize(value, true), delegate(FastBufferReader reader)
			{
				string result = default(string);
				((FastBufferReader)(ref reader)).ReadValueSafe(ref result, true);
				return result;
			}, delegate(FastBufferWriter writer, string value)
			{
				((FastBufferWriter)(ref writer)).WriteValueSafe(value, true);
			}));
		}

		public static SyncedEntry<T> BindSynced<T>(this ConfigFile config, string section, string key, T value, ConfigDescription description) where T : Enum
		{
			return Add(new SyncedEntry<T>(config.Bind<T>(section, key, value, description), (T _) => 4, delegate(FastBufferReader reader)
			{
				//IL_0006: 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)
				int num2 = default(int);
				((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num2, default(ForPrimitives));
				return (T)(object)num2;
			}, delegate(FastBufferWriter writer, T value)
			{
				//IL_0012: 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)
				int num = Convert.ToInt32(value);
				((FastBufferWriter)(ref writer)).WriteValueSafe<int>(ref num, default(ForPrimitives));
			}));
		}
	}
	public class SyncedEntry<T> : ISyncable
	{
		private readonly Func<FastBufferReader, T> read;

		private readonly Action<FastBufferWriter, T> write;

		public ConfigEntry<T> Entry;

		public Action<T, T> OnChanged;

		public readonly Func<T, int> calcSize;

		public T Value
		{
			get
			{
				return <Value>k__BackingField;
			}
			set
			{
				T arg = <Value>k__BackingField;
				<Value>k__BackingField = value;
				OnChanged?.Invoke(arg, value);
			}
		}

		public SyncedEntry(ConfigEntry<T> entry, Func<T, int> calcSize, Func<FastBufferReader, T> read, Action<FastBufferWriter, T> write)
		{
			Entry = entry;
			Value = entry.Value;
			this.calcSize = calcSize;
			this.read = read;
			this.write = write;
		}

		public int GetSize()
		{
			return calcSize(Value);
		}

		public void ResetValue()
		{
			Value = Entry.Value;
		}

		public void SetFromReader(FastBufferReader reader)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			Value = read(reader);
		}

		public void WriteToWriter(FastBufferWriter writer)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			write(writer, Value);
		}
	}
}
namespace BetterBetterTeleporter.Integrations
{
	internal static class LethalConfigIntegration
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static Func<GrabbableObject, bool> <>9__9_1;

			public static Func<GrabbableObject, string> <>9__9_2;

			public static GenericButtonHandler <>9__9_0;

			public static Func<ShipTeleporter, bool> <>9__10_1;

			public static GenericButtonHandler <>9__10_0;

			internal void <RegisterShowInventoryButton>b__9_0()
			{
				GrabbableObject[] array = GameNetworkManager.Instance?.localPlayerController?.ItemSlots;
				if (array != null && (Object)(object)HUDManager.Instance != (Object)null)
				{
					string text = string.Join(",", from x in array
						where (Object)(object)x != (Object)null
						select ((Object)x.itemProperties).name);
					HUDManager.Instance.DisplayTip("Current Inventory", text, false, false, "LC_Tip1");
				}
			}

			internal bool <RegisterShowInventoryButton>b__9_1(GrabbableObject x)
			{
				return (Object)(object)x != (Object)null;
			}

			internal string <RegisterShowInventoryButton>b__9_2(GrabbableObject x)
			{
				return ((Object)x.itemProperties).name;
			}

			internal void <RegisterSelfTeleportButton>b__10_0()
			{
				HUDManager instance = HUDManager.Instance;
				StartOfRound instance2 = StartOfRound.Instance;
				PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
				if ((Object)(object)instance == (Object)null || (Object)(object)instance2 == (Object)null || (Object)(object)val == (Object)null)
				{
					return;
				}
				NetworkManager singleton = NetworkManager.Singleton;
				if (singleton != null && singleton.ConnectedClientsList.Count > 1)
				{
					instance.DisplayTip("No cheating", "There's more than one player in the game.", true, false, "LC_Tip1");
					return;
				}
				ShipTeleporter val2 = ((IEnumerable<ShipTeleporter>)Object.FindObjectsOfType<ShipTeleporter>()).FirstOrDefault((Func<ShipTeleporter, bool>)((ShipTeleporter tp) => !tp.isInverseTeleporter));
				if ((Object)(object)val2 == (Object)null)
				{
					instance.DisplayTip("No cheating", "No teleporter on the ship.", true, false, "LC_Tip1");
					return;
				}
				FieldInfo shipTeleporterCooldownTimeField = ReflectionHelper.GetShipTeleporterCooldownTimeField();
				if (shipTeleporterCooldownTimeField != null && shipTeleporterCooldownTimeField.GetValue(val2) is float num && num > 0f)
				{
					instance.DisplayTip("No cheating", "The teleporter is on cooldown.", true, false, "LC_Tip1");
				}
				else
				{
					val2.PressTeleportButtonOnLocalClient();
				}
			}

			internal bool <RegisterSelfTeleportButton>b__10_1(ShipTeleporter tp)
			{
				return !tp.isInverseTeleporter;
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static void Initialize()
		{
			Plugin.Logger.LogInfo((object)"LethalConfig detected — integrating BetterBetterTeleporter config.");
			RegisterAll();
		}

		private static void RegisterAll()
		{
			RegisterCheckbox(Plugin.ModConfig.ResetCooldownOnOrbit.Entry);
			RegisterInput(Plugin.ModConfig.TeleporterCooldown.Entry);
			RegisterDropdown(Plugin.ModConfig.TeleporterBehavior.Entry);
			RegisterTextArea(Plugin.ModConfig.TeleporterAlwaysKeep.Entry);
			RegisterTextArea(Plugin.ModConfig.TeleporterAlwaysDrop.Entry);
			RegisterInput(Plugin.ModConfig.InverseTeleporterCooldown.Entry);
			RegisterDropdown(Plugin.ModConfig.InverseTeleporterBehavior.Entry);
			RegisterTextArea(Plugin.ModConfig.InverseTeleporterAlwaysKeep.Entry);
			RegisterTextArea(Plugin.ModConfig.InverseTeleporterAlwaysDrop.Entry);
			RegisterSlider(Plugin.ModConfig.BatteryDrainPercent.Entry, 0, 100);
			RegisterShowInventoryButton();
			RegisterSelfTeleportButton();
		}

		private static void RegisterInput(ConfigEntry<int> entry)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Expected O, but got Unknown
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			IntInputFieldOptions val = new IntInputFieldOptions
			{
				RequiresRestart = false
			};
			LethalConfigManager.AddConfigItem((BaseConfigItem)new IntInputFieldConfigItem(entry, val));
		}

		private static void RegisterSlider(ConfigEntry<int> entry, int min, int max)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			IntSliderOptions val = new IntSliderOptions();
			((BaseRangeOptions<int>)val).Min = min;
			((BaseRangeOptions<int>)val).Max = max;
			((BaseOptions)val).RequiresRestart = false;
			IntSliderOptions val2 = val;
			LethalConfigManager.AddConfigItem((BaseConfigItem)new IntSliderConfigItem(entry, val2));
		}

		private static void RegisterSlider(ConfigEntry<float> entry, float min, float max)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			FloatSliderOptions val = new FloatSliderOptions();
			((BaseRangeOptions<float>)val).Min = min;
			((BaseRangeOptions<float>)val).Max = max;
			((BaseOptions)val).RequiresRestart = false;
			FloatSliderOptions val2 = val;
			LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatSliderConfigItem(entry, val2));
		}

		private static void RegisterCheckbox(ConfigEntry<bool> entry)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(entry, false));
		}

		private static void RegisterDropdown(ConfigEntry<ItemTeleportBehavior> entry)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Expected O, but got Unknown
			EnumDropDownOptions val = new EnumDropDownOptions
			{
				RequiresRestart = false
			};
			LethalConfigManager.AddConfigItem((BaseConfigItem)(object)new EnumDropDownConfigItem<ItemTeleportBehavior>(entry, val));
		}

		private static void RegisterTextInput(ConfigEntry<string> entry)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			LethalConfigManager.AddConfigItem((BaseConfigItem)new TextInputFieldConfigItem(entry, false));
		}

		private static void RegisterTextArea(ConfigEntry<string> entry, int lines = 3)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: 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_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			TextInputFieldOptions val = new TextInputFieldOptions
			{
				CharacterLimit = 500,
				NumberOfLines = 50,
				RequiresRestart = false
			};
			LethalConfigManager.AddConfigItem((BaseConfigItem)new TextInputFieldConfigItem(entry, val));
		}

		private static void RegisterShowInventoryButton()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//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_0033: Expected O, but got Unknown
			object obj = <>c.<>9__9_0;
			if (obj == null)
			{
				GenericButtonHandler val = delegate
				{
					GrabbableObject[] array = GameNetworkManager.Instance?.localPlayerController?.ItemSlots;
					if (array != null && (Object)(object)HUDManager.Instance != (Object)null)
					{
						string text = string.Join(",", from x in array
							where (Object)(object)x != (Object)null
							select ((Object)x.itemProperties).name);
						HUDManager.Instance.DisplayTip("Current Inventory", text, false, false, "LC_Tip1");
					}
				};
				<>c.<>9__9_0 = val;
				obj = (object)val;
			}
			LethalConfigManager.AddConfigItem((BaseConfigItem)new GenericButtonConfigItem("Help", "What items am I holding?", "See currently held items to help figure out what to add to the keep/drop lists.", "Show inventory", (GenericButtonHandler)obj));
		}

		private static void RegisterSelfTeleportButton()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//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_0033: Expected O, but got Unknown
			object obj = <>c.<>9__10_0;
			if (obj == null)
			{
				GenericButtonHandler val = delegate
				{
					HUDManager instance = HUDManager.Instance;
					StartOfRound instance2 = StartOfRound.Instance;
					PlayerControllerB val2 = GameNetworkManager.Instance?.localPlayerController;
					if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance2 == (Object)null) && !((Object)(object)val2 == (Object)null))
					{
						NetworkManager singleton = NetworkManager.Singleton;
						if (singleton != null && singleton.ConnectedClientsList.Count > 1)
						{
							instance.DisplayTip("No cheating", "There's more than one player in the game.", true, false, "LC_Tip1");
						}
						else
						{
							ShipTeleporter val3 = ((IEnumerable<ShipTeleporter>)Object.FindObjectsOfType<ShipTeleporter>()).FirstOrDefault((Func<ShipTeleporter, bool>)((ShipTeleporter tp) => !tp.isInverseTeleporter));
							if ((Object)(object)val3 == (Object)null)
							{
								instance.DisplayTip("No cheating", "No teleporter on the ship.", true, false, "LC_Tip1");
							}
							else
							{
								FieldInfo shipTeleporterCooldownTimeField = ReflectionHelper.GetShipTeleporterCooldownTimeField();
								if (shipTeleporterCooldownTimeField != null && shipTeleporterCooldownTimeField.GetValue(val3) is float num && num > 0f)
								{
									instance.DisplayTip("No cheating", "The teleporter is on cooldown.", true, false, "LC_Tip1");
								}
								else
								{
									val3.PressTeleportButtonOnLocalClient();
								}
							}
						}
					}
				};
				<>c.<>9__10_0 = val;
				obj = (object)val;
			}
			LethalConfigManager.AddConfigItem((BaseConfigItem)new GenericButtonConfigItem("Help", "Activate Teleporter", "Pushes the teleport button. Only works if the Teleporter is unlocked and there are no other players connected to the game.", "Beam me up, Scotty", (GenericButtonHandler)obj));
		}
	}
}
namespace BetterBetterTeleporter.Adapters
{
	public interface IItemInfo
	{
		string Name { get; }

		string TypeName { get; }

		string DisplayName { get; }

		bool? IsScrap { get; }

		int? Value { get; }

		bool? IsMetal { get; }

		bool? IsWeapon { get; }

		bool? IsPocketed { get; }

		bool? HasBattery { get; }

		float? BatteryCharge { get; }

		bool? IsTwoHanded { get; }

		float? Weight { get; }
	}
	public sealed class ItemInfo : IItemInfo
	{
		[CompilerGenerated]
		private GrabbableObject <source>P;

		public string Name => TryGet(() => ((Object)<source>P.itemProperties).name, "itemProperties.name");

		public string TypeName => ((object)<source>P).GetType().Name;

		public string DisplayName => TryGet(() => <source>P.itemProperties.itemName, "itemProperties.itemName");

		public bool? IsScrap => TryGet(() => <source>P.itemProperties.isScrap, "itemProperties.isScrap");

		public int? Value => TryGet(() => <source>P.scrapValue, "scrapValue");

		public bool? IsMetal => TryGet(() => <source>P.itemProperties.isConductiveMetal, "itemProperties.isConductiveMetal");

		public bool? IsWeapon => TryGet(() => <source>P.itemProperties.isDefensiveWeapon, "itemProperties.isDefensiveWeapon");

		public bool? IsPocketed => TryGet(() => <source>P.isPocketed, "isPocketed");

		public bool? HasBattery => TryGet(() => <source>P.itemProperties.requiresBattery, "itemProperties.requiresBattery");

		public float? BatteryCharge => TryGet(() => <source>P.insertedBattery?.charge ?? 0f, "insertedBattery.charge");

		public bool? IsTwoHanded => TryGet(() => <source>P.itemProperties.twoHanded, "itemProperties.twoHanded");

		public float? Weight => TryGet(() => <source>P.itemProperties.weight, "itemProperties.weight");

		public ItemInfo(GrabbableObject source)
		{
			<source>P = source;
			base..ctor();
		}

		private static T TryGet<T>(Func<T> getter, string propertyName)
		{
			try
			{
				return getter();
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogError((object)("Failed to read 'GrabbableObject." + propertyName + "'. Game structure may have changed. Error: " + ex.Message));
				return default(T);
			}
		}
	}
	public interface IPlayerInfo
	{
		IReadOnlyList<IItemInfo> Slots { get; }

		int CurrentItemSlotIndex { get; }
	}
	public sealed class PlayerInfo : IPlayerInfo
	{
		[CompilerGenerated]
		private PlayerControllerB <player>P;

		private readonly IReadOnlyList<IItemInfo> _slots;

		public IReadOnlyList<IItemInfo> Slots => _slots;

		public int CurrentItemSlotIndex => TryGet(() => <player>P.currentItemSlot, "currentItemSlot");

		public PlayerInfo(PlayerControllerB player)
		{
			<player>P = player;
			List<IItemInfo> list = new List<IItemInfo>();
			list.AddRange(TryGet(() => <player>P.ItemSlots.Select((GrabbableObject item) => (!((Object)(object)item == (Object)null)) ? new ItemInfo(item) : null), "ItemSlots") ?? Array.Empty<ItemInfo>());
			_slots = new <>z__ReadOnlyList<IItemInfo>(list);
			base..ctor();
		}

		private static T TryGet<T>(Func<T> getter, string propertyName)
		{
			try
			{
				return getter();
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogError((object)("Failed to read 'PlayerControllerB." + propertyName + "'. Game structure may have changed. Error: " + ex.Message));
				return default(T);
			}
		}
	}
}
[CompilerGenerated]
internal sealed class <>z__ReadOnlyList<T> : IEnumerable, ICollection, IList, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T>
{
	int ICollection.Count => _items.Count;

	bool ICollection.IsSynchronized => false;

	object ICollection.SyncRoot => this;

	object IList.this[int index]
	{
		get
		{
			return _items[index];
		}
		set
		{
			throw new NotSupportedException();
		}
	}

	bool IList.IsFixedSize => true;

	bool IList.IsReadOnly => true;

	int IReadOnlyCollection<T>.Count => _items.Count;

	T IReadOnlyList<T>.this[int index] => _items[index];

	int ICollection<T>.Count => _items.Count;

	bool ICollection<T>.IsReadOnly => true;

	T IList<T>.this[int index]
	{
		get
		{
			return _items[index];
		}
		set
		{
			throw new NotSupportedException();
		}
	}

	public <>z__ReadOnlyList(List<T> items)
	{
		_items = items;
	}

	IEnumerator IEnumerable.GetEnumerator()
	{
		return ((IEnumerable)_items).GetEnumerator();
	}

	void ICollection.CopyTo(Array array, int index)
	{
		((ICollection)_items).CopyTo(array, index);
	}

	int IList.Add(object value)
	{
		throw new NotSupportedException();
	}

	void IList.Clear()
	{
		throw new NotSupportedException();
	}

	bool IList.Contains(object value)
	{
		return ((IList)_items).Contains(value);
	}

	int IList.IndexOf(object value)
	{
		return ((IList)_items).IndexOf(value);
	}

	void IList.Insert(int index, object value)
	{
		throw new NotSupportedException();
	}

	void IList.Remove(object value)
	{
		throw new NotSupportedException();
	}

	void IList.RemoveAt(int index)
	{
		throw new NotSupportedException();
	}

	IEnumerator<T> IEnumerable<T>.GetEnumerator()
	{
		return ((IEnumerable<T>)_items).GetEnumerator();
	}

	void ICollection<T>.Add(T item)
	{
		throw new NotSupportedException();
	}

	void ICollection<T>.Clear()
	{
		throw new NotSupportedException();
	}

	bool ICollection<T>.Contains(T item)
	{
		return _items.Contains(item);
	}

	void ICollection<T>.CopyTo(T[] array, int arrayIndex)
	{
		_items.CopyTo(array, arrayIndex);
	}

	bool ICollection<T>.Remove(T item)
	{
		throw new NotSupportedException();
	}

	int IList<T>.IndexOf(T item)
	{
		return _items.IndexOf(item);
	}

	void IList<T>.Insert(int index, T item)
	{
		throw new NotSupportedException();
	}

	void IList<T>.RemoveAt(int index)
	{
		throw new NotSupportedException();
	}
}
[CompilerGenerated]
internal sealed class <>z__ReadOnlySingleElementList<T> : IEnumerable, ICollection, IList, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T>
{
	private sealed class Enumerator : IDisposable, IEnumerator, IEnumerator<T>
	{
		object IEnumerator.Current => _item;

		T IEnumerator<T>.Current => _item;

		public Enumerator(T item)
		{
			_item = item;
		}

		bool IEnumerator.MoveNext()
		{
			if (!_moveNextCalled)
			{
				return _moveNextCalled = true;
			}
			return false;
		}

		void IEnumerator.Reset()
		{
			_moveNextCalled = false;
		}

		void IDisposable.Dispose()
		{
		}
	}

	int ICollection.Count => 1;

	bool ICollection.IsSynchronized => false;

	object ICollection.SyncRoot => this;

	object IList.this[int index]
	{
		get
		{
			if (index != 0)
			{
				throw new IndexOutOfRangeException();
			}
			return _item;
		}
		set
		{
			throw new NotSupportedException();
		}
	}

	bool IList.IsFixedSize => true;

	bool IList.IsReadOnly => true;

	int IReadOnlyCollection<T>.Count => 1;

	T IReadOnlyList<T>.this[int index]
	{
		get
		{
			if (index != 0)
			{
				throw new IndexOutOfRangeException();
			}
			return _item;
		}
	}

	int ICollection<T>.Count => 1;

	bool ICollection<T>.IsReadOnly => true;

	T IList<T>.this[int index]
	{
		get
		{
			if (index != 0)
			{
				throw new IndexOutOfRangeException();
			}
			return _item;
		}
		set
		{
			throw new NotSupportedException();
		}
	}

	public <>z__ReadOnlySingleElementList(T item)
	{
		_item = item;
	}

	IEnumerator IEnumerable.GetEnumerator()
	{
		return new Enumerator(_item);
	}

	void ICollection.CopyTo(Array array, int index)
	{
		array.SetValue(_item, index);
	}

	int IList.Add(object value)
	{
		throw new NotSupportedException();
	}

	void IList.Clear()
	{
		throw new NotSupportedException();
	}

	bool IList.Contains(object value)
	{
		return EqualityComparer<T>.Default.Equals(_item, (T)value);
	}

	int IList.IndexOf(object value)
	{
		if (!EqualityComparer<T>.Default.Equals(_item, (T)value))
		{
			return -1;
		}
		return 0;
	}

	void IList.Insert(int index, object value)
	{
		throw new NotSupportedException();
	}

	void IList.Remove(object value)
	{
		throw new NotSupportedException();
	}

	void IList.RemoveAt(int index)
	{
		throw new NotSupportedException();
	}

	IEnumerator<T> IEnumerable<T>.GetEnumerator()
	{
		return new Enumerator(_item);
	}

	void ICollection<T>.Add(T item)
	{
		throw new NotSupportedException();
	}

	void ICollection<T>.Clear()
	{
		throw new NotSupportedException();
	}

	bool ICollection<T>.Contains(T item)
	{
		return EqualityComparer<T>.Default.Equals(_item, item);
	}

	void ICollection<T>.CopyTo(T[] array, int arrayIndex)
	{
		array[arrayIndex] = _item;
	}

	bool ICollection<T>.Remove(T item)
	{
		throw new NotSupportedException();
	}

	int IList<T>.IndexOf(T item)
	{
		if (!EqualityComparer<T>.Default.Equals(_item, item))
		{
			return -1;
		}
		return 0;
	}

	void IList<T>.Insert(int index, T item)
	{
		throw new NotSupportedException();
	}

	void IList<T>.RemoveAt(int index)
	{
		throw new NotSupportedException();
	}
}