Decompiled source of QuotaControl v0.1.3

QuotaControl.dll

Decompiled an hour ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using QuotaControl.Domain;
using REPOLib.Modules;
using UnityEngine;
using UnityEngine.Events;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("QuotaControl")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.3.0")]
[assembly: AssemblyInformationalVersion("0.1.3")]
[assembly: AssemblyProduct("QuotaControl")]
[assembly: AssemblyTitle("QuotaControl")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.3.0")]
[module: UnverifiableCode]
[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 QuotaControl
{
	internal sealed class ConfirmationPanel : MonoBehaviour
	{
		private ExtractionControl control;

		private Transform button;

		private Vector3 buttonScale;

		private float nextPress;

		private float pressUntil;

		internal static ConfirmationPanel Create(ExtractionControl control, ExtractionPoint point)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: 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_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)point.shopStation == (Object)null || (Object)(object)point.shopButton == (Object)null)
			{
				return null;
			}
			GameObject val = new GameObject("Quota Control - Shop Confirmation Stand");
			val.transform.SetParent(point.shopStation.parent, false);
			val.transform.localPosition = point.shopStation.localPosition;
			val.transform.localRotation = point.shopStation.localRotation;
			val.transform.localScale = point.shopStation.localScale;
			ConfirmationPanel confirmationPanel = val.AddComponent<ConfirmationPanel>();
			confirmationPanel.control = control;
			Dictionary<Transform, Transform> map = new Dictionary<Transform, Transform> { { point.shopStation, val.transform } };
			MeshRenderer[] componentsInChildren = ((Component)point.shopStation).GetComponentsInChildren<MeshRenderer>(true);
			foreach (MeshRenderer val2 in componentsInChildren)
			{
				MeshFilter component = ((Component)val2).GetComponent<MeshFilter>();
				if (!((Object)(object)component == (Object)null) && !((Object)(object)component.sharedMesh == (Object)null))
				{
					Transform obj = CopyTransform(((Component)val2).transform);
					((Component)obj).gameObject.layer = ((Component)val2).gameObject.layer;
					((Component)obj).gameObject.AddComponent<MeshFilter>().sharedMesh = component.sharedMesh;
					MeshRenderer obj2 = ((Component)obj).gameObject.AddComponent<MeshRenderer>();
					((Renderer)obj2).sharedMaterials = ((Renderer)val2).sharedMaterials;
					((Renderer)obj2).shadowCastingMode = ((Renderer)val2).shadowCastingMode;
					((Renderer)obj2).receiveShadows = ((Renderer)val2).receiveShadows;
					BoxCollider obj3 = ((Component)obj).gameObject.AddComponent<BoxCollider>();
					Bounds bounds = component.sharedMesh.bounds;
					obj3.center = ((Bounds)(ref bounds)).center;
					bounds = component.sharedMesh.bounds;
					obj3.size = ((Bounds)(ref bounds)).size;
				}
			}
			if (map.TryGetValue(point.shopButton, out var value))
			{
				confirmationPanel.button = value;
				confirmationPanel.buttonScale = value.localScale;
			}
			val.SetActive(false);
			Log.Info("Captured vanilla shop confirmation stand geometry and materials.");
			return confirmationPanel;
			Transform CopyTransform(Transform source)
			{
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				//IL_0038: Unknown result type (might be due to invalid IL or missing references)
				//IL_0044: Unknown result type (might be due to invalid IL or missing references)
				//IL_0050: Unknown result type (might be due to invalid IL or missing references)
				if (map.TryGetValue(source, out var value2))
				{
					return value2;
				}
				Transform transform = new GameObject(((Object)source).name).transform;
				transform.SetParent(CopyTransform(source.parent), false);
				transform.localPosition = source.localPosition;
				transform.localRotation = source.localRotation;
				transform.localScale = source.localScale;
				map.Add(source, transform);
				return transform;
			}
		}

		private void Update()
		{
			//IL_005e: 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_00ba: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)button != (Object)null)
			{
				float num = Mathf.Clamp01((pressUntil - Time.unscaledTime) / 0.25f);
				button.localScale = new Vector3(buttonScale.x, buttonScale.y * Mathf.Lerp(1f, 0.3f, num), buttonScale.z);
			}
			RaycastHit val = default(RaycastHit);
			if (control.Applies && !((Object)(object)Camera.main == (Object)null) && !((Object)(object)PlayerController.instance == (Object)null) && !(PlayerController.instance.InputDisableTimer > 0f) && Physics.Raycast(((Component)Camera.main).transform.position, ((Component)Camera.main).transform.forward, ref val, 3.5f, -1, (QueryTriggerInteraction)1) && !((Object)(object)((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<ConfirmationPanel>() != (Object)(object)this) && (SemiFunc.InputDown((InputKey)10) || SemiFunc.InputDown((InputKey)2)) && Time.unscaledTime >= nextPress)
			{
				nextPress = Time.unscaledTime + 0.5f;
				pressUntil = Time.unscaledTime + 0.25f;
				TeamControl.RequestConfirm(control.Point);
			}
		}
	}
	internal static class ControlModel
	{
		private static Texture2D panel;

		internal static void Apply(GameObject prefab)
		{
			//IL_001e: 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_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Expected O, but got Unknown
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_031d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0322: Unknown result type (might be due to invalid IL or missing references)
			//IL_032c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0354: Unknown result type (might be due to invalid IL or missing references)
			//IL_0368: Unknown result type (might be due to invalid IL or missing references)
			//IL_0390: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Expected O, but got Unknown
			Transform obj = prefab.transform.Find("Mesh");
			if ((Object)(object)obj == (Object)null)
			{
				throw new MissingComponentException("Upgrade Mesh root missing");
			}
			MeshRenderer[] componentsInChildren = ((Component)obj).GetComponentsInChildren<MeshRenderer>(true);
			if (componentsInChildren.Length == 0)
			{
				throw new MissingComponentException("Upgrade renderer missing");
			}
			Material sharedMaterial = ((Renderer)componentsInChildren[0]).sharedMaterial;
			MeshRenderer[] array = componentsInChildren;
			for (int i = 0; i < array.Length; i++)
			{
				((Renderer)array[i]).enabled = false;
			}
			GameObject val = new GameObject("Quota Control Unit");
			val.transform.SetParent(prefab.transform, false);
			Vector3 lossyScale = prefab.transform.lossyScale;
			val.transform.localScale = new Vector3(1f / lossyScale.x, 1f / lossyScale.y, 1f / lossyScale.z);
			Material material = MakeMaterial(sharedMaterial, new Color(0.92f, 0.58f, 0.04f));
			Material material2 = MakeMaterial(sharedMaterial, new Color(0.055f, 0.065f, 0.07f));
			Material material3 = MakeMaterial(sharedMaterial, new Color(0.15f, 0.9f, 0.32f));
			Part(val.transform, "Housing", (PrimitiveType)3, new Vector3(0f, 0.18f, 0f), new Vector3(0.36f, 0.36f, 0.13f), material);
			Part(val.transform, "Back Plate", (PrimitiveType)3, new Vector3(0f, 0.18f, 0.07f), new Vector3(0.38f, 0.38f, 0.035f), material2);
			Material sharedMaterial2 = ((Renderer)Part(val.transform, "Printed Face", (PrimitiveType)5, new Vector3(0f, 0.18f, -0.066f), new Vector3(0.34f, 0.34f, 1f), MakeMaterial(sharedMaterial, Color.white)).GetComponent<MeshRenderer>()).sharedMaterial;
			if ((Object)(object)panel == (Object)null)
			{
				using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("QuotaControl.Panel.png");
				using MemoryStream memoryStream = new MemoryStream();
				stream.CopyTo(memoryStream);
				panel = new Texture2D(2, 2, (TextureFormat)4, true);
				ImageConversion.LoadImage(panel, memoryStream.ToArray());
				((Texture)panel).wrapMode = (TextureWrapMode)1;
				Object.DontDestroyOnLoad((Object)(object)panel);
			}
			string[] array2 = new string[3] { "_MainTex", "_BaseMap", "_BaseColorMap" };
			foreach (string text in array2)
			{
				if (sharedMaterial2.HasProperty(text))
				{
					sharedMaterial2.SetTexture(text, (Texture)(object)panel);
				}
			}
			Part(val.transform, "Confirm Button", (PrimitiveType)2, new Vector3(0f, 0.105f, -0.084f), new Vector3(0.085f, 0.018f, 0.085f), material3).transform.localRotation = Quaternion.Euler(90f, 0f, 0f);
			Part(val.transform, "Status LED", (PrimitiveType)0, new Vector3(0.14f, 0.32f, -0.078f), Vector3.one * 0.022f, material3);
			Part(val.transform, "Handle Left", (PrimitiveType)3, new Vector3(-0.215f, 0.18f, 0f), new Vector3(0.035f, 0.22f, 0.06f), material2);
			Part(val.transform, "Handle Right", (PrimitiveType)3, new Vector3(0.215f, 0.18f, 0f), new Vector3(0.035f, 0.22f, 0.06f), material2);
		}

		private static Material MakeMaterial(Material source, Color color)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			Material val = new Material(source);
			val.color = color;
			string[] array = new string[3] { "_MainTex", "_BaseMap", "_BaseColorMap" };
			foreach (string text in array)
			{
				if (val.HasProperty(text))
				{
					val.SetTexture(text, (Texture)(object)Texture2D.whiteTexture);
				}
			}
			return val;
		}

		private static GameObject Part(Transform root, string name, PrimitiveType type, Vector3 position, Vector3 size, Material material)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = GameObject.CreatePrimitive(type);
			((Object)obj).name = name;
			obj.layer = ((Component)root).gameObject.layer;
			obj.transform.SetParent(root, false);
			obj.transform.localPosition = position;
			obj.transform.localScale = size;
			Collider component = obj.GetComponent<Collider>();
			if ((Object)(object)component != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)component);
			}
			((Renderer)obj.GetComponent<MeshRenderer>()).sharedMaterial = material;
			return obj;
		}

		internal static void AttachFrame(Transform button)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: 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_0107: Unknown result type (might be due to invalid IL or missing references)
			MeshFilter component = ((Component)button).GetComponent<MeshFilter>();
			if (!((Object)(object)component == (Object)null) && !((Object)(object)component.sharedMesh == (Object)null))
			{
				Bounds bounds = component.sharedMesh.bounds;
				Vector3 size = ((Bounds)(ref bounds)).size;
				Vector3 center = ((Bounds)(ref bounds)).center;
				Material material = MakeMaterial(((Renderer)((Component)button).GetComponent<MeshRenderer>()).sharedMaterial, new Color(1f, 0.65f, 0.05f));
				Part(button, "QC Left", (PrimitiveType)3, center + new Vector3((0f - size.x) * 0.6f, 0f, 0f), new Vector3(size.x * 0.15f, size.y * 1.25f, size.z * 0.6f), material);
				Part(button, "QC Right", (PrimitiveType)3, center + new Vector3(size.x * 0.6f, 0f, 0f), new Vector3(size.x * 0.15f, size.y * 1.25f, size.z * 0.6f), material);
			}
		}
	}
	internal sealed class ExtractionControl : MonoBehaviour
	{
		private ExtractionPoint point;

		private ConfirmationPanel panel;

		internal bool AllowSuccess;

		internal bool Applies
		{
			get
			{
				if (TeamControl.Enabled && SemiFunc.RunIsLevel() && (Object)(object)point != (Object)null)
				{
					return !point.isShop;
				}
				return false;
			}
		}

		internal ExtractionPoint Point => point;

		private void Awake()
		{
			point = ((Component)this).GetComponent<ExtractionPoint>();
		}

		internal void CaptureStand()
		{
			if ((Object)(object)panel == (Object)null && SemiFunc.RunIsLevel())
			{
				panel = ConfirmationPanel.Create(this, point);
			}
		}

		internal void Refresh()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Invalid comparison between Unknown and I4
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Invalid comparison between Unknown and I4
			if ((Object)(object)panel != (Object)null)
			{
				((Component)panel).gameObject.SetActive(Applies && ((int)point.currentState == 1 || (int)point.currentState == 2));
			}
		}

		internal void Confirm()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			if (!TeamControl.IsHost || !Applies || (int)point.stateSetTo != 0)
			{
				return;
			}
			point.HaulInternalStatsUpdate();
			if (!CanConfirm())
			{
				point.soundCancel.Play(((Component)point).transform.position, 1f, 1f, 1f, 1f);
				return;
			}
			AllowSuccess = true;
			try
			{
				point.soundButton.Play(((Component)point).transform.position, 1f, 1f, 1f, 1f);
				point.StateSet((State)3);
				Log.Info("Manual extraction confirmed by shop stand.");
			}
			finally
			{
				AllowSuccess = false;
			}
		}

		private bool CanConfirm()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Invalid comparison between Unknown and I4
			return ExtractionRules.CanConfirm(TeamControl.Enabled, (int)point.currentState == 2, point.haulGoalFetched, point.haulGoal, point.haulCurrent, point.tubeSlamDownEval >= 1f, SemiFunc.GameEventIsHalloween() && (Object)(object)point.halloweenTower != (Object)null && point.halloweenTower.ExtractionWait());
		}

		private void OnDestroy()
		{
			if ((Object)(object)panel != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)panel).gameObject);
			}
		}
	}
	[HarmonyPatch(typeof(ExtractionPoint), "Start")]
	internal static class PointSetupPatch
	{
		private static void Prefix(ExtractionPoint __instance)
		{
			(((Component)__instance).GetComponent<ExtractionControl>() ?? ((Component)__instance).gameObject.AddComponent<ExtractionControl>()).CaptureStand();
		}
	}
	[HarmonyPatch(typeof(ExtractionPoint), "Update")]
	internal static class PointRefreshPatch
	{
		private static void Postfix(ExtractionPoint __instance)
		{
			((Component)__instance).GetComponent<ExtractionControl>()?.Refresh();
		}
	}
	[HarmonyPatch(typeof(ExtractionPoint), "StateSet")]
	internal static class ManualSuccessPatch
	{
		private static bool Prefix(ExtractionPoint __instance, State newState)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Invalid comparison between Unknown and I4
			if ((int)newState != 3 || (int)__instance.currentState != 2)
			{
				return true;
			}
			ExtractionControl component = ((Component)__instance).GetComponent<ExtractionControl>();
			if (!((Object)(object)component == (Object)null) && component.Applies)
			{
				return component.AllowSuccess;
			}
			return true;
		}
	}
	[BepInPlugin("sqyan.QuotaControl", "Quota Control", "0.1.3")]
	[BepInDependency("REPOLib", "4.3.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string UpgradeId = "QuotaControl";

		internal static PlayerUpgrade Upgrade;

		private Harmony harmony;

		private float nextError;

		private void Awake()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			Log.Source = ((BaseUnityPlugin)this).Logger;
			TeamControl.Initialize();
			harmony = new Harmony("sqyan.QuotaControl");
			harmony.PatchAll();
			Log.Info("Quota Control 0.1.3 loaded. Buy and use the $30,000 control unit to enable manual extraction for the team.");
		}

		private void Update()
		{
			try
			{
				ControlShop.Tick();
				TeamControl.Tick();
			}
			catch (Exception ex)
			{
				if (Time.unscaledTime >= nextError)
				{
					nextError = Time.unscaledTime + 5f;
					Log.Error(ex.ToString());
				}
			}
		}

		private void OnDestroy()
		{
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
		}
	}
	internal static class Log
	{
		internal static ManualLogSource Source;

		internal static void Info(string s)
		{
			ManualLogSource source = Source;
			if (source != null)
			{
				source.LogInfo((object)s);
			}
		}

		internal static void Error(string s)
		{
			ManualLogSource source = Source;
			if (source != null)
			{
				source.LogError((object)s);
			}
		}
	}
	internal static class ControlShop
	{
		internal static Item Item;

		private static GameObject storage;

		private static float nextRegistrationAttempt;

		internal static void Tick()
		{
			if ((Object)(object)Item != (Object)null)
			{
				BindSavedState();
			}
			if ((Object)(object)Item == (Object)null && Time.unscaledTime >= nextRegistrationAttempt)
			{
				nextRegistrationAttempt = Time.unscaledTime + 5f;
				try
				{
					Register();
				}
				catch (Exception ex)
				{
					Log.Error("Quota Control deferred registration failed: " + ex);
				}
			}
		}

		internal static void Register()
		{
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Invalid comparison between Unknown and I4
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Expected O, but got Unknown
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Expected O, but got Unknown
			if ((Object)(object)Item != (Object)null)
			{
				BindSavedState();
				return;
			}
			Item val = null;
			GameObject val2 = null;
			StatsManager instance = StatsManager.instance;
			if ((Object)(object)instance == (Object)null || instance.itemDictionary.Count == 0)
			{
				return;
			}
			Item[] array = instance.itemDictionary.Values.OrderBy<Item, string>((Item x) => ((Object)x).name, StringComparer.Ordinal).ToArray();
			Item[] array2 = array;
			foreach (Item val3 in array2)
			{
				if ((int)val3.itemType == 3 && val3.prefab != null)
				{
					GameObject prefab = ((PrefabRef<GameObject>)(object)val3.prefab).Prefab;
					if (!((Object)(object)prefab == (Object)null) && !((Object)(object)prefab.GetComponent<ItemUpgradePlayerGrabStrength>() == (Object)null))
					{
						val = val3;
						val2 = prefab;
						break;
					}
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				throw new InvalidOperationException("No upgrade prefab with ItemUpgradePlayerGrabStrength found among " + array.Count() + " item assets");
			}
			Log.Info("Quota Control template resolved by component: " + ((Object)val).name + " -> " + ((Object)val2).name);
			storage = new GameObject("QuotaControl Prefab Storage");
			storage.SetActive(false);
			Object.DontDestroyOnLoad((Object)(object)storage);
			GameObject obj = Object.Instantiate<GameObject>(val2, storage.transform, false);
			((Object)obj).name = "Item Upgrade Quota Control";
			obj.SetActive(true);
			ItemAttributes component = obj.GetComponent<ItemAttributes>();
			ItemUpgradePlayerGrabStrength component2 = obj.GetComponent<ItemUpgradePlayerGrabStrength>();
			if ((Object)(object)component2 != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)component2);
			}
			Item val4 = Object.Instantiate<Item>(val);
			((Object)val4).name = "Item Upgrade Quota Control";
			val4.itemName = "QUOTA CONTROL";
			val4.itemNameLocalized = null;
			val4.description = "Install team-wide manual extraction control for this run. Press the extraction button after reaching the quota.";
			val4.value = ScriptableObject.CreateInstance<Value>();
			val4.value.valueMin = 7500f;
			val4.value.valueMax = 9000f;
			val4.maxAmountInShop = 1;
			val4.maxAmount = 1;
			val4.maxPurchase = false;
			component.item = val4;
			obj.AddComponent<ControlInstall>();
			obj.GetComponent<ItemUpgrade>().upgradeEvent = new UnityEvent();
			ControlModel.Apply(obj);
			Plugin.Upgrade = Upgrades.GetUpgrade("QuotaControl") ?? Upgrades.RegisterUpgrade("QuotaControl", val4, (Action<PlayerAvatar, int>)null, (Action<PlayerAvatar, int>)null);
			if (Plugin.Upgrade == null || Items.RegisterItem(component) == null)
			{
				throw new InvalidOperationException("REPOLib rejected Quota Control registration");
			}
			Item = val4;
			BindSavedState();
			Log.Info("Quota Control registered: personal cereal upgrade; team manual extraction; regular price floor $30,000.");
		}

		private static void BindSavedState()
		{
			StatsManager instance = StatsManager.instance;
			if (!((Object)(object)instance == (Object)null) && Plugin.Upgrade != null)
			{
				string key = "playerUpgradeQuotaControl";
				if (instance.dictionaryOfDictionaries.TryGetValue(key, out var value))
				{
					Plugin.Upgrade.PlayerDictionary = value;
				}
				else
				{
					instance.dictionaryOfDictionaries[key] = Plugin.Upgrade.PlayerDictionary;
				}
			}
		}
	}
	public sealed class ControlInstall : MonoBehaviour
	{
		private bool consumed;

		private void Awake()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			ItemUpgrade component = ((Component)this).GetComponent<ItemUpgrade>();
			component.upgradeEvent = new UnityEvent();
			component.upgradeEvent.AddListener(new UnityAction(Consume));
		}

		public void Consume()
		{
			if (!consumed)
			{
				PlayerAvatar val = SemiFunc.PlayerAvatarGetFromPhotonID(((Component)this).GetComponent<ItemToggle>().playerTogglePhotonID);
				if (!((Object)(object)val == (Object)null) && val.isLocal && Plugin.Upgrade != null && !TeamControl.Enabled)
				{
					consumed = true;
					Plugin.Upgrade.AddLevel(val, 1);
					TeamControl.RequestInstall(val);
				}
			}
		}
	}
	[HarmonyPatch(typeof(StatsManager), "RunStartStats")]
	internal static class RegisterControlPatch
	{
		[HarmonyPostfix]
		[HarmonyPriority(800)]
		private static void Postfix()
		{
			try
			{
				ControlShop.Register();
			}
			catch (Exception ex)
			{
				Log.Error("Quota Control registration failed: " + ex);
			}
		}
	}
	[HarmonyPatch(typeof(ShopManager), "GetAllItemsFromStatsManager")]
	internal static class RegisterControlBeforeShopPatch
	{
		[HarmonyPrefix]
		private static void Prefix()
		{
			try
			{
				ControlShop.Register();
			}
			catch (Exception ex)
			{
				Log.Error("Quota Control shop registration failed: " + ex);
			}
		}
	}
	[HarmonyPatch(typeof(ShopManager), "UpgradeValueGet")]
	internal static class ControlPricePatch
	{
		[HarmonyPostfix]
		private static void Postfix(Item item, ref float __result)
		{
			if ((Object)(object)item == (Object)(object)ControlShop.Item && (Object)(object)item != (Object)null)
			{
				__result = Mathf.Max(30f, __result);
			}
		}
	}
	[HarmonyPatch(typeof(ItemToggle), "ToggleItem")]
	internal static class PreventDuplicatePurchasePatch
	{
		private static bool Prefix(ItemToggle __instance, bool toggle, int player)
		{
			if (!toggle || (Object)(object)((Component)__instance).GetComponent<ControlInstall>() == (Object)null)
			{
				return true;
			}
			if ((Object)(object)SemiFunc.PlayerAvatarGetFromPhotonID(player) == (Object)null || Plugin.Upgrade == null)
			{
				return true;
			}
			if (!TeamControl.Enabled)
			{
				return true;
			}
			Log.Info("Quota Control is already owned; cereal box was not consumed.");
			return false;
		}
	}
	internal static class TeamControl
	{
		private const string SaveKey = "sqyanQuotaControlInstalled";

		private static NetworkedEvent status;

		private static float nextSync;

		internal static bool IsHost
		{
			get
			{
				if ((Object)(object)GameManager.instance != (Object)null)
				{
					return SemiFunc.IsMasterClientOrSingleplayer();
				}
				return false;
			}
		}

		internal static bool Enabled
		{
			get
			{
				if ((Object)(object)StatsManager.instance != (Object)null && StatsManager.instance.runStats.TryGetValue("sqyanQuotaControlInstalled", out var value))
				{
					return value > 0;
				}
				return false;
			}
		}

		internal static void Initialize()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			status = new NetworkedEvent("Quota Control v1", (Action<EventData>)Receive);
		}

		internal static void RequestInstall(PlayerAvatar player)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			if (IsHost)
			{
				Install();
				return;
			}
			NetworkedEvent obj = status;
			Hashtable val = new Hashtable();
			((Dictionary<object, object>)val).Add((object)"request", (object)player.photonView.ViewID);
			obj.RaiseEvent((object)val, NetworkingEvents.RaiseMasterClient, SendOptions.SendReliable);
		}

		private static void Install()
		{
			if (!((Object)(object)StatsManager.instance == (Object)null))
			{
				StatsManager.instance.runStats["sqyanQuotaControlInstalled"] = 1;
				nextSync = 0f;
				Log.Info("Quota Control installed for the entire run.");
			}
		}

		internal static void RequestConfirm(ExtractionPoint point)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Expected O, but got Unknown
			PlayerAvatar val = PlayerController.instance?.playerAvatarScript;
			if (!((Object)(object)val == (Object)null) && !val.deadSet && !val.isDisabled)
			{
				if (IsHost)
				{
					((Component)point).GetComponent<ExtractionControl>()?.Confirm();
					return;
				}
				NetworkedEvent obj = status;
				Hashtable val2 = new Hashtable();
				((Dictionary<object, object>)val2).Add((object)"confirm", (object)point.photonView.ViewID);
				((Dictionary<object, object>)val2).Add((object)"player", (object)val.photonView.ViewID);
				obj.RaiseEvent((object)val2, NetworkingEvents.RaiseMasterClient, SendOptions.SendReliable);
			}
		}

		private static void Receive(EventData e)
		{
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			object customData = e.CustomData;
			Hashtable val = (Hashtable)((customData is Hashtable) ? customData : null);
			if (val == null || PhotonNetwork.MasterClient == null)
			{
				return;
			}
			if (val[(object)"confirm"] is int num && val[(object)"player"] is int num2 && IsHost)
			{
				PhotonView obj = PhotonView.Find(num2);
				PlayerAvatar val2 = ((obj != null) ? ((Component)obj).GetComponent<PlayerAvatar>() : null);
				PhotonView obj2 = PhotonView.Find(num);
				ExtractionPoint val3 = ((obj2 != null) ? ((Component)obj2).GetComponent<ExtractionPoint>() : null);
				if ((Object)(object)val2 != (Object)null && (Object)(object)val3 != (Object)null && val2.photonView.OwnerActorNr == e.Sender && !val2.deadSet && !val2.isDisabled && Vector3.Distance(((Component)val2).transform.position, ((Component)val3.button).transform.position) < 4.5f)
				{
					((Component)val3).GetComponent<ExtractionControl>()?.Confirm();
				}
			}
			else if (val[(object)"request"] is int num3 && IsHost)
			{
				PhotonView obj3 = PhotonView.Find(num3);
				PlayerAvatar val4 = ((obj3 != null) ? ((Component)obj3).GetComponent<PlayerAvatar>() : null);
				if ((Object)(object)val4 != (Object)null && val4.photonView.OwnerActorNr == e.Sender && Plugin.Upgrade != null && Plugin.Upgrade.GetLevel(val4) > 0)
				{
					Install();
				}
			}
			else if (e.Sender == PhotonNetwork.MasterClient.ActorNumber && val[(object)"enabled"] is bool flag && (Object)(object)StatsManager.instance != (Object)null)
			{
				StatsManager.instance.runStats["sqyanQuotaControlInstalled"] = (flag ? 1 : 0);
			}
		}

		internal static void Tick()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: 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
			if (IsHost && SemiFunc.IsMultiplayer() && !((Object)(object)StatsManager.instance == (Object)null) && !(Time.unscaledTime < nextSync))
			{
				nextSync = Time.unscaledTime + 1f;
				NetworkedEvent obj = status;
				Hashtable val = new Hashtable();
				((Dictionary<object, object>)val).Add((object)"enabled", (object)Enabled);
				obj.RaiseEvent((object)val, NetworkingEvents.RaiseOthers, SendOptions.SendReliable);
			}
		}
	}
}
namespace QuotaControl.Domain
{
	public static class ExtractionRules
	{
		public static bool CanConfirm(bool installed, bool active, bool goalKnown, int goal, int current, bool ready, bool waiting)
		{
			if (installed && active && goalKnown && goal > 0 && current >= goal && ready)
			{
				return !waiting;
			}
			return false;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}