Decompiled source of CartCompressor v0.2.2

CartCompressor.dll

Decompiled 11 hours 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.Configuration;
using BepInEx.Logging;
using CartCompressor.Domain;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
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("CartCompressor")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.2.2.0")]
[assembly: AssemblyInformationalVersion("0.2.2+cdeb81f53a82ae329c25bdc089ca143e5d64da3a")]
[assembly: AssemblyProduct("CartCompressor")]
[assembly: AssemblyTitle("CartCompressor")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.2.2.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 CartCompressor
{
	internal sealed class CargoRuntime : IDisposable
	{
		private sealed class ScaleState
		{
			internal Transform Target;

			internal Vector3 Original;

			internal float Current = 1f;

			internal float Desired = 1f;
		}

		private readonly CartAttunement attunement = new CartAttunement();

		private readonly Dictionary<int, ScaleState> scales = new Dictionary<int, ScaleState>();

		private readonly Dictionary<int, float> wanted = new Dictionary<int, float>();

		private readonly Dictionary<int, PhysGrabObject> objects = new Dictionary<int, PhysGrabObject>();

		private readonly List<string> handlers = new List<string>();

		private readonly List<int> remove = new List<int>();

		private readonly HashSet<int> knownCarts = new HashSet<int>();

		private readonly HashSet<int> currentCarts = new HashSet<int>();

		private readonly NetworkedEvent snapshot;

		private float nextScan;

		private float nextSync;

		private bool disposed;

		internal CargoRuntime()
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Expected O, but got Unknown
			snapshot = new NetworkedEvent("Cart Compressor Cargo v2", (Action<EventData>)Receive);
		}

		private int PlayerLevel(string id)
		{
			PlayerAvatar val = SemiFunc.PlayerAvatarGetFromSteamID(id);
			if (!((Object)(object)val == (Object)null) && !val.isDisabled && !val.deadSet && Plugin.Upgrade != null)
			{
				return Plugin.Upgrade.GetLevel(id);
			}
			return 0;
		}

		internal void Tick()
		{
			if ((Object)(object)GameManager.instance == (Object)null || (Object)(object)RunManager.instance == (Object)null)
			{
				return;
			}
			if (SemiFunc.IsMasterClientOrSingleplayer() && Time.unscaledTime >= nextScan)
			{
				nextScan = Time.unscaledTime + 0.1f;
				Scan();
				if (Time.unscaledTime >= nextSync)
				{
					nextSync = Time.unscaledTime + 0.5f;
					Broadcast();
				}
			}
			Animate();
		}

		private void Scan()
		{
			wanted.Clear();
			objects.Clear();
			currentCarts.Clear();
			if (Plugin.Enabled.Value)
			{
				PhysGrabCart[] array = Object.FindObjectsByType<PhysGrabCart>((FindObjectsSortMode)0);
				foreach (PhysGrabCart val in array)
				{
					int instanceID = ((Object)val).GetInstanceID();
					currentCarts.Add(instanceID);
					knownCarts.Add(instanceID);
					PhysGrabObject component = ((Component)val).GetComponent<PhysGrabObject>();
					if ((Object)(object)component == (Object)null)
					{
						continue;
					}
					handlers.Clear();
					foreach (PhysGrabber item in component.playerGrabbing)
					{
						handlers.Add(((Object)(object)item != (Object)null && (Object)(object)item.playerAvatar != (Object)null) ? item.playerAvatar.steamID : null);
					}
					CartContacts cartContacts = ((Component)component).GetComponent<CartContacts>();
					if ((Object)(object)cartContacts == (Object)null)
					{
						cartContacts = ((Component)component).gameObject.AddComponent<CartContacts>();
					}
					cartContacts.Append(handlers);
					float num = UpgradeBalance.Factor(attunement.Observe(instanceID, handlers, PlayerLevel));
					if (num >= 1f || val.itemsInCart == null)
					{
						continue;
					}
					foreach (PhysGrabObject item2 in val.itemsInCart)
					{
						if (Supported(item2))
						{
							int instanceID2 = ((Object)item2).GetInstanceID();
							if (!wanted.TryGetValue(instanceID2, out var value) || num > value)
							{
								wanted[instanceID2] = num;
							}
							objects[instanceID2] = item2;
						}
					}
				}
			}
			remove.Clear();
			foreach (int knownCart in knownCarts)
			{
				if (!currentCarts.Contains(knownCart))
				{
					remove.Add(knownCart);
				}
			}
			foreach (int item3 in remove)
			{
				knownCarts.Remove(item3);
				attunement.Remove(item3);
			}
			foreach (ScaleState value2 in scales.Values)
			{
				value2.Desired = 1f;
			}
			foreach (KeyValuePair<int, float> item4 in wanted)
			{
				SetTarget(((Component)objects[item4.Key]).transform, item4.Value, null);
			}
		}

		private static bool Supported(PhysGrabObject item, bool hostPhysics = true)
		{
			if ((Object)(object)item == (Object)null || item.dead || (Object)(object)item.rb == (Object)null || (hostPhysics && item.rb.isKinematic))
			{
				return false;
			}
			if ((Object)(object)((Component)item).GetComponent<ValuableObject>() == (Object)null || (Object)(object)((Component)item).GetComponent<ItemAttributes>() != (Object)null)
			{
				return false;
			}
			if ((Object)(object)((Component)item).GetComponent<PhysGrabCart>() != (Object)null || (Object)(object)((Component)item).GetComponent<PlayerDeathHead>() != (Object)null || (Object)(object)((Component)item).GetComponentInParent<Enemy>() != (Object)null)
			{
				return false;
			}
			return (Object)(object)((Component)item).GetComponent<SemiMounting>() == (Object)null;
		}

		private void SetTarget(Transform target, float factor, Vector3? baseline)
		{
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: 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_002c: 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_008d: 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)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			int instanceID = ((Object)((Component)target).gameObject).GetInstanceID();
			if (!scales.TryGetValue(instanceID, out var value))
			{
				Vector3 original = (Vector3)(((??)baseline) ?? target.localScale);
				float num;
				if (!baseline.HasValue || !(((Vector3)(ref original)).sqrMagnitude > 1E-06f))
				{
					num = 1f;
				}
				else
				{
					Vector3 localScale = target.localScale;
					num = Mathf.Clamp(((Vector3)(ref localScale)).magnitude / ((Vector3)(ref original)).magnitude, 0.65f, 1f);
				}
				float current = num;
				value = new ScaleState
				{
					Target = target,
					Original = original,
					Current = current
				};
				scales[instanceID] = value;
			}
			if (baseline.HasValue)
			{
				value.Original = baseline.Value;
			}
			value.Desired = Mathf.Clamp(factor, 0.65f, 1f);
		}

		private void Animate()
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			remove.Clear();
			foreach (KeyValuePair<int, ScaleState> scale in scales)
			{
				ScaleState value = scale.Value;
				if ((Object)(object)value.Target == (Object)null)
				{
					remove.Add(scale.Key);
					continue;
				}
				value.Current = Mathf.MoveTowards(value.Current, value.Desired, Time.deltaTime * ((value.Desired > value.Current) ? 4f : 0.8f));
				value.Target.localScale = value.Original * value.Current;
				if (value.Current == 1f && value.Desired == 1f)
				{
					remove.Add(scale.Key);
				}
			}
			foreach (int item in remove)
			{
				scales.Remove(item);
			}
		}

		private void Broadcast()
		{
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Expected O, but got Unknown
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Expected O, but got Unknown
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			if (!SemiFunc.IsMultiplayer())
			{
				return;
			}
			List<object> list = new List<object>();
			foreach (ScaleState value in scales.Values)
			{
				if (!((Object)(object)value.Target == (Object)null) && !(value.Desired >= 1f))
				{
					PhotonView component = ((Component)value.Target).GetComponent<PhotonView>();
					if (!((Object)(object)component == (Object)null) && component.ViewID != 0)
					{
						list.Add(new object[3] { component.ViewID, value.Desired, value.Original });
					}
				}
			}
			NetworkedEvent obj = snapshot;
			Hashtable val = new Hashtable();
			((Dictionary<object, object>)val).Add((object)"rows", (object)list.ToArray());
			obj.RaiseEvent((object)val, NetworkingEvents.RaiseOthers, SendOptions.SendReliable);
		}

		private void Receive(EventData data)
		{
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			if (disposed || PhotonNetwork.MasterClient == null || data.Sender != PhotonNetwork.MasterClient.ActorNumber)
			{
				return;
			}
			object customData = data.CustomData;
			Hashtable val = (Hashtable)((customData is Hashtable) ? customData : null);
			if (val == null || !(val[(object)"rows"] is object[] array))
			{
				return;
			}
			foreach (ScaleState value2 in scales.Values)
			{
				value2.Desired = 1f;
			}
			object[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				if (array2[i] is object[] array3 && array3.Length == 3 && array3[0] is int num && array3[1] is float num2 && array3[2] is Vector3 value && !float.IsNaN(num2) && !(num2 < 0.65f) && !(num2 >= 1f) && Finite(value))
				{
					PhotonView val2 = PhotonView.Find(num);
					if ((Object)(object)val2 != (Object)null && Supported(((Component)val2).GetComponent<PhysGrabObject>(), hostPhysics: false))
					{
						SetTarget(((Component)val2).transform, num2, value);
					}
				}
			}
		}

		private static bool Finite(Vector3 value)
		{
			//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)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			if (!float.IsNaN(value.x) && !float.IsInfinity(value.x) && !float.IsNaN(value.y) && !float.IsInfinity(value.y) && !float.IsNaN(value.z))
			{
				return !float.IsInfinity(value.z);
			}
			return false;
		}

		internal void Reset()
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			foreach (ScaleState value in scales.Values)
			{
				if ((Object)(object)value.Target != (Object)null)
				{
					value.Target.localScale = value.Original;
				}
			}
			scales.Clear();
			wanted.Clear();
			objects.Clear();
			attunement.Clear();
			knownCarts.Clear();
		}

		public void Dispose()
		{
			disposed = true;
			Reset();
		}
	}
	public sealed class CartContacts : MonoBehaviour
	{
		private readonly Dictionary<PlayerAvatar, float> recent = new Dictionary<PlayerAvatar, float>();

		private readonly List<PlayerAvatar> expired = new List<PlayerAvatar>();

		private void OnCollisionEnter(Collision collision)
		{
			Observe(collision);
		}

		private void OnCollisionStay(Collision collision)
		{
			Observe(collision);
		}

		private void Observe(Collision collision)
		{
			PlayerAvatar componentInParent = ((Component)collision.collider).GetComponentInParent<PlayerAvatar>();
			if ((Object)(object)componentInParent != (Object)null)
			{
				recent[componentInParent] = Time.time;
			}
		}

		internal void Append(List<string> players)
		{
			expired.Clear();
			foreach (KeyValuePair<PlayerAvatar, float> item in recent)
			{
				if ((Object)(object)item.Key == (Object)null || Time.time - item.Value > 0.12f)
				{
					expired.Add(item.Key);
				}
				else
				{
					players.Add(item.Key.steamID);
				}
			}
			foreach (PlayerAvatar item2 in expired)
			{
				recent.Remove(item2);
			}
		}
	}
	internal static class CerealVisual
	{
		private static Texture2D artwork;

		internal static void Apply(GameObject prefab)
		{
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Expected O, but got Unknown
			if ((Object)(object)artwork == (Object)null)
			{
				using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("CartCompressor.CartCrunch.png"))
				{
					if (stream == null)
					{
						throw new FileNotFoundException("Embedded cereal artwork missing");
					}
					using MemoryStream memoryStream = new MemoryStream();
					stream.CopyTo(memoryStream);
					artwork = new Texture2D(2, 2, (TextureFormat)4, true);
					if (!ImageConversion.LoadImage(artwork, memoryStream.ToArray()))
					{
						throw new IOException("Invalid cereal texture");
					}
				}
				((Object)artwork).name = "Cart Crunch Cereal Albedo";
				((Texture)artwork).wrapMode = (TextureWrapMode)1;
				((Texture)artwork).filterMode = (FilterMode)1;
				Object.DontDestroyOnLoad((Object)(object)artwork);
			}
			Transform obj = prefab.transform.Find("Mesh");
			if ((Object)(object)obj == (Object)null)
			{
				throw new MissingComponentException("Vanilla cereal mesh not found");
			}
			MeshRenderer[] componentsInChildren = ((Component)obj).GetComponentsInChildren<MeshRenderer>(true);
			foreach (MeshRenderer val in componentsInChildren)
			{
				Material[] sharedMaterials = ((Renderer)val).sharedMaterials;
				for (int j = 0; j < sharedMaterials.Length; j++)
				{
					sharedMaterials[j] = new Material(sharedMaterials[j]);
					if (sharedMaterials[j].HasProperty("_MainTex"))
					{
						sharedMaterials[j].SetTexture("_MainTex", (Texture)(object)artwork);
					}
					if (sharedMaterials[j].HasProperty("_BaseMap"))
					{
						sharedMaterials[j].SetTexture("_BaseMap", (Texture)(object)artwork);
					}
					if (sharedMaterials[j].HasProperty("_BaseColorMap"))
					{
						sharedMaterials[j].SetTexture("_BaseColorMap", (Texture)(object)artwork);
					}
				}
				((Renderer)val).sharedMaterials = sharedMaterials;
			}
		}
	}
	[BepInPlugin("Local.CartCompressor", "Cart Compressor", "0.2.2")]
	[BepInDependency("REPOLib", "4.3.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string UpgradeId = "CartCompressor";

		internal static PlayerUpgrade Upgrade;

		internal static CargoRuntime Cargo;

		internal static ConfigEntry<bool> Enabled;

		private Harmony harmony;

		private float nextError;

		private void Awake()
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			Log.Source = ((BaseUnityPlugin)this).Logger;
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Основное", "Включить улучшение", true, "Три уровня персонального сжатия груза.");
			Cargo = new CargoRuntime();
			harmony = new Harmony("Local.CartCompressor");
			harmony.PatchAll(typeof(Plugin).Assembly);
			Log.Info("Cart Compressor 0.2.2 standalone loaded. Dependency: REPOLib only. Tiers: 76.7% / 70.8% / 65%.");
		}

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

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

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

		internal static void Warn(string message)
		{
			ManualLogSource source = Source;
			if (source != null)
			{
				source.LogWarning((object)message);
			}
		}

		internal static void Error(string message)
		{
			ManualLogSource source = Source;
			if (source != null)
			{
				source.LogError((object)message);
			}
		}
	}
	[HarmonyPatch(typeof(RunManager), "ChangeLevel")]
	internal static class LevelResetPatch
	{
		private static void Prefix()
		{
			Plugin.Cargo?.Reset();
		}
	}
	internal static class CompressorShop
	{
		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("Cart Compressor 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("Cart Compressor template resolved by component: " + ((Object)val).name + " -> " + ((Object)val2).name);
			storage = new GameObject("CartCompressor Prefab Storage");
			storage.SetActive(false);
			Object.DontDestroyOnLoad((Object)(object)storage);
			GameObject obj = Object.Instantiate<GameObject>(val2, storage.transform, false);
			((Object)obj).name = "Item Upgrade Cart Compressor";
			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 Cart Compressor";
			val4.itemName = "CART COMPRESSOR";
			val4.itemNameLocalized = null;
			val4.description = "CART CRUNCH: personal cart compression, levels I / II / III. Cargo size: 76.7% / 70.8% / 65%. Untrained handlers cancel compression.";
			val4.value = ScriptableObject.CreateInstance<Value>();
			val4.value.valueMin = 3750f;
			val4.value.valueMax = 4500f;
			val4.maxAmountInShop = 1;
			val4.maxAmount = 6;
			val4.maxPurchase = false;
			component.item = val4;
			obj.AddComponent<CompressorConsume>();
			obj.GetComponent<ItemUpgrade>().upgradeEvent = new UnityEvent();
			CerealVisual.Apply(obj);
			Plugin.Upgrade = Upgrades.GetUpgrade("CartCompressor") ?? Upgrades.RegisterUpgrade("CartCompressor", val4, (Action<PlayerAvatar, int>)null, (Action<PlayerAvatar, int>)null);
			if (Plugin.Upgrade == null || Items.RegisterItem(component) == null)
			{
				throw new InvalidOperationException("REPOLib rejected Cart Compressor registration");
			}
			Item = val4;
			BindSavedState();
			Log.Info("Cart Compressor registered: personal cereal upgrade, 3 tiers, price floor $15,000.");
		}

		private static void BindSavedState()
		{
			StatsManager instance = StatsManager.instance;
			if (!((Object)(object)instance == (Object)null) && Plugin.Upgrade != null)
			{
				string key = "playerUpgradeCartCompressor";
				if (instance.dictionaryOfDictionaries.TryGetValue(key, out var value))
				{
					Plugin.Upgrade.PlayerDictionary = value;
				}
				else
				{
					instance.dictionaryOfDictionaries[key] = Plugin.Upgrade.PlayerDictionary;
				}
			}
		}
	}
	public sealed class CompressorConsume : 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)
			{
				return;
			}
			PlayerAvatar val = SemiFunc.PlayerAvatarGetFromPhotonID(((Component)this).GetComponent<ItemToggle>().playerTogglePhotonID);
			if (!((Object)(object)val == (Object)null) && val.isLocal && Plugin.Upgrade != null)
			{
				consumed = true;
				if (Plugin.Upgrade.GetLevel(val) < 3)
				{
					Plugin.Upgrade.AddLevel(val, 1);
				}
			}
		}
	}
	[HarmonyPatch(typeof(StatsManager), "RunStartStats")]
	internal static class RegisterCompressorPatch
	{
		[HarmonyPostfix]
		[HarmonyPriority(800)]
		private static void Postfix()
		{
			try
			{
				CompressorShop.Register();
			}
			catch (Exception ex)
			{
				Log.Error("Cart Compressor registration failed: " + ex);
			}
		}
	}
	[HarmonyPatch(typeof(ShopManager), "GetAllItemsFromStatsManager")]
	internal static class RegisterCompressorBeforeShopPatch
	{
		[HarmonyPrefix]
		private static void Prefix()
		{
			try
			{
				CompressorShop.Register();
			}
			catch (Exception ex)
			{
				Log.Error("Cart Compressor shop registration failed: " + ex);
			}
		}
	}
	[HarmonyPatch(typeof(ShopManager), "UpgradeValueGet")]
	internal static class CompressorPricePatch
	{
		[HarmonyPostfix]
		private static void Postfix(Item item, ref float __result)
		{
			if ((Object)(object)item == (Object)(object)CompressorShop.Item && (Object)(object)item != (Object)null)
			{
				__result = Mathf.Max(15f, __result);
			}
		}
	}
	[HarmonyPatch(typeof(ItemToggle), "ToggleItem")]
	internal static class MaxTierConsumptionPatch
	{
		private static bool Prefix(ItemToggle __instance, bool toggle, int player)
		{
			if (!toggle || (Object)(object)((Component)__instance).GetComponent<CompressorConsume>() == (Object)null)
			{
				return true;
			}
			PlayerAvatar val = SemiFunc.PlayerAvatarGetFromPhotonID(player);
			if ((Object)(object)val == (Object)null || Plugin.Upgrade == null)
			{
				return true;
			}
			if (Plugin.Upgrade.GetLevel(val) < 3)
			{
				return true;
			}
			Log.Info("Cart Compressor is already level III; cereal box was not consumed.");
			return false;
		}
	}
}
namespace CartCompressor.Domain
{
	public static class UpgradeBalance
	{
		public const int MaxLevel = 3;

		public static float Factor(int level)
		{
			if (level <= 0)
			{
				return 1f;
			}
			return level switch
			{
				1 => 23f / 30f, 
				2 => 0.7083334f, 
				_ => 0.65f, 
			};
		}
	}
	public sealed class CartAttunement
	{
		private readonly Dictionary<int, string> owners = new Dictionary<int, string>();

		public int Observe(int cart, IEnumerable<string> handlers, Func<string, int> level)
		{
			string text = null;
			int num = 3;
			bool flag = false;
			foreach (string handler in handlers)
			{
				int num2 = ((!string.IsNullOrEmpty(handler)) ? Math.Min(3, level(handler)) : 0);
				if (num2 <= 0)
				{
					flag = true;
				}
				else if (text == null || num2 < num || (num2 == num && StringComparer.Ordinal.Compare(handler, text) < 0))
				{
					text = handler;
					num = num2;
				}
			}
			if (flag)
			{
				owners.Remove(cart);
				return 0;
			}
			if (text != null)
			{
				owners[cart] = text;
			}
			if (!owners.TryGetValue(cart, out var value))
			{
				return 0;
			}
			int num3 = Math.Min(3, level(value));
			if (num3 <= 0)
			{
				owners.Remove(cart);
			}
			return Math.Max(0, num3);
		}

		public void Remove(int cart)
		{
			owners.Remove(cart);
		}

		public void Clear()
		{
			owners.Clear();
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}