Decompiled source of InstancedLoot continuation v2.0.0

InstancedLoot\InstancedLoot.dll

Decompiled 3 weeks ago
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using IL.RoR2;
using IL.RoR2.Hologram;
using InstancedLoot.Components;
using InstancedLoot.Configuration;
using InstancedLoot.Enums;
using InstancedLoot.Hooks;
using InstancedLoot.Networking;
using InstancedLoot.ObjectInstancing;
using Microsoft.CodeAnalysis;
using Mono.Cecil;
using Mono.Cecil.Cil;
using MonoMod.Cil;
using On.RoR2;
using On.RoR2.Hologram;
using R2API.Networking;
using R2API.Networking.Interfaces;
using R2API.Utils;
using RoR2;
using RoR2.Hologram;
using RoR2.UI;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;

[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("KubeRoot")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("2.0.0.0")]
[assembly: AssemblyInformationalVersion("2.0.0+c17cf1db15c8bfa52dd267983168225cc3dd2165")]
[assembly: AssemblyProduct("InstancedLoot")]
[assembly: AssemblyTitle("InstancedLoot")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace InstancedLoot
{
	[BepInPlugin("com.kuberoot.instancedloot", "InstancedLoot", "2.0.0")]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class InstancedLoot : BaseUnityPlugin
	{
		private float nextResend;

		public static InstancedLoot Instance { get; private set; }

		internal ManualLogSource _logger => ((BaseUnityPlugin)this).Logger;

		public Config ModConfig { get; private set; }

		public HookManager HookManager { get; private set; }

		public ObjectInstanceService Objects { get; private set; }

		public void Awake()
		{
			ModConfig = new Config(this, ((BaseUnityPlugin)this).Logger);
			ModConfig.Init();
			Objects = new ObjectInstanceService(this);
			HookManager = new HookManager(this);
			NetworkingAPI.RegisterMessageType<OwnerSnapshot>();
		}

		public void OnEnable()
		{
			Instance = this;
			HookManager.RegisterHooks();
			SceneManager.activeSceneChanged += SceneChanged;
			PlayerCharacterMasterController.onPlayerAdded += PlayerAdded;
		}

		public void OnDisable()
		{
			SceneManager.activeSceneChanged -= SceneChanged;
			PlayerCharacterMasterController.onPlayerAdded -= PlayerAdded;
			HookManager.UnregisterHooks();
			Clear();
			InstancedLootBehaviour[] array = Object.FindObjectsOfType<InstancedLootBehaviour>();
			for (int i = 0; i < array.Length; i++)
			{
				Object.Destroy((Object)(object)array[i]);
			}
			Instance = null;
		}

		private void Clear()
		{
			Objects.Clear();
			OwnerSnapshot.Clear();
		}

		private void SceneChanged(Scene previous, Scene current)
		{
			Objects.Clear();
			OwnerSnapshot.SceneChanged();
		}

		private void PlayerAdded(PlayerCharacterMasterController player)
		{
			Resend();
		}

		private void Resend()
		{
			if (!NetworkServer.active || !Object.op_Implicit((Object)(object)Run.instance))
			{
				return;
			}
			foreach (InstanceHandler instance in InstanceHandler.Instances)
			{
				if (Object.op_Implicit((Object)(object)instance) && Object.op_Implicit((Object)(object)instance.Owner))
				{
					new OwnerSnapshot(instance).SendToAll();
				}
			}
		}

		public void Update()
		{
			Objects.Pump();
			OwnerSnapshot.Pump();
			if (Time.unscaledTime >= nextResend)
			{
				nextResend = Time.unscaledTime + 2f;
				Resend();
			}
		}
	}
	public static class Utils
	{
		public static bool IsObjectInteractibleForPlayer(GameObject target, PlayerCharacterMasterController player)
		{
			if (!Object.op_Implicit((Object)(object)target) || !Object.op_Implicit((Object)(object)player))
			{
				return true;
			}
			if (PendingOwnership.IsPending(target))
			{
				return false;
			}
			InstanceHandler component = target.GetComponent<InstanceHandler>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				return true;
			}
			return component.LinkedHandlers.Where((InstanceHandler handler) => handler.IsInstancedFor(player)).Any(delegate(InstanceHandler handler)
			{
				//IL_003f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0045: Invalid comparison between Unknown and I4
				PurchaseInteraction component2 = ((Component)handler).GetComponent<PurchaseInteraction>();
				Interactor val = (Object.op_Implicit((Object)(object)player.body) ? ((Component)player.body).GetComponent<Interactor>() : null);
				return !Object.op_Implicit((Object)(object)component2) || !Object.op_Implicit((Object)(object)val) || (int)component2.GetInteractability(val) > 0;
			});
		}

		public static bool IsObjectInstanceInteractibleForPlayer(GameObject target, PlayerCharacterMasterController player)
		{
			if (PendingOwnership.IsPending(target))
			{
				return false;
			}
			InstanceHandler instanceHandler = (Object.op_Implicit((Object)(object)target) ? target.GetComponent<InstanceHandler>() : null);
			if (Object.op_Implicit((Object)(object)instanceHandler))
			{
				return instanceHandler.IsInstancedFor(player);
			}
			return true;
		}

		private static PlayerCharacterMasterController CameraPlayer(CameraRigController camera)
		{
			CharacterBody val = (Object.op_Implicit((Object)(object)camera) ? camera.targetBody : null);
			if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val.master))
			{
				return null;
			}
			return val.master.playerCharacterMasterController;
		}

		public static bool IsObjectInteractibleForCameraRigController(GameObject target, CameraRigController camera)
		{
			return IsObjectInteractibleForPlayer(target, CameraPlayer(camera));
		}

		public static bool IsObjectInstanceInteractibleForCameraRigController(GameObject target, CameraRigController camera)
		{
			if (Object.op_Implicit((Object)(object)CameraPlayer(camera)))
			{
				return IsObjectInstanceInteractibleForPlayer(target, CameraPlayer(camera));
			}
			return true;
		}
	}
}
namespace InstancedLoot.ObjectInstancing
{
	public static class NativeAdapters
	{
		public sealed class Chest : ObjectAdapter
		{
			public override Action<GameObject> CaptureState(GameObject source)
			{
				//IL_0020: Unknown result type (might be due to invalid IL or missing references)
				//IL_002a: Expected O, but got Unknown
				//IL_002c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0031: Unknown result type (might be due to invalid IL or missing references)
				Action<GameObject> purchase = base.CaptureState(source);
				ChestBehavior component = source.GetComponent<ChestBehavior>();
				Xoroshiro128Plus rng = new Xoroshiro128Plus(component.rng);
				UniquePickup pickup = component.currentPickup;
				int count = component.dropCount;
				return delegate(GameObject target)
				{
					//IL_0019: Unknown result type (might be due to invalid IL or missing references)
					//IL_0023: Expected O, but got Unknown
					//IL_0025: Unknown result type (might be due to invalid IL or missing references)
					purchase(target);
					ChestBehavior component2 = target.GetComponent<ChestBehavior>();
					component2.rng = new Xoroshiro128Plus(rng);
					component2.currentPickup = pickup;
					component2.dropCount = count;
				};
			}
		}

		public sealed class OptionChest : ObjectAdapter
		{
			public override Action<GameObject> CaptureState(GameObject source)
			{
				//IL_0020: Unknown result type (might be due to invalid IL or missing references)
				//IL_002a: Expected O, but got Unknown
				Action<GameObject> purchase = base.CaptureState(source);
				OptionChestBehavior component = source.GetComponent<OptionChestBehavior>();
				Xoroshiro128Plus rng = new Xoroshiro128Plus(component.rng);
				UniquePickup[] pickups = component.generatedPickups.ToArray();
				return delegate(GameObject target)
				{
					//IL_0019: Unknown result type (might be due to invalid IL or missing references)
					//IL_0023: Expected O, but got Unknown
					purchase(target);
					OptionChestBehavior component2 = target.GetComponent<OptionChestBehavior>();
					component2.rng = new Xoroshiro128Plus(rng);
					component2.generatedPickups = pickups.ToList();
				};
			}
		}

		public sealed class Roulette : ObjectAdapter
		{
			public override Action<GameObject> CaptureState(GameObject source)
			{
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0028: Expected O, but got Unknown
				Action<GameObject> purchase = base.CaptureState(source);
				Xoroshiro128Plus rng = new Xoroshiro128Plus(source.GetComponent<RouletteChestController>().rng);
				return delegate(GameObject target)
				{
					//IL_0018: Unknown result type (might be due to invalid IL or missing references)
					//IL_0022: Expected O, but got Unknown
					purchase(target);
					target.GetComponent<RouletteChestController>().rng = new Xoroshiro128Plus(rng);
				};
			}
		}

		public sealed class MultiShop : ObjectAdapter
		{
			public override bool IsReady(GameObject source)
			{
				return source.GetComponent<MultiShopController>().terminalGameObjects.All((GameObject terminal) => Object.op_Implicit((Object)(object)terminal) && terminal.GetComponent<ShopTerminalBehavior>().hasStarted);
			}

			public override IEnumerable<GameObject> OwnedObjects(GameObject root)
			{
				yield return root;
				GameObject[] terminalGameObjects = root.GetComponent<MultiShopController>().terminalGameObjects;
				for (int i = 0; i < terminalGameObjects.Length; i++)
				{
					yield return terminalGameObjects[i];
				}
			}

			public override Action<GameObject> CaptureState(GameObject source)
			{
				//IL_0033: Unknown result type (might be due to invalid IL or missing references)
				//IL_003d: Expected O, but got Unknown
				MultiShopController component = source.GetComponent<MultiShopController>();
				int cost = component.Networkcost;
				bool available = component.Networkavailable;
				Xoroshiro128Plus rng = new Xoroshiro128Plus(component.rng);
				Action<GameObject>[] terminals = ((IEnumerable<GameObject>)component.terminalGameObjects).Select((Func<GameObject, Action<GameObject>>)delegate(GameObject terminal)
				{
					//IL_0020: Unknown result type (might be due to invalid IL or missing references)
					//IL_0025: Unknown result type (might be due to invalid IL or missing references)
					//IL_0045: Unknown result type (might be due to invalid IL or missing references)
					Action<GameObject> purchase = base.CaptureState(terminal);
					ShopTerminalBehavior component2 = terminal.GetComponent<ShopTerminalBehavior>();
					UniquePickup pickup = component2.Networkpickup;
					bool hidden = component2.Networkhidden;
					Xoroshiro128Plus terminalRng = ((component2.rng == null) ? ((Xoroshiro128Plus)null) : new Xoroshiro128Plus(component2.rng));
					return delegate(GameObject target)
					{
						//IL_0035: Unknown result type (might be due to invalid IL or missing references)
						//IL_0029: Unknown result type (might be due to invalid IL or missing references)
						//IL_0033: Expected O, but got Unknown
						purchase(target);
						ShopTerminalBehavior component3 = target.GetComponent<ShopTerminalBehavior>();
						component3.hasStarted = true;
						if (terminalRng != null)
						{
							component3.rng = new Xoroshiro128Plus(terminalRng);
						}
						component3.Networkpickup = pickup;
						component3.Networkhidden = hidden;
						component3.UpdatePickupDisplayAndAnimations();
					};
				}).ToArray();
				return delegate(GameObject target)
				{
					//IL_0043: Unknown result type (might be due to invalid IL or missing references)
					//IL_004d: Expected O, but got Unknown
					MultiShopController component2 = target.GetComponent<MultiShopController>();
					if (component2.terminalGameObjects.Length != terminals.Length)
					{
						throw new InvalidOperationException("MultiShop terminal count differs from the initialized source.");
					}
					component2.Networkcost = cost;
					component2.Networkavailable = available;
					component2.rng = new Xoroshiro128Plus(rng);
					for (int i = 0; i < terminals.Length; i++)
					{
						terminals[i](component2.terminalGameObjects[i]);
					}
				};
			}
		}

		public sealed class Shrine : ObjectAdapter
		{
			public override Action<GameObject> CaptureState(GameObject source)
			{
				//IL_0047: Unknown result type (might be due to invalid IL or missing references)
				//IL_0051: Expected O, but got Unknown
				//IL_003a: Unknown result type (might be due to invalid IL or missing references)
				Action<GameObject> purchase = base.CaptureState(source);
				ShrineChanceBehavior component = source.GetComponent<ShrineChanceBehavior>();
				ShrineRestackBehavior component2 = source.GetComponent<ShrineRestackBehavior>();
				Xoroshiro128Plus rng = ((!Object.op_Implicit((Object)(object)component)) ? ((!Object.op_Implicit((Object)(object)component2)) ? ((Xoroshiro128Plus)null) : new Xoroshiro128Plus(component2.rng)) : new Xoroshiro128Plus(component.rng));
				return delegate(GameObject target)
				{
					//IL_003e: Unknown result type (might be due to invalid IL or missing references)
					//IL_0048: Expected O, but got Unknown
					//IL_005e: Unknown result type (might be due to invalid IL or missing references)
					//IL_0068: Expected O, but got Unknown
					purchase(target);
					PurchaseInteraction component3 = target.GetComponent<PurchaseInteraction>();
					ShrineChanceBehavior component4 = target.GetComponent<ShrineChanceBehavior>();
					ShrineRestackBehavior component5 = target.GetComponent<ShrineRestackBehavior>();
					ShrineBloodBehavior component6 = target.GetComponent<ShrineBloodBehavior>();
					if (Object.op_Implicit((Object)(object)component4))
					{
						component4.purchaseInteraction = component3;
						component4.rng = new Xoroshiro128Plus(rng);
					}
					if (Object.op_Implicit((Object)(object)component5))
					{
						component5.purchaseInteraction = component3;
						component5.rng = new Xoroshiro128Plus(rng);
					}
					if (Object.op_Implicit((Object)(object)component6))
					{
						component6.purchaseInteraction = component3;
					}
				};
			}
		}

		public sealed class Repair : ObjectAdapter
		{
			public override Action<GameObject> CaptureState(GameObject source)
			{
				Action<GameObject> purchase = base.CaptureState(source);
				SummonMasterBehavior component = source.GetComponent<SummonMasterBehavior>();
				GameObject master = component.masterPrefab;
				int upgrades = component.droneUpgradeCount;
				bool destroy = component.destroyAfterSummoning;
				return delegate(GameObject target)
				{
					purchase(target);
					SummonMasterBehavior component2 = target.GetComponent<SummonMasterBehavior>();
					component2.masterPrefab = master;
					component2.NetworkdroneUpgradeCount = upgrades;
					component2.destroyAfterSummoning = destroy;
				};
			}
		}

		public static readonly string[] ChestTypes = new string[15]
		{
			"Chest1", "Chest2", "GoldChest", "Chest1StealthedVariant", "CategoryChestDamage", "CategoryChestHealing", "CategoryChestUtility", "CategoryChest2Damage", "CategoryChest2Healing", "CategoryChest2Utility",
			"EquipmentBarrel", "LunarChest", "VoidChest", "Lockbox", "ScavBackpack"
		};

		public static readonly string[] ObjectTypes = ChestTypes.Concat(new string[11]
		{
			"VoidTriple", "LockboxVoid", "CasinoChest", "TripleShop", "TripleShopEquipment", "FreeChestMultiShop", "ShrineChance", "ShrineBlood", "ShrineRestack", "Drone",
			"Turret"
		}).ToArray();

		public static string Identify(GameObject target, IEnumerable<string> types)
		{
			return types.FirstOrDefault((string type) => string.Equals(((Object)target).name.Replace("(Clone)", "").Trim(), type, StringComparison.Ordinal));
		}
	}
	public abstract class ObjectAdapter
	{
		public virtual bool IsReady(GameObject source)
		{
			return true;
		}

		public virtual IEnumerable<GameObject> OwnedObjects(GameObject root)
		{
			yield return root;
		}

		public virtual Action<GameObject> CaptureState(GameObject source)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			PurchaseInteraction component = source.GetComponent<PurchaseInteraction>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				return delegate
				{
				};
			}
			CostTypeIndex costType = component.costType;
			int cost = component.cost;
			bool available = component.available;
			Xoroshiro128Plus rng = ((component.rng == null) ? ((Xoroshiro128Plus)null) : new Xoroshiro128Plus(component.rng));
			return delegate(GameObject target)
			{
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				//IL_004d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0057: Expected O, but got Unknown
				PurchaseInteraction component2 = target.GetComponent<PurchaseInteraction>();
				if (!Object.op_Implicit((Object)(object)component2))
				{
					throw new InvalidOperationException("Copy is missing PurchaseInteraction.");
				}
				component2.NetworkcostType = costType;
				component2.Networkcost = cost;
				component2.Networkavailable = available;
				if (rng != null)
				{
					component2.rng = new Xoroshiro128Plus(rng);
				}
			};
		}
	}
	public sealed class ObjectInstanceService
	{
		private sealed class PendingCopy
		{
			public Action<GameObject> ApplyState;

			public ObjectAdapter Adapter;

			public PlayerCharacterMasterController Owner;

			public int Group;

			public GameObject[] OwnedObjects;
		}

		private readonly InstancedLoot plugin;

		private readonly Dictionary<GameObject, PendingCopy> pending = new Dictionary<GameObject, PendingCopy>();

		private readonly HashSet<GameObject> initialized = new HashSet<GameObject>();

		private readonly List<(ObjectAdapter adapter, GameObject source, string type)> sources = new List<(ObjectAdapter, GameObject, string)>();

		private readonly HashSet<GameObject> pendingChildren = new HashSet<GameObject>();

		private Run run;

		private int nextGroup;

		public ObjectInstanceService(InstancedLoot plugin)
		{
			this.plugin = plugin;
		}

		public bool InitializeCopy(GameObject target)
		{
			CheckRun();
			if (!NetworkServer.active || !pending.TryGetValue(target, out var value))
			{
				return false;
			}
			try
			{
				if (!Object.op_Implicit((Object)(object)value.Owner))
				{
					throw new InvalidOperationException("Copy owner has left.");
				}
				value.ApplyState(target);
				AssignTree(value.Adapter, target, value.Owner, value.Group);
			}
			catch (Exception arg)
			{
				plugin._logger.LogError((object)$"Copy initialization failed for {((Object)target).name}: {arg}");
				DestroyCopy(value);
			}
			finally
			{
				pending.Remove(target);
				GameObject[] ownedObjects = value.OwnedObjects;
				foreach (GameObject item in ownedObjects)
				{
					pendingChildren.Remove(item);
				}
			}
			return true;
		}

		public bool IsPendingChild(GameObject target)
		{
			return pendingChildren.Contains(target);
		}

		private void CheckRun()
		{
			if (!((Object)(object)run == (Object)(object)Run.instance))
			{
				Clear();
				run = Run.instance;
				OwnerSnapshot.RunChanged();
			}
		}

		public void InitializeSource(ObjectAdapter adapter, GameObject source, string objectType)
		{
			CheckRun();
			if (!NetworkServer.active || !Object.op_Implicit((Object)(object)source) || !initialized.Add(source) || !plugin.ModConfig.IsEnabled(objectType))
			{
				return;
			}
			foreach (GameObject item in adapter.OwnedObjects(source))
			{
				PendingOwnership.Mark(item);
			}
			sources.Add((adapter, source, objectType));
		}

		public void Pump()
		{
			CheckRun();
			if (!NetworkServer.active)
			{
				return;
			}
			(ObjectAdapter, GameObject, string)[] array = sources.ToArray();
			for (int i = 0; i < array.Length; i++)
			{
				(ObjectAdapter, GameObject, string) item = array[i];
				if (!Object.op_Implicit((Object)(object)item.Item2))
				{
					sources.Remove(item);
				}
				else if (item.Item1.IsReady(item.Item2))
				{
					sources.Remove(item);
					try
					{
						CreateCopies(item.Item1, item.Item2);
					}
					catch (Exception arg)
					{
						ResolveTree(item.Item1, item.Item2);
						plugin._logger.LogError((object)$"Object instancing failed for {((Object)item.Item2).name}: {arg}");
					}
				}
			}
		}

		private void CreateCopies(ObjectAdapter adapter, GameObject source)
		{
			PlayerCharacterMasterController[] array = PlayerCharacterMasterController.instances.Where((PlayerCharacterMasterController player) => Object.op_Implicit((Object)(object)player)).ToArray();
			if (array.Length == 0)
			{
				ResolveTree(adapter, source);
				return;
			}
			int num = ++nextGroup;
			Action<GameObject> applyState = adapter.CaptureState(source);
			List<GameObject> list = new List<GameObject>();
			try
			{
				for (int num2 = 1; num2 < array.Length; num2++)
				{
					GameObject val = SpawnCopy(source);
					if (!Object.op_Implicit((Object)(object)val))
					{
						throw new InvalidOperationException("SpawnCard did not create all player copies; keeping the source vanilla.");
					}
					list.Add(val);
					GameObject[] array2 = adapter.OwnedObjects(val).ToArray();
					pending.Add(val, new PendingCopy
					{
						ApplyState = applyState,
						Adapter = adapter,
						Owner = array[num2],
						Group = num,
						OwnedObjects = array2
					});
					GameObject[] array3 = array2;
					foreach (GameObject val2 in array3)
					{
						PendingOwnership.Mark(val2);
						if ((Object)(object)val2 != (Object)(object)val)
						{
							pendingChildren.Add(val2);
						}
					}
				}
				AssignTree(adapter, source, array[0], num);
			}
			catch
			{
				foreach (GameObject item2 in list)
				{
					if (pending.TryGetValue(item2, out var value))
					{
						DestroyCopy(value);
						GameObject[] array3 = value.OwnedObjects;
						foreach (GameObject item in array3)
						{
							pendingChildren.Remove(item);
						}
						pending.Remove(item2);
						continue;
					}
					foreach (GameObject item3 in adapter.OwnedObjects(item2).Reverse())
					{
						if (Object.op_Implicit((Object)(object)item3))
						{
							NetworkServer.Destroy(item3);
						}
					}
				}
				throw;
			}
		}

		private void AssignTree(ObjectAdapter adapter, GameObject root, PlayerCharacterMasterController owner, int group)
		{
			int num = 0;
			List<InstanceHandler> list = new List<InstanceHandler>();
			try
			{
				foreach (GameObject item in adapter.OwnedObjects(root))
				{
					if (Object.op_Implicit((Object)(object)item))
					{
						InstanceHandler instanceHandler = item.GetComponent<InstanceHandler>() ?? item.AddComponent<InstanceHandler>();
						list.Add(instanceHandler);
						instanceHandler.Assign(owner, checked(group * 16 + num++));
					}
				}
			}
			catch
			{
				foreach (InstanceHandler item2 in list)
				{
					if (Object.op_Implicit((Object)(object)item2))
					{
						Object.Destroy((Object)(object)item2);
					}
				}
				throw;
			}
			foreach (InstanceHandler item3 in list)
			{
				try
				{
					new OwnerSnapshot(item3).SendToAll();
				}
				catch (Exception arg)
				{
					plugin._logger.LogError((object)$"Owner snapshot send failed for {((Object)item3).name}: {arg}");
				}
			}
		}

		public GameObject SpawnCopy(GameObject source)
		{
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Expected O, but got Unknown
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Expected O, but got Unknown
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Expected O, but got Unknown
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active || !Object.op_Implicit((Object)(object)source))
			{
				return null;
			}
			SpawnCard val = source.GetComponent<SpawnCardTracker>()?.SpawnCard;
			if (!Object.op_Implicit((Object)(object)val))
			{
				val = (SpawnCard)(object)((IEnumerable<InteractableSpawnCard>)Resources.FindObjectsOfTypeAll<InteractableSpawnCard>()).FirstOrDefault((Func<InteractableSpawnCard, bool>)((InteractableSpawnCard candidate) => Object.op_Implicit((Object)(object)((SpawnCard)candidate).prefab) && ((Object)((SpawnCard)candidate).prefab).name == ((Object)source).name.Replace("(Clone)", "").Trim()));
			}
			if (!Object.op_Implicit((Object)(object)val))
			{
				plugin._logger.LogError((object)("No SpawnCard for " + ((Object)source).name + "; additional player copies were not created."));
				return null;
			}
			DirectorPlacementRule val2 = new DirectorPlacementRule
			{
				placementMode = (PlacementMode)6,
				position = source.transform.position,
				rotation = source.transform.rotation
			};
			SpawnResult val3 = val.DoSpawn(source.transform.position, source.transform.rotation, new DirectorSpawnRequest(val, val2, new Xoroshiro128Plus(0uL)));
			if (Object.op_Implicit((Object)(object)val3.spawnedInstance))
			{
				val3.spawnedInstance.transform.position = source.transform.position;
				val3.spawnedInstance.transform.rotation = source.transform.rotation;
				val3.spawnedInstance.transform.localScale = source.transform.localScale;
			}
			return val3.spawnedInstance;
		}

		public void Clear()
		{
			if (NetworkServer.active)
			{
				foreach (PendingCopy value in pending.Values)
				{
					DestroyCopy(value);
				}
			}
			foreach (var source in sources)
			{
				if (Object.op_Implicit((Object)(object)source.source))
				{
					ResolveTree(source.adapter, source.source);
				}
			}
			pending.Clear();
			pendingChildren.Clear();
			sources.Clear();
			initialized.Clear();
		}

		private static void DestroyCopy(PendingCopy copy)
		{
			foreach (GameObject item in copy.OwnedObjects.AsEnumerable().Reverse())
			{
				if (Object.op_Implicit((Object)(object)item))
				{
					NetworkServer.Destroy(item);
				}
			}
		}

		private static void ResolveTree(ObjectAdapter adapter, GameObject source)
		{
			foreach (GameObject item in adapter.OwnedObjects(source))
			{
				if (Object.op_Implicit((Object)(object)item))
				{
					PendingOwnership.Resolve(item);
				}
			}
		}
	}
}
namespace InstancedLoot.Networking
{
	public sealed class OwnerSnapshot : INetMessage, ISerializableObject
	{
		public const int ProtocolVersion = 2;

		private int version = 2;

		private NetworkInstanceId runId;

		private NetworkInstanceId targetId;

		private NetworkInstanceId ownerId;

		private int stage;

		private int epoch;

		private int revision;

		private int group;

		private string scene;

		private float expires;

		private static int serverEpoch = 1;

		private static readonly Dictionary<(NetworkInstanceId run, int epoch, NetworkInstanceId target), OwnerSnapshot> pending = new Dictionary<(NetworkInstanceId, int, NetworkInstanceId), OwnerSnapshot>();

		private static readonly Dictionary<(NetworkInstanceId run, int epoch, NetworkInstanceId target), int> latest = new Dictionary<(NetworkInstanceId, int, NetworkInstanceId), int>();

		private static readonly Dictionary<NetworkInstanceId, int> newestEpoch = new Dictionary<NetworkInstanceId, int>();

		private static readonly Dictionary<NetworkInstanceId, int> appliedEpoch = new Dictionary<NetworkInstanceId, int>();

		private static readonly Dictionary<NetworkInstanceId, int> minimumEpoch = new Dictionary<NetworkInstanceId, int>();

		private (NetworkInstanceId, int, NetworkInstanceId) Key => (runId, epoch, targetId);

		public static int PendingCount => pending.Count;

		private bool CurrentSession
		{
			get
			{
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				//IL_0035: Unknown result type (might be due to invalid IL or missing references)
				//IL_003a: Unknown result type (might be due to invalid IL or missing references)
				if (Object.op_Implicit((Object)(object)Run.instance) && ((NetworkBehaviour)Run.instance).netId == runId && Run.instance.stageClearCount == stage)
				{
					Scene activeScene = SceneManager.GetActiveScene();
					return ((Scene)(ref activeScene)).name == scene;
				}
				return false;
			}
		}

		private bool Obsolete
		{
			get
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_0023: Unknown result type (might be due to invalid IL or missing references)
				if (!minimumEpoch.TryGetValue(runId, out var value) || epoch >= value)
				{
					if (newestEpoch.TryGetValue(runId, out var value2))
					{
						return epoch < value2;
					}
					return false;
				}
				return true;
			}
		}

		public OwnerSnapshot()
		{
		}

		public OwnerSnapshot(InstanceHandler handler)
		{
			//IL_0013: 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_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			runId = ((NetworkBehaviour)Run.instance).netId;
			stage = Run.instance.stageClearCount;
			Scene activeScene = SceneManager.GetActiveScene();
			scene = ((Scene)(ref activeScene)).name;
			epoch = serverEpoch;
			targetId = ((Component)handler).GetComponent<NetworkIdentity>().netId;
			ownerId = ((Component)handler.Owner).GetComponent<NetworkIdentity>().netId;
			revision = handler.Revision;
			group = handler.GroupId;
		}

		public void Serialize(NetworkWriter writer)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			writer.Write(version);
			writer.Write(runId);
			writer.Write(stage);
			writer.Write(scene);
			writer.Write(epoch);
			writer.Write(targetId);
			writer.Write(ownerId);
			writer.Write(revision);
			writer.Write(group);
		}

		public void Deserialize(NetworkReader reader)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			version = reader.ReadInt32();
			runId = reader.ReadNetworkId();
			stage = reader.ReadInt32();
			scene = reader.ReadString();
			epoch = reader.ReadInt32();
			targetId = reader.ReadNetworkId();
			ownerId = reader.ReadNetworkId();
			revision = reader.ReadInt32();
			group = reader.ReadInt32();
		}

		public void OnReceived()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active && version == 2 && !(runId == NetworkInstanceId.Invalid) && !(targetId == NetworkInstanceId.Invalid) && !(ownerId == NetworkInstanceId.Invalid) && epoch > 0 && revision > 0 && group > 0 && !Obsolete && (!latest.TryGetValue(Key, out var value) || revision >= value))
			{
				newestEpoch[runId] = epoch;
				latest[Key] = revision;
				expires = Time.realtimeSinceStartup + 30f;
				pending[Key] = this;
				Pump();
			}
		}

		private static void Release(OwnerSnapshot snapshot)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Util.FindNetworkObject(snapshot.targetId);
			if (Object.op_Implicit((Object)(object)val) && !Object.op_Implicit((Object)(object)val.GetComponent<InstanceHandler>()))
			{
				PendingOwnership.Resolve(val);
			}
			pending.Remove(snapshot.Key);
		}

		public static void Pump()
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			OwnerSnapshot[] array = pending.Values.ToArray();
			foreach (OwnerSnapshot ownerSnapshot in array)
			{
				if (ownerSnapshot.Obsolete || Time.realtimeSinceStartup > ownerSnapshot.expires)
				{
					Release(ownerSnapshot);
				}
				else if (ownerSnapshot.CurrentSession)
				{
					appliedEpoch[ownerSnapshot.runId] = ownerSnapshot.epoch;
					GameObject val = Util.FindNetworkObject(ownerSnapshot.targetId);
					GameObject obj = Util.FindNetworkObject(ownerSnapshot.ownerId);
					PlayerCharacterMasterController val2 = ((obj != null) ? obj.GetComponent<PlayerCharacterMasterController>() : null);
					if (Object.op_Implicit((Object)(object)val) && !Object.op_Implicit((Object)(object)val2))
					{
						PendingOwnership.Mark(val);
					}
					if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val2))
					{
						(val.GetComponent<InstanceHandler>() ?? val.AddComponent<InstanceHandler>()).Assign(val2, ownerSnapshot.group, ownerSnapshot.revision);
						pending.Remove(ownerSnapshot.Key);
					}
				}
			}
		}

		public void SendToAll()
		{
			if (NetworkServer.active && Object.op_Implicit((Object)(object)Run.instance))
			{
				NetMessageExtensions.Send((INetMessage)(object)this, (NetworkDestination)1);
			}
		}

		public static void SceneChanged()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkServer.active)
			{
				serverEpoch++;
				return;
			}
			if (Object.op_Implicit((Object)(object)Run.instance) && appliedEpoch.TryGetValue(((NetworkBehaviour)Run.instance).netId, out var value))
			{
				minimumEpoch[((NetworkBehaviour)Run.instance).netId] = value + 1;
			}
			Pump();
		}

		public static void RunChanged()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkServer.active)
			{
				serverEpoch++;
				return;
			}
			OwnerSnapshot[] array = pending.Values.ToArray();
			foreach (OwnerSnapshot ownerSnapshot in array)
			{
				if (Object.op_Implicit((Object)(object)Run.instance) && ownerSnapshot.runId != ((NetworkBehaviour)Run.instance).netId)
				{
					Release(ownerSnapshot);
				}
			}
			Pump();
		}

		public static void Clear()
		{
			OwnerSnapshot[] array = pending.Values.ToArray();
			for (int i = 0; i < array.Length; i++)
			{
				Release(array[i]);
			}
			latest.Clear();
			newestEpoch.Clear();
			appliedEpoch.Clear();
			minimumEpoch.Clear();
		}
	}
}
namespace InstancedLoot.Enums
{
	public enum InstanceMode
	{
		InstanceObject
	}
}
namespace InstancedLoot.Configuration
{
	public sealed class Config
	{
		private readonly InstancedLoot plugin;

		private readonly Dictionary<string, ConfigEntry<bool>> enabled = new Dictionary<string, ConfigEntry<bool>>();

		public ConfigEntry<InstanceMode> PreferredInstanceMode { get; private set; }

		public ConfigEntry<bool> ReduceInteractibleBudget { get; private set; }

		public ConfigEntry<bool> ReduceMoneyDrops { get; private set; }

		public Config(InstancedLoot plugin, ManualLogSource logger)
		{
			this.plugin = plugin;
		}

		public void Init()
		{
			PreferredInstanceMode = ((BaseUnityPlugin)plugin).Config.Bind<InstanceMode>("General", "PreferredInstanceMode", InstanceMode.InstanceObject, "InstanceObject is the only supported allocation strategy. Every player owns a native purchase object.");
			ReduceInteractibleBudget = ((BaseUnityPlugin)plugin).Config.Bind<bool>("General - Balance", "ReduceInteractibleBudget", true, "Use the single-player interactable budget. Does not change object prices or payment rules.");
			ReduceMoneyDrops = ((BaseUnityPlugin)plugin).Config.Bind<bool>("General - Balance", "ReduceMoneyDrops", false, "Divide native team money rewards by participating player count. Purchases still charge the native payer.");
			string[] objectTypes = NativeAdapters.ObjectTypes;
			foreach (string text in objectTypes)
			{
				string text2 = (text.StartsWith("Shrine") ? "Shrines" : ((text == "Drone" || text == "Turret") ? "Repairs" : "Objects"));
				enabled[text] = ((BaseUnityPlugin)plugin).Config.Bind<bool>(text2, text, true, "Create an independently usable purchase object per player. False keeps vanilla behavior. Applies to newly spawned objects.");
			}
		}

		public bool IsEnabled(string type)
		{
			if (enabled.TryGetValue(type, out var value))
			{
				return value.Value;
			}
			return false;
		}
	}
}
namespace InstancedLoot.Components
{
	public sealed class FadeBehavior : InstancedLootBehaviour
	{
		private static readonly int Fade;

		public float FadeLevel;

		public readonly HashSet<GameObject> ExtraGameObjects = new HashSet<GameObject>();

		public static readonly List<FadeBehavior> InstancesList;

		private readonly HashSet<Renderer> renderers = new HashSet<Renderer>();

		private readonly HashSet<Behaviour> effects = new HashSet<Behaviour>();

		private MaterialPropertyBlock properties;

		private bool dirty = true;

		private readonly Dictionary<Renderer, bool> originalForce = new Dictionary<Renderer, bool>();

		private readonly Dictionary<Behaviour, bool> originalEffects = new Dictionary<Behaviour, bool>();

		private readonly Dictionary<Renderer, MaterialPropertyBlock> originalProperties = new Dictionary<Renderer, MaterialPropertyBlock>();

		static FadeBehavior()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			Fade = Shader.PropertyToID("_Fade");
			InstancesList = new List<FadeBehavior>();
			SceneCamera.onSceneCameraPreCull += (SceneCameraDelegate)delegate(SceneCamera camera)
			{
				RefreshAll(camera, cull: true);
			};
			SceneCamera.onSceneCameraPreRender += (SceneCameraDelegate)delegate(SceneCamera camera)
			{
				RefreshAll(camera, cull: false);
			};
			SceneCamera.onSceneCameraPostRender += (SceneCameraDelegate)delegate
			{
				foreach (FadeBehavior instances in InstancesList)
				{
					instances.RestoreAfterCamera();
				}
			};
		}

		private static void RefreshAll(SceneCamera camera, bool cull)
		{
			CharacterBody val = (Object.op_Implicit((Object)(object)camera.cameraRigController) ? camera.cameraRigController.targetBody : null);
			PlayerCharacterMasterController player = ((Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.master)) ? val.master.playerCharacterMasterController : null);
			foreach (FadeBehavior instances in InstancesList)
			{
				if (cull)
				{
					instances.RefreshForPreCull(player);
				}
				else
				{
					instances.RefreshForPreRender(player);
				}
			}
		}

		public void Awake()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			properties = new MaterialPropertyBlock();
		}

		public void OnEnable()
		{
			InstancesList.Add(this);
		}

		public void OnDisable()
		{
			RestoreAfterCamera();
			InstancesList.Remove(this);
		}

		public void OnDestroy()
		{
			RestoreAfterCamera();
			InstancesList.Remove(this);
		}

		public void Refresh()
		{
			dirty = true;
		}

		public void RefreshNextFrame()
		{
			Refresh();
		}

		public void RefreshComponentLists()
		{
			dirty = false;
			renderers.Clear();
			effects.Clear();
			ExtraGameObjects.RemoveWhere((GameObject target) => !Object.op_Implicit((Object)(object)target));
			HashSet<GameObject> hashSet = new HashSet<GameObject>(ExtraGameObjects) { ((Component)this).gameObject };
			ModelLocator[] componentsInChildren = ((Component)this).GetComponentsInChildren<ModelLocator>();
			foreach (ModelLocator val in componentsInChildren)
			{
				if ((Object)(object)val.modelTransform != (Object)null)
				{
					hashSet.Add(((Component)val.modelTransform).gameObject);
				}
			}
			GameObject[] array = hashSet.ToArray();
			for (int num = 0; num < array.Length; num++)
			{
				CostHologramContent[] componentsInChildren2 = array[num].GetComponentsInChildren<CostHologramContent>();
				foreach (CostHologramContent val2 in componentsInChildren2)
				{
					if (Object.op_Implicit((Object)(object)val2.targetTextMesh))
					{
						hashSet.Add(((Component)val2.targetTextMesh).gameObject);
					}
				}
			}
			foreach (GameObject item in hashSet)
			{
				renderers.UnionWith(item.GetComponentsInChildren<Renderer>());
				effects.UnionWith((IEnumerable<Behaviour>)(object)item.GetComponentsInChildren<Highlight>());
				effects.UnionWith((IEnumerable<Behaviour>)(object)item.GetComponentsInChildren<Light>());
			}
			renderers.RemoveWhere(delegate(Renderer renderer)
			{
				if (Object.op_Implicit((Object)(object)renderer))
				{
					FadeBehavior componentInParent = ((Component)renderer).GetComponentInParent<FadeBehavior>();
					if (Object.op_Implicit((Object)(object)componentInParent))
					{
						return (Object)(object)componentInParent != (Object)(object)this;
					}
				}
				return false;
			});
			effects.RemoveWhere(delegate(Behaviour effect)
			{
				if (Object.op_Implicit((Object)(object)effect))
				{
					FadeBehavior componentInParent = ((Component)effect).GetComponentInParent<FadeBehavior>();
					if (Object.op_Implicit((Object)(object)componentInParent))
					{
						return (Object)(object)componentInParent != (Object)(object)this;
					}
				}
				return false;
			});
		}

		private bool Visible(PlayerCharacterMasterController player)
		{
			if (PendingOwnership.IsPending(((Component)this).gameObject))
			{
				return false;
			}
			InstanceHandler component = ((Component)this).GetComponent<InstanceHandler>();
			if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)player))
			{
				return component.IsInstancedFor(player);
			}
			return true;
		}

		public float GetFadeLevelForCameraRigController(CameraRigController camera)
		{
			CharacterBody val = (Object.op_Implicit((Object)(object)camera) ? camera.targetBody : null);
			if (!Visible((Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.master)) ? val.master.playerCharacterMasterController : null))
			{
				return FadeLevel;
			}
			return 1f;
		}

		public void RefreshForPreCull(PlayerCharacterMasterController player)
		{
			RestoreAfterCamera();
			if (dirty)
			{
				RefreshComponentLists();
			}
			bool flag = Visible(player);
			foreach (Renderer renderer in renderers)
			{
				if (Object.op_Implicit((Object)(object)renderer))
				{
					originalForce[renderer] = renderer.forceRenderingOff;
					renderer.forceRenderingOff = renderer.forceRenderingOff || !flag;
				}
			}
			foreach (Behaviour effect in effects)
			{
				if (Object.op_Implicit((Object)(object)effect))
				{
					originalEffects[effect] = effect.enabled;
					if (!flag)
					{
						effect.enabled = false;
					}
				}
			}
		}

		public void RefreshForPreRender(PlayerCharacterMasterController player)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			if (dirty)
			{
				RefreshComponentLists();
			}
			float num = (Visible(player) ? 1f : FadeLevel);
			foreach (Renderer renderer in renderers)
			{
				if (Object.op_Implicit((Object)(object)renderer))
				{
					if (!originalProperties.ContainsKey(renderer))
					{
						MaterialPropertyBlock val = new MaterialPropertyBlock();
						renderer.GetPropertyBlock(val);
						originalProperties[renderer] = val;
					}
					renderer.GetPropertyBlock(properties);
					properties.SetFloat(Fade, num);
					renderer.SetPropertyBlock(properties);
				}
			}
		}

		public void RestoreAfterCamera()
		{
			foreach (KeyValuePair<Renderer, bool> item in originalForce)
			{
				if (Object.op_Implicit((Object)(object)item.Key))
				{
					item.Key.forceRenderingOff = item.Value;
				}
			}
			foreach (KeyValuePair<Behaviour, bool> originalEffect in originalEffects)
			{
				if (Object.op_Implicit((Object)(object)originalEffect.Key))
				{
					originalEffect.Key.enabled = originalEffect.Value;
				}
			}
			foreach (KeyValuePair<Renderer, MaterialPropertyBlock> originalProperty in originalProperties)
			{
				if (Object.op_Implicit((Object)(object)originalProperty.Key))
				{
					originalProperty.Key.SetPropertyBlock(originalProperty.Value);
				}
			}
			originalForce.Clear();
			originalEffects.Clear();
			originalProperties.Clear();
		}

		public static FadeBehavior Attach(GameObject target)
		{
			FadeBehavior obj = target.GetComponent<FadeBehavior>() ?? target.AddComponent<FadeBehavior>();
			obj.Refresh();
			return obj;
		}
	}
	public static class InstanceAccessPolicy
	{
		public static PlayerCharacterMasterController ResolvePlayer(Interactor interactor)
		{
			if (!Object.op_Implicit((Object)(object)interactor))
			{
				return null;
			}
			return ResolvePlayer(((Component)interactor).GetComponent<CharacterBody>());
		}

		public static PlayerCharacterMasterController ResolvePlayer(CharacterBody body)
		{
			if (!Object.op_Implicit((Object)(object)body) || !Object.op_Implicit((Object)(object)body.master))
			{
				return null;
			}
			return body.master.playerCharacterMasterController;
		}

		public static bool CanInteract(InstanceHandler handler, PlayerCharacterMasterController player)
		{
			if (Object.op_Implicit((Object)(object)handler))
			{
				return handler.IsInstancedFor(player);
			}
			return false;
		}

		public static bool CanInteract(InstanceHandler handler, Interactor interactor)
		{
			return CanInteract(handler, ResolvePlayer(interactor));
		}

		public static bool CanInteract(GameObject target, Interactor interactor)
		{
			if (PendingOwnership.IsPending(target))
			{
				return false;
			}
			InstanceHandler instanceHandler = (Object.op_Implicit((Object)(object)target) ? target.GetComponent<InstanceHandler>() : null);
			if (Object.op_Implicit((Object)(object)instanceHandler))
			{
				return CanInteract(instanceHandler, interactor);
			}
			return true;
		}
	}
	public class InstancedLootBehaviour : MonoBehaviour
	{
	}
	public sealed class InstanceHandler : InstancedLootBehaviour
	{
		public static readonly List<InstanceHandler> Instances = new List<InstanceHandler>();

		public PlayerCharacterMasterController Owner { get; private set; }

		public int GroupId { get; private set; }

		public int Revision { get; private set; }

		public IEnumerable<InstanceHandler> LinkedHandlers => Instances.Where((InstanceHandler handler) => Object.op_Implicit((Object)(object)handler) && handler.GroupId == GroupId);

		public IEnumerable<PlayerCharacterMasterController> AllPlayers => (from handler in LinkedHandlers
			select handler.Owner into player
			where Object.op_Implicit((Object)(object)player)
			select player).Distinct();

		public HashSet<PlayerCharacterMasterController> Players
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)Owner))
				{
					return new HashSet<PlayerCharacterMasterController>();
				}
				return new HashSet<PlayerCharacterMasterController> { Owner };
			}
		}

		public PlayerCharacterMasterController OrigPlayer => Owner;

		public void Awake()
		{
			Instances.Add(this);
		}

		public void Assign(PlayerCharacterMasterController owner, int groupId, int revision = 1)
		{
			Owner = owner;
			GroupId = groupId;
			Revision = revision;
			PendingOwnership.Resolve(((Component)this).gameObject);
			FadeBehavior.Attach(((Component)this).gameObject).Refresh();
		}

		public bool IsInstancedFor(PlayerCharacterMasterController player)
		{
			if (Object.op_Implicit((Object)(object)player))
			{
				return (Object)(object)Owner == (Object)(object)player;
			}
			return false;
		}

		public bool IsObjectInstancedFor(PlayerCharacterMasterController player)
		{
			return IsInstancedFor(player);
		}

		public bool IsInstancedForInteractor(Interactor interactor)
		{
			return InstanceAccessPolicy.CanInteract(this, interactor);
		}

		public void OnDestroy()
		{
			Instances.Remove(this);
			FadeBehavior component = ((Component)this).GetComponent<FadeBehavior>();
			if (Object.op_Implicit((Object)(object)component))
			{
				Object.Destroy((Object)(object)component);
			}
		}
	}
	public sealed class PendingOwnership : InstancedLootBehaviour
	{
		public bool Resolved;

		public static void Mark(GameObject target)
		{
			if (!Object.op_Implicit((Object)(object)target.GetComponent<PendingOwnership>()))
			{
				target.AddComponent<PendingOwnership>();
			}
			FadeBehavior.Attach(target).Refresh();
		}

		public static bool IsPending(GameObject target)
		{
			PendingOwnership pendingOwnership = (Object.op_Implicit((Object)(object)target) ? target.GetComponent<PendingOwnership>() : null);
			if (Object.op_Implicit((Object)(object)pendingOwnership))
			{
				return !pendingOwnership.Resolved;
			}
			return false;
		}

		public static void Resolve(GameObject target)
		{
			PendingOwnership component = target.GetComponent<PendingOwnership>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.Resolved = true;
				Object.Destroy((Object)(object)component);
				FadeBehavior component2 = target.GetComponent<FadeBehavior>();
				if (Object.op_Implicit((Object)(object)component2))
				{
					component2.Refresh();
				}
			}
		}
	}
	public sealed class PingerControllerRenderBehaviour : InstancedLootBehaviour
	{
		public static readonly List<PingerControllerRenderBehaviour> InstancesList;

		private readonly Dictionary<Renderer, bool> originalForce = new Dictionary<Renderer, bool>();

		private PingerController pinger;

		static PingerControllerRenderBehaviour()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			InstancesList = new List<PingerControllerRenderBehaviour>();
			SceneCamera.onSceneCameraPreCull += (SceneCameraDelegate)delegate(SceneCamera camera)
			{
				CharacterBody val = (Object.op_Implicit((Object)(object)camera.cameraRigController) ? camera.cameraRigController.targetBody : null);
				PlayerCharacterMasterController player = ((Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.master)) ? val.master.playerCharacterMasterController : null);
				foreach (PingerControllerRenderBehaviour instances in InstancesList)
				{
					instances.RefreshForPlayer(player);
				}
			};
			SceneCamera.onSceneCameraPostRender += (SceneCameraDelegate)delegate
			{
				foreach (PingerControllerRenderBehaviour instances2 in InstancesList)
				{
					instances2.RestoreAfterCamera();
				}
			};
		}

		public void Awake()
		{
			pinger = ((Component)this).GetComponent<PingerController>();
		}

		public void OnEnable()
		{
			InstancesList.Add(this);
		}

		public void OnDisable()
		{
			RestoreAfterCamera();
			InstancesList.Remove(this);
		}

		public void OnDestroy()
		{
			RestoreAfterCamera();
			InstancesList.Remove(this);
		}

		public void RefreshForPlayer(PlayerCharacterMasterController player)
		{
			RestoreAfterCamera();
			if (Object.op_Implicit((Object)(object)pinger) && Object.op_Implicit((Object)(object)pinger.pingIndicator))
			{
				PingIndicator pingIndicator = pinger.pingIndicator;
				bool flag = Utils.IsObjectInteractibleForPlayer(pingIndicator.pingTarget, player);
				Renderer[] componentsInChildren = ((Component)pingIndicator).GetComponentsInChildren<Renderer>();
				foreach (Renderer val in componentsInChildren)
				{
					originalForce[val] = val.forceRenderingOff;
					val.forceRenderingOff = val.forceRenderingOff || !flag;
				}
			}
		}

		public void RestoreAfterCamera()
		{
			foreach (KeyValuePair<Renderer, bool> item in originalForce)
			{
				if (Object.op_Implicit((Object)(object)item.Key))
				{
					item.Key.forceRenderingOff = item.Value;
				}
			}
			originalForce.Clear();
		}
	}
	public class SpawnCardTracker : InstancedLootBehaviour
	{
		public SpawnCard SpawnCard;
	}
}
namespace InstancedLoot.Hooks
{
	public abstract class AbstractHookHandler
	{
		internal HookManager hookManager;

		protected InstancedLoot Plugin => hookManager.Plugin;

		protected Config ModConfig => Plugin.ModConfig;

		public void Init(HookManager _hookManager)
		{
			hookManager = _hookManager;
		}

		public abstract void RegisterHooks();

		public abstract void UnregisterHooks();
	}
	public sealed class HookManager
	{
		public readonly Dictionary<Type, AbstractHookHandler> HookHandlers = new Dictionary<Type, AbstractHookHandler>();

		public readonly InstancedLoot Plugin;

		public HookManager(InstancedLoot plugin)
		{
			Plugin = plugin;
			RegisterHandler<ObjectLifecycleHooks>();
			RegisterHandler<PurchaseInteractionHandler>();
			RegisterHandler<InteractorHandler>();
			RegisterHandler<SpawnCardHandler>();
			RegisterHandler<SceneDirectorHandler>();
			RegisterHandler<DeathRewardsHandler>();
			RegisterHandler<DitherModelHandler>();
			RegisterHandler<HologramProjectorHandler>();
			RegisterHandler<AnimationEventsHandler>();
			RegisterHandler<EffectManagerHandler>();
			RegisterHandler<PingHandler>();
		}

		public void RegisterHandler<T>() where T : AbstractHookHandler, new()
		{
			if (!HookHandlers.ContainsKey(typeof(T)))
			{
				T val = new T();
				val.Init(this);
				HookHandlers.Add(typeof(T), val);
			}
		}

		public T GetHandler<T>() where T : AbstractHookHandler
		{
			return (T)HookHandlers[typeof(T)];
		}

		public void RegisterHooks()
		{
			foreach (AbstractHookHandler value in HookHandlers.Values)
			{
				value.RegisterHooks();
			}
		}

		public void UnregisterHooks()
		{
			foreach (AbstractHookHandler value in HookHandlers.Values)
			{
				value.UnregisterHooks();
			}
		}
	}
	public class AnimationEventsHandler : AbstractHookHandler
	{
		public static AnimationEvents CurrentAnimationEvents;

		public override void RegisterHooks()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			AnimationEvents.CreateEffect += new hook_CreateEffect(On_AnimationEvents_CreateEffect);
			AnimationEvents.CreatePrefab += new Manipulator(IL_AnimationEvents_CreatePrefab);
		}

		public override void UnregisterHooks()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			AnimationEvents.CreateEffect -= new hook_CreateEffect(On_AnimationEvents_CreateEffect);
			AnimationEvents.CreatePrefab -= new Manipulator(IL_AnimationEvents_CreatePrefab);
		}

		private void On_AnimationEvents_CreateEffect(orig_CreateEffect orig, AnimationEvents self, AnimationEvent animationEvent)
		{
			CurrentAnimationEvents = self;
			orig.Invoke(self, animationEvent);
			CurrentAnimationEvents = null;
			FadeBehavior component = ((Component)self).GetComponent<FadeBehavior>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.RefreshNextFrame();
			}
			EntityLocator component2 = ((Component)self).GetComponent<EntityLocator>();
			if (Object.op_Implicit((Object)(object)component2) && Object.op_Implicit((Object)(object)component2.entity))
			{
				FadeBehavior component3 = component2.entity.GetComponent<FadeBehavior>();
				if (Object.op_Implicit((Object)(object)component3))
				{
					component3.Refresh();
				}
			}
		}

		private void IL_AnimationEvents_CreatePrefab(ILContext il)
		{
			AnimationPrefabIL.Apply<Action<Transform, AnimationEvents, bool>>(il, HandlePrefabCreation);
		}

		public static void HandlePrefabCreation(Transform created, AnimationEvents parent, bool pooled)
		{
			if (!pooled && Object.op_Implicit((Object)(object)created))
			{
				HandleObjectCreation(((Component)created).gameObject, parent);
			}
		}

		public static void HandleEffectCreation(GameObject objectToAdd)
		{
			if ((Object)(object)CurrentAnimationEvents != (Object)null)
			{
				HandleObjectCreation(objectToAdd, CurrentAnimationEvents);
			}
		}

		public static void HandleObjectCreation(GameObject objectToAdd, AnimationEvents parent)
		{
			Transform val = objectToAdd.transform;
			Transform transform = ((Component)parent).transform;
			while ((Object)(object)val != (Object)(object)transform && (Object)(object)val != (Object)null)
			{
				val = val.parent;
			}
			FadeBehavior componentInParent = ((Component)parent).GetComponentInParent<FadeBehavior>();
			if ((Object)(object)componentInParent == (Object)null)
			{
				EntityLocator component = ((Component)parent).GetComponent<EntityLocator>();
				if ((Object)(object)component != (Object)null && (Object)(object)component.entity != (Object)null)
				{
					componentInParent = component.entity.GetComponentInParent<FadeBehavior>();
				}
			}
			if (!((Object)(object)componentInParent == (Object)null))
			{
				if ((Object)(object)val != (Object)(object)transform)
				{
					componentInParent.ExtraGameObjects.Add(objectToAdd);
				}
				componentInParent.Refresh();
			}
		}
	}
	internal static class AnimationPrefabIL
	{
		internal static void Apply<TDelegate>(ILContext il, TDelegate handleCreation) where TDelegate : Delegate
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Expected O, but got Unknown
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Invalid comparison between Unknown and I4
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			ILCursor val = new ILCursor(il);
			int pooledLocal = -1;
			if (!val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[2]
			{
				delegate(Instruction i)
				{
					//IL_0001: Unknown result type (might be due to invalid IL or missing references)
					//IL_0006: Unknown result type (might be due to invalid IL or missing references)
					//IL_0050: Unknown result type (might be due to invalid IL or missing references)
					//IL_0056: Invalid comparison between Unknown and I4
					if (i.OpCode == OpCodes.Call)
					{
						object operand = i.Operand;
						MethodReference val2 = (MethodReference)((operand is MethodReference) ? operand : null);
						if (val2 != null && ((MemberReference)((MemberReference)val2).DeclaringType).FullName == "RoR2.EffectManager" && ((MemberReference)val2).Name == "ShouldUsePooledEffect" && (int)val2.ReturnType.MetadataType == 2 && val2.Parameters.Count == 1)
						{
							return ((MemberReference)((ParameterReference)val2.Parameters[0]).ParameterType).FullName == "UnityEngine.GameObject";
						}
					}
					return false;
				},
				(Instruction i) => ILPatternMatchingExt.MatchStloc(i, ref pooledLocal)
			}) || (int)((VariableReference)il.Body.Variables[pooledLocal]).VariableType.MetadataType != 2)
			{
				throw new InvalidOperationException(((MemberReference)il.Method).FullName + ": CreatePrefab pooled-effect flag pattern not found.");
			}
			val.Index = 0;
			int num = 0;
			while (val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
			{
				delegate(Instruction i)
				{
					//IL_0001: Unknown result type (might be due to invalid IL or missing references)
					//IL_0006: Unknown result type (might be due to invalid IL or missing references)
					//IL_009e: Unknown result type (might be due to invalid IL or missing references)
					//IL_00a4: Invalid comparison between Unknown and I4
					if (i.OpCode == OpCodes.Call)
					{
						object operand = i.Operand;
						MethodReference val2 = (MethodReference)((operand is MethodReference) ? operand : null);
						if (val2 != null && ((MemberReference)((MemberReference)val2).DeclaringType).FullName == "RoR2.AnimationEvents" && !val2.HasThis && ((MemberReference)val2).Name.StartsWith("<CreatePrefab>g__DoSpawnEffect|", StringComparison.Ordinal) && ((MemberReference)val2.ReturnType).FullName == "UnityEngine.Transform" && val2.Parameters.Count == 5 && (int)((ParameterReference)val2.Parameters[0]).ParameterType.MetadataType == 2 && ((MemberReference)((ParameterReference)val2.Parameters[1]).ParameterType).FullName == "UnityEngine.GameObject" && ((MemberReference)((ParameterReference)val2.Parameters[2]).ParameterType).FullName == "UnityEngine.Vector3" && ((MemberReference)((ParameterReference)val2.Parameters[3]).ParameterType).FullName == "UnityEngine.Quaternion")
						{
							return ((MemberReference)((ParameterReference)val2.Parameters[4]).ParameterType).FullName == "UnityEngine.Transform";
						}
					}
					return false;
				}
			}))
			{
				val.Emit(OpCodes.Dup);
				val.Emit(OpCodes.Ldarg_0);
				val.Emit(OpCodes.Ldloc, il.Body.Variables[pooledLocal]);
				val.EmitDelegate<TDelegate>(handleCreation);
				num++;
			}
			if (num == 0)
			{
				throw new InvalidOperationException(((MemberReference)il.Method).FullName + ": CreatePrefab DoSpawnEffect pattern not found.");
			}
		}
	}
	public class DeathRewardsHandler : AbstractHookHandler
	{
		public override void RegisterHooks()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			DeathRewards.OnKilledServer += new Manipulator(IL_DeathRewards_OnKilledServer);
		}

		public override void UnregisterHooks()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			DeathRewards.OnKilledServer -= new Manipulator(IL_DeathRewards_OnKilledServer);
		}

		private void IL_DeathRewards_OnKilledServer(ILContext il)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			ILCursor val = new ILCursor(il);
			val.GotoNext((MoveType)0, new Func<Instruction, bool>[1]
			{
				(Instruction i) => ILPatternMatchingExt.MatchCallOrCallvirt<TeamManager>(i, "GiveTeamMoney")
			});
			val.EmitDelegate<Func<uint, uint>>((Func<uint, uint>)delegate(uint money)
			{
				if (base.ModConfig.ReduceMoneyDrops.Value)
				{
					money /= (uint)Math.Max(1, Run.instance.participatingPlayerCount);
				}
				return money;
			});
		}
	}
	public class DitherModelHandler : AbstractHookHandler
	{
		public override void RegisterHooks()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			DitherModel.RefreshObstructorsForCamera += new Manipulator(IL_DitherModel_RefreshObstructorsForCamera);
		}

		public override void UnregisterHooks()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			DitherModel.RefreshObstructorsForCamera -= new Manipulator(IL_DitherModel_RefreshObstructorsForCamera);
		}

		private void IL_DitherModel_RefreshObstructorsForCamera(ILContext il)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Expected O, but got Unknown
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			ILCursor val = new ILCursor(il);
			ILLabel val2 = il.DefineLabel();
			ILLabel val3 = il.DefineLabel();
			MethodInfo methodInfo = typeof(Component).GetMethods(BindingFlags.Instance | BindingFlags.Public).First((MethodInfo method) => method.Name == "GetComponent" && method.IsGenericMethod).MakeGenericMethod(typeof(FadeBehavior));
			int ditherModelLoc = -1;
			val.GotoNext((MoveType)0, new Func<Instruction, bool>[2]
			{
				(Instruction i) => ILPatternMatchingExt.MatchLdloc(i, ref ditherModelLoc),
				(Instruction i) => ILPatternMatchingExt.MatchCallOrCallvirt<DitherModel>(i, "UpdateDither")
			});
			int index = val.Index;
			val.Index = index + 1;
			val.Emit(OpCodes.Dup);
			val.Emit(OpCodes.Dup);
			val.Emit(OpCodes.Call, (MethodBase)methodInfo);
			val.Emit(OpCodes.Dup);
			val.Emit(OpCodes.Ldnull);
			val.Emit(OpCodes.Ceq);
			val.Emit(OpCodes.Brtrue, (object)val2);
			val.Emit(OpCodes.Ldarg_0);
			val.Emit<FadeBehavior>(OpCodes.Call, "GetFadeLevelForCameraRigController");
			val.Emit(OpCodes.Ldloc, ditherModelLoc);
			val.Emit<DitherModel>(OpCodes.Ldfld, "fade");
			val.Emit(OpCodes.Mul);
			val.Emit<DitherModel>(OpCodes.Stfld, "fade");
			val.Emit(OpCodes.Br, (object)val3);
			val.MarkLabel(val2);
			val.Emit(OpCodes.Pop);
			val.Emit(OpCodes.Pop);
			val.MarkLabel(val3);
		}
	}
	public class EffectManagerHandler : AbstractHookHandler
	{
		public override void RegisterHooks()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			EffectManager.SpawnEffect_EffectIndex_EffectData_bool += new Manipulator(IL_EffectManager_SpawnEffect);
		}

		public override void UnregisterHooks()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			EffectManager.SpawnEffect_EffectIndex_EffectData_bool -= new Manipulator(IL_EffectManager_SpawnEffect);
		}

		private void IL_EffectManager_SpawnEffect(ILContext il)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			ILCursor val = new ILCursor(il);
			val.GotoNext((MoveType)2, new Func<Instruction, bool>[1]
			{
				(Instruction i) => ILPatternMatchingExt.MatchCallOrCallvirt<Object>(i, "Instantiate")
			});
			val.Emit(OpCodes.Dup);
			val.Emit<AnimationEventsHandler>(OpCodes.Call, "HandleEffectCreation");
		}
	}
	public class HologramProjectorHandler : AbstractHookHandler
	{
		private readonly MethodInfo Method_ReadOnlyCollection_PlayerCharacterMasterController_get_Item = typeof(ReadOnlyCollection<PlayerCharacterMasterController>).GetMethod("get_Item", BindingFlags.Instance | BindingFlags.Public);

		public override void RegisterHooks()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			HologramProjector.FindViewer += new Manipulator(IL_HologramProjector_FindViewer);
			HologramProjector.BuildHologram += new hook_BuildHologram(On_HologramProjector_BuildHologram);
			HologramProjector.DestroyHologram += new hook_DestroyHologram(On_HologramProjector_DestroyHologram);
		}

		public override void UnregisterHooks()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			HologramProjector.FindViewer -= new Manipulator(IL_HologramProjector_FindViewer);
			HologramProjector.BuildHologram -= new hook_BuildHologram(On_HologramProjector_BuildHologram);
			HologramProjector.DestroyHologram -= new hook_DestroyHologram(On_HologramProjector_DestroyHologram);
		}

		private void On_HologramProjector_BuildHologram(orig_BuildHologram orig, HologramProjector self)
		{
			orig.Invoke(self);
			FadeBehavior component = ((Component)self).GetComponent<FadeBehavior>();
			if ((Object)(object)component != (Object)null)
			{
				component.Refresh();
				component.RefreshNextFrame();
			}
		}

		private void On_HologramProjector_DestroyHologram(orig_DestroyHologram orig, HologramProjector self)
		{
			bool num = (Object)(object)self.hologramContentInstance != (Object)null;
			orig.Invoke(self);
			FadeBehavior component = ((Component)self).GetComponent<FadeBehavior>();
			if (num && (Object)(object)component != (Object)null)
			{
				component.Refresh();
			}
		}

		private void IL_HologramProjector_FindViewer(ILContext il)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)base.Plugin == (Object)null || !((Behaviour)base.Plugin).enabled)
			{
				return;
			}
			ILCursor val = new ILCursor(il);
			MethodInfo methodInfo = typeof(Component).GetMethods(BindingFlags.Instance | BindingFlags.Public).First((MethodInfo method) => method.Name == "GetComponent" && method.IsGenericMethod).MakeGenericMethod(typeof(InstanceHandler));
			ILLabel val2 = il.DefineLabel();
			ILLabel val3 = il.DefineLabel();
			ILLabel val4 = il.DefineLabel();
			int playersVariableId = -1;
			int indexVariableId = -1;
			val.GotoNext((MoveType)0, new Func<Instruction, bool>[3]
			{
				(Instruction i) => ILPatternMatchingExt.MatchLdloc(i, ref playersVariableId),
				(Instruction i) => ILPatternMatchingExt.MatchLdloc(i, ref indexVariableId),
				(Instruction i) => ILPatternMatchingExt.MatchCallOrCallvirt(i, (MethodBase)Method_ReadOnlyCollection_PlayerCharacterMasterController_get_Item)
			});
			val.Emit(OpCodes.Ldarg_0);
			foreach (ILLabel incomingLabel in val.IncomingLabels)
			{
				incomingLabel.Target = val.Prev;
			}
			val.Emit(OpCodes.Call, (MethodBase)methodInfo);
			val.Emit(OpCodes.Dup);
			val.Emit(OpCodes.Ldnull);
			val.Emit(OpCodes.Ceq);
			val.Emit(OpCodes.Brtrue, (object)val3);
			val.Emit(OpCodes.Ldloc, playersVariableId);
			val.Emit(OpCodes.Ldloc, indexVariableId);
			val.Emit<ReadOnlyCollection<PlayerCharacterMasterController>>(OpCodes.Callvirt, "get_Item");
			val.Emit<InstanceHandler>(OpCodes.Call, "IsObjectInstancedFor");
			val.Emit(OpCodes.Brtrue, (object)val4);
			val.Emit(OpCodes.Ldc_I4_0);
			val.Emit(OpCodes.Br, (object)val2);
			val.MarkLabel(val3);
			val.Emit(OpCodes.Pop);
			val.MarkLabel(val4);
			ILLabel val5 = default(ILLabel);
			val.GotoNext((MoveType)0, new Func<Instruction, bool>[2]
			{
				(Instruction i) => ILPatternMatchingExt.MatchCallOrCallvirt<Object>(i, "op_Implicit"),
				(Instruction i) => ILPatternMatchingExt.MatchBrfalse(i, ref val5)
			});
			int index = val.Index;
			val.Index = index + 1;
			val.MarkLabel(val2);
		}
	}
	public static class InteractorCandidateIL
	{
		public static void Apply<T>(ILContext il, T filter) where T : Delegate
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			Instruction[] array = ((IEnumerable<Instruction>)il.Body.Instructions).Where(delegate(Instruction instruction)
			{
				object operand = instruction.Operand;
				GenericInstanceMethod val2 = (GenericInstanceMethod)((operand is GenericInstanceMethod) ? operand : null);
				return val2 != null && ((MemberReference)val2).Name == "TryGetComponent" && ((MemberReference)((MemberReference)val2).DeclaringType).FullName == "UnityEngine.GameObject" && val2.GenericArguments.Count == 1 && ((MemberReference)val2.GenericArguments[0]).FullName == "RoR2.IInteractable";
			}).ToArray();
			if (array.Length != 2)
			{
				throw new InvalidOperationException($"Expected raycast and overlap candidate sites, found {array.Length}.");
			}
			for (int num = 0; num < array.Length; num++)
			{
				ILCursor val = new ILCursor(il);
				val.Goto(array[num], (MoveType)0, false);
				ILLabel[] array2 = val.IncomingLabels.ToArray();
				val.Emit(OpCodes.Ldarg_0);
				ILLabel[] array3 = array2;
				for (int num2 = 0; num2 < array3.Length; num2++)
				{
					array3[num2].Target = val.Prev;
				}
				val.Emit((num == 0) ? OpCodes.Ldc_I4_0 : OpCodes.Ldc_I4_1);
				val.Remove();
				val.EmitDelegate<T>(filter);
			}
		}
	}
	public sealed class InteractorHandler : AbstractHookHandler
	{
		public delegate bool CandidateFilter(GameObject target, out IInteractable result, Interactor actor, bool spherecast);

		[CompilerGenerated]
		private static class <>O
		{
			public static Manipulator <0>__FilterCandidates;

			public static hook_PerformInteraction <1>__Perform;

			public static CandidateFilter <2>__TryCandidate;
		}

		public override void RegisterHooks()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			object obj = <>O.<0>__FilterCandidates;
			if (obj == null)
			{
				Manipulator val = FilterCandidates;
				<>O.<0>__FilterCandidates = val;
				obj = (object)val;
			}
			Interactor.FindBestInteractableObject += (Manipulator)obj;
			object obj2 = <>O.<1>__Perform;
			if (obj2 == null)
			{
				hook_PerformInteraction val2 = Perform;
				<>O.<1>__Perform = val2;
				obj2 = (object)val2;
			}
			Interactor.PerformInteraction += (hook_PerformInteraction)obj2;
		}

		public override void UnregisterHooks()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			object obj = <>O.<0>__FilterCandidates;
			if (obj == null)
			{
				Manipulator val = FilterCandidates;
				<>O.<0>__FilterCandidates = val;
				obj = (object)val;
			}
			Interactor.FindBestInteractableObject -= (Manipulator)obj;
			object obj2 = <>O.<1>__Perform;
			if (obj2 == null)
			{
				hook_PerformInteraction val2 = Perform;
				<>O.<1>__Perform = val2;
				obj2 = (object)val2;
			}
			Interactor.PerformInteraction -= (hook_PerformInteraction)obj2;
		}

		private static void FilterCandidates(ILContext il)
		{
			InteractorCandidateIL.Apply<CandidateFilter>(il, TryCandidate);
		}

		public static bool TryCandidate(GameObject target, out IInteractable result, Interactor actor, bool spherecast)
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Invalid comparison between Unknown and I4
			result = null;
			if (!Object.op_Implicit((Object)(object)target))
			{
				return false;
			}
			if (!Object.op_Implicit((Object)(object)target.GetComponent<InstanceHandler>()) && !PendingOwnership.IsPending(target))
			{
				return target.TryGetComponent<IInteractable>(ref result);
			}
			if (!InstanceAccessPolicy.CanInteract(target, actor))
			{
				return false;
			}
			IInteractable[] components = target.GetComponents<IInteractable>();
			foreach (IInteractable val in components)
			{
				Behaviour val2 = (Behaviour)(object)((val is Behaviour) ? val : null);
				if ((val2 != null && !val2.isActiveAndEnabled) || (spherecast && val.ShouldIgnoreSpherecastForInteractibility(actor)))
				{
					continue;
				}
				Interactability interactability = val.GetInteractability(actor);
				if ((int)interactability != 0)
				{
					result = val;
					if ((int)interactability == 2)
					{
						return true;
					}
				}
			}
			return result != null;
		}

		private static void Perform(orig_PerformInteraction orig, Interactor self, GameObject target)
		{
			if (!NetworkServer.active || InstanceAccessPolicy.CanInteract(target, self))
			{
				orig.Invoke(self, target);
			}
		}
	}
	public sealed class ObjectLifecycleHooks : AbstractHookHandler
	{
		private readonly NativeAdapters.Chest chest = new NativeAdapters.Chest();

		private readonly NativeAdapters.OptionChest option = new NativeAdapters.OptionChest();

		private readonly NativeAdapters.MultiShop shop = new NativeAdapters.MultiShop();

		private readonly NativeAdapters.Roulette roulette = new NativeAdapters.Roulette();

		private readonly NativeAdapters.Shrine shrine = new NativeAdapters.Shrine();

		private readonly NativeAdapters.Repair repair = new NativeAdapters.Repair();

		public override void RegisterHooks()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: 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_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Expected O, but got Unknown
			ChestBehavior.Start += new hook_Start(ChestStart);
			OptionChestBehavior.Start += new hook_Start(OptionStart);
			MultiShopController.Start += new hook_Start(ShopStart);
			ShopTerminalBehavior.Start += new hook_Start(TerminalStart);
			RouletteChestController.Start += new hook_Start(RouletteStart);
			ShrineChanceBehavior.Start += new hook_Start(ChanceStart);
			ShrineBloodBehavior.Start += new hook_Start(BloodStart);
			ShrineRestackBehavior.Start += new hook_Start(OrderStart);
			SummonMasterBehavior.Start += new hook_Start(RepairStart);
		}

		public override void UnregisterHooks()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: 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_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Expected O, but got Unknown
			ChestBehavior.Start -= new hook_Start(ChestStart);
			OptionChestBehavior.Start -= new hook_Start(OptionStart);
			MultiShopController.Start -= new hook_Start(ShopStart);
			ShopTerminalBehavior.Start -= new hook_Start(TerminalStart);
			RouletteChestController.Start -= new hook_Start(RouletteStart);
			ShrineChanceBehavior.Start -= new hook_Start(ChanceStart);
			ShrineBloodBehavior.Start -= new hook_Start(BloodStart);
			ShrineRestackBehavior.Start -= new hook_Start(OrderStart);
			SummonMasterBehavior.Start -= new hook_Start(RepairStart);
		}

		private void Start(Component component, Action original, ObjectAdapter adapter, string type, bool initializeCopyDisplay = false)
		{
			if (NetworkServer.active && base.Plugin.Objects.InitializeCopy(component.gameObject))
			{
				if (initializeCopyDisplay && Object.op_Implicit((Object)(object)component))
				{
					original();
				}
				return;
			}
			original();
			if (NetworkServer.active && type != null)
			{
				base.Plugin.Objects.InitializeSource(adapter, component.gameObject, type);
			}
		}

		private void ChestStart(orig_Start orig, ChestBehavior self)
		{
			Start((Component)(object)self, delegate
			{
				orig.Invoke(self);
			}, chest, NativeAdapters.Identify(((Component)self).gameObject, NativeAdapters.ChestTypes));
		}

		private void OptionStart(orig_Start orig, OptionChestBehavior self)
		{
			Start((Component)(object)self, delegate
			{
				orig.Invoke(self);
			}, option, NativeAdapters.Identify(((Component)self).gameObject, new string[2] { "VoidTriple", "LockboxVoid" }));
		}

		private void ShopStart(orig_Start orig, MultiShopController self)
		{
			Start((Component)(object)self, delegate
			{
				orig.Invoke(self);
			}, shop, NativeAdapters.Identify(((Component)self).gameObject, new string[3] { "TripleShopEquipment", "TripleShop", "FreeChestMultiShop" }));
		}

		private void TerminalStart(orig_Start orig, ShopTerminalBehavior self)
		{
			if (!NetworkServer.active || (!base.Plugin.Objects.IsPendingChild(((Component)self).gameObject) && (!Object.op_Implicit((Object)(object)((Component)self).GetComponent<InstanceHandler>()) || !self.hasStarted)))
			{
				orig.Invoke(self);
			}
		}

		private void RouletteStart(orig_Start orig, RouletteChestController self)
		{
			Start((Component)(object)self, delegate
			{
				orig.Invoke(self);
			}, roulette, ((Object)self).name.StartsWith("CasinoChest") ? "CasinoChest" : null);
		}

		private void ChanceStart(orig_Start orig, ShrineChanceBehavior self)
		{
			Start((Component)(object)self, delegate
			{
				orig.Invoke(self);
			}, shrine, "ShrineChance");
		}

		private void BloodStart(orig_Start orig, ShrineBloodBehavior self)
		{
			Start((Component)(object)self, delegate
			{
				orig.Invoke(self);
			}, shrine, "ShrineBlood");
		}

		private void OrderStart(orig_Start orig, ShrineRestackBehavior self)
		{
			Start((Component)(object)self, delegate
			{
				orig.Invoke(self);
			}, shrine, "ShrineRestack");
		}

		private void RepairStart(orig_Start orig, SummonMasterBehavior self)
		{
			string type = null;
			if (Object.op_Implicit((Object)(object)((Component)self).GetComponent<PurchaseInteraction>()) && Object.op_Implicit((Object)(object)self.masterPrefab) && self.destroyAfterSummoning)
			{
				string name = ((Object)((Component)self).gameObject).name;
				if (name.IndexOf("Broken", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					if (name.IndexOf("Turret", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						type = "Turret";
					}
					else if (name.IndexOf("Drone", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						type = "Drone";
					}
				}
			}
			Start((Component)(object)self, delegate
			{
				orig.Invoke(self);
			}, repair, type, initializeCopyDisplay: true);
		}
	}
	public sealed class PingHandler : AbstractHookHandler
	{
		public override void RegisterHooks()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			PingerController.RebuildPing += new hook_RebuildPing(Rebuild);
			PositionIndicator.UpdatePositions += new hook_UpdatePositions(Positions);
		}

		public override void UnregisterHooks()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			PingerController.RebuildPing -= new hook_RebuildPing(Rebuild);
			PositionIndicator.UpdatePositions -= new hook_UpdatePositions(Positions);
		}

		private void Rebuild(orig_RebuildPing orig, PingerController self, PingInfo info)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)((Component)self).GetComponent<PingerControllerRenderBehaviour>()))
			{
				((Component)self).gameObject.AddComponent<PingerControllerRenderBehaviour>();
			}
			orig.Invoke(self, info);
		}

		private void Positions(orig_UpdatePositions orig, UICamera camera)
		{
			orig.Invoke(camera);
			foreach (PositionIndicator instances in PositionIndicator.instancesList)
			{
				if (Object.op_Implicit((Object)(object)instances.targetTransform) && !Utils.IsObjectInteractibleForCameraRigController(((Component)instances.targetTransform).gameObject, camera.cameraRigController))
				{
					if (Object.op_Implicit((Object)(object)instances.insideViewObject))
					{
						instances.insideViewObject.SetActive(false);
					}
					if (Object.op_Implicit((Object)(object)instances.outsideViewObject))
					{
						instances.outsideViewObject.SetActive(false);
					}
					if (Object.op_Implicit((Object)(object)instances.alwaysVisibleObject))
					{
						instances.alwaysVisibleObject.SetActive(false);
					}
				}
			}
		}
	}
	public sealed class PurchaseInteractionHandler : AbstractHookHandler
	{
		private readonly HashSet<Object> inProgress = new HashSet<Object>();

		public override void RegisterHooks()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			PurchaseInteraction.GetInteractability += new hook_GetInteractability(GetInteractability);
			PurchaseInteraction.OnInteractionBegin += new hook_OnInteractionBegin(Begin);
		}

		public override void UnregisterHooks()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			PurchaseInteraction.GetInteractability -= new hook_GetInteractability(GetInteractability);
			PurchaseInteraction.OnInteractionBegin -= new hook_OnInteractionBegin(Begin);
			inProgress.Clear();
		}

		private Interactability GetInteractability(orig_GetInteractability orig, PurchaseInteraction self, Interactor actor)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			if (!InstanceAccessPolicy.CanInteract(((Component)self).gameObject, actor))
			{
				return (Interactability)0;
			}
			return orig.Invoke(self, actor);
		}

		private void Begin(orig_OnInteractionBegin orig, PurchaseInteraction self, Interactor actor)
		{
			if (!NetworkServer.active)
			{
				orig.Invoke(self, actor);
				return;
			}
			if (!Object.op_Implicit((Object)(object)((Component)self).GetComponent<InstanceHandler>()) && !PendingOwnership.IsPending(((Component)self).gameObject))
			{
				orig.Invoke(self, actor);
				return;
			}
			ShopTerminalBehavior component = ((Component)self).GetComponent<ShopTerminalBehavior>();
			Object item = (Object)((Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.serverMultiShopController)) ? ((object)component.serverMultiShopController) : ((object)self));
			if (!InstanceAccessPolicy.CanInteract(((Component)self).gameObject, actor) || !self.available || !inProgress.Add(item))
			{
				return;
			}
			try
			{
				orig.Invoke(self, actor);
			}
			finally
			{
				inProgress.Remove(item);
			}
		}
	}
	public sealed class SceneDirectorHandler : AbstractHookHandler
	{
		public override void RegisterHooks()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			SceneDirector.Start += new Manipulator(Budget);
		}

		public override void UnregisterHooks()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			SceneDirector.Start -= new Manipulator(Budget);
		}

		private void Budget(ILContext il)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			ILCursor val = new ILCursor(il);
			val.GotoNext((MoveType)2, new Func<Instruction, bool>[1]
			{
				(Instruction instruction) => ILPatternMatchingExt.MatchCallOrCallvirt<Run>(instruction, "get_participatingPlayerCount")
			});
			val.EmitDelegate<Func<int, int>>((Func<int, int>)((int count) => base.ModConfig.ReduceInteractibleBudget.Value ? 1 : count));
		}
	}
	public class SpawnCardHandler : AbstractHookHandler
	{
		public override void RegisterHooks()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			SpawnCard.DoSpawn += new hook_DoSpawn(On_SpawnCard_DoSpawn);
		}

		public override void UnregisterHooks()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			SpawnCard.DoSpawn -= new hook_DoSpawn(On_SpawnCard_DoSpawn);
		}

		private void HandleSpawnResult(SpawnCard spawnCard, SpawnResult result)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)result.spawnedInstance))
			{
				result.spawnedInstance.AddComponent<SpawnCardTracker>().SpawnCard = spawnCard;
			}
		}

		private SpawnResult On_SpawnCard_DoSpawn(orig_DoSpawn orig, SpawnCard self, Vector3 position, Quaternion rotation, DirectorSpawnRequest spawnRequest)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			SpawnResult result = orig.Invoke(self, position, rotation, spawnRequest);
			HandleSpawnResult(self, result);
			return result;
		}
	}
}