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();
}
}