Decompiled source of ForceItemsEqualShare v1.3.3

ForceItemsEqualShare.dll

Decompiled 2 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using On.RoR2;
using R2API.Utils;
using RoR2;
using UnityEngine;
using UnityEngine.Networking;

[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("ForceItemsEqualShare")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+99841aa7cee2b3fde324f3917e6d78b122f878eb")]
[assembly: AssemblyProduct("ForceItemsEqualShare")]
[assembly: AssemblyTitle("ForceItemsEqualShare")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ForceItemsEqualShare;

[BepInDependency(/*Could not decode attribute arguments.*/)]
[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
[BepInPlugin("com.Mordrog.ForceItemsEqualShare", "ForceItemsEqualShare", "1.3.2")]
public class ForceItemsEqualSharePlugin : BaseUnityPlugin
{
	public const string ModVer = "1.3.2";

	public const string ModName = "ForceItemsEqualShare";

	public const string ModGuid = "com.Mordrog.ForceItemsEqualShare";

	public ForceItemsEqualSharePlugin()
	{
		InitConfig();
	}

	public void Awake()
	{
		((Component)this).gameObject.AddComponent<PickupItemsPermissionController>();
	}

	private void InitConfig()
	{
		PluginConfig.HowToHandleItemsDisproportion = ((BaseUnityPlugin)this).Config.Bind<HowToHandleItemsDisproportion>("Settings", "HowToHandleItemsDisproportion", HowToHandleItemsDisproportion.GiveRandomItemToLowestCostsPlayer, "Way to handle items disproportion between player with loweset and biggest item costs");
		PluginConfig.ItemsCostsDifferenceThresholdScale = ((BaseUnityPlugin)this).Config.Bind<float>("Settings", "ItemsCostsDifferenceThresholdScale", 0.3f, "The items costs difference threshold scale for player picking item against the player with the lowest number of items costs.\nToo many items formula: Clamp(PlayersItemsCost * ItemsCostsDifferenceThresholdScale, MinItemsCostsDifferenceThreshold, MaxItemsCostsDifferenceThreshold) <= PlayersItemsCost - LeastPlayerItemsCost\nHave to be between 0 and 1");
		PluginConfig.MinItemsCostsDifferenceThreshold = ((BaseUnityPlugin)this).Config.Bind<uint>("Settings", "MinItemsCostsDifferenceThreshold", 5u, "The min items costs difference threshold for player picking item against the player with the lowest number of items costs..\nHave to be equal or lesser then MaxItemsCostsDifferenceThreshold");
		PluginConfig.MaxItemsCostsDifferenceThreshold = ((BaseUnityPlugin)this).Config.Bind<uint>("Settings", "MaxItemsCostsDifferenceThreshold", 15u, "The max items costs difference threshold for player picking item against the player with the lowest number of items costs.\nHave to be equal or bigger then MinItemsCostsDifferenceThreshold");
		PluginConfig.WhiteItemsCost = ((BaseUnityPlugin)this).Config.Bind<uint>("Settings", "WhiteItemsCost", 1u, "Cost of white items");
		PluginConfig.GreenItemsCost = ((BaseUnityPlugin)this).Config.Bind<uint>("Settings", "GreenItemsCost", 2u, "Cost of green items");
		PluginConfig.RedItemsCost = ((BaseUnityPlugin)this).Config.Bind<uint>("Settings", "RedItemsCost", 4u, "Cost of red items");
		PluginConfig.BossItemsCost = ((BaseUnityPlugin)this).Config.Bind<uint>("Settings", "BossItemsCost", 2u, "Cost of boss items");
		PluginConfig.BlueItemsCost = ((BaseUnityPlugin)this).Config.Bind<uint>("Settings", "BlueItemsCost", 0u, "Cost of blue items");
		PluginConfig.WhiteItemBoostWeight = ((BaseUnityPlugin)this).Config.Bind<float>("Settings", "WhiteItemBoostWeight", 100f, "Weight which indicate chance of player being boosted with white item.\nHave to be between 0 and 100. Works only with GiveRandomItemToLowestCostsPlayer");
		PluginConfig.GreenItemBoostWeight = ((BaseUnityPlugin)this).Config.Bind<float>("Settings", "GreenItemBoostWeight", 20f, "Weight which indicate chance of player being boosted with green item.\nHave to be between 0 and 100. Works only with GiveRandomItemToLowestCostsPlayer");
		PluginConfig.RedItemBoostWeight = ((BaseUnityPlugin)this).Config.Bind<float>("Settings", "RedItemBoostWeight", 0f, "Weight which indicate chance of player being boosted with red item.\nHave to be between 0 and 100. Works only with GiveRandomItemToLowestCostsPlayer");
	}
}
public static class ChatHelper
{
	private const string RedColor = "ff0000";

	private const string GreenColor = "32cd32";

	private const string SilverColor = "c0c0c0";

	public static void PlayerHasTooManyItems(string userName)
	{
		//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_0022: Expected O, but got Unknown
		string baseToken = "<color=#ff0000>" + userName + " has too many items!</color> <color=#32cd32>Share by</color> <color=#c0c0c0>ping + Interact button.</color>";
		Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage
		{
			baseToken = baseToken
		});
	}

	public static void PlayerBoostedWithItem(string userName, string pickupToken, Color itemColor)
	{
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: 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_005c: Expected O, but got Unknown
		string baseToken = "<style=cEvent><noparse>" + userName + "</noparse> boosted with <color=#" + ColorUtility.ToHtmlStringRGB(itemColor) + ">" + (Language.GetString(pickupToken) ?? "???") + "</color>";
		Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage
		{
			baseToken = baseToken
		});
	}
}
public static class UsersHelper
{
	public static CharacterMaster GetUserMaster(CharacterBody body)
	{
		foreach (CharacterMaster item in PlayerCharacterMasterController.instances.Select((PlayerCharacterMasterController p) => p.master))
		{
			if ((Object)(object)item.GetBody() == (Object)(object)body)
			{
				return item;
			}
		}
		return null;
	}

	public static Interactor GetUserInteractor(NetworkUser user)
	{
		if (!Object.op_Implicit((Object)(object)user) || !Object.op_Implicit((Object)(object)user.master))
		{
			return null;
		}
		GameObject bodyObject = user.master.GetBodyObject();
		if (!Object.op_Implicit((Object)(object)bodyObject))
		{
			return null;
		}
		return bodyObject.GetComponent<InteractionDriver>().interactor;
	}

	public static IEnumerable<NetworkUser> GetAllUsers()
	{
		return NetworkUser.readOnlyInstancesList;
	}

	public static NetworkUser GetUser(CharacterMaster userMaster)
	{
		return ((IEnumerable<NetworkUser>)NetworkUser.readOnlyInstancesList).FirstOrDefault((Func<NetworkUser, bool>)((NetworkUser u) => (Object)(object)u.master == (Object)(object)userMaster));
	}

	public static NetworkUser GetUser(CharacterBody userBody)
	{
		return GetUser(GetUserMaster(userBody));
	}

	public static NetworkUser GetUser(Interactor userInteractor)
	{
		return GetUser((userInteractor != null) ? ((Component)userInteractor).GetComponent<CharacterBody>() : null);
	}

	public static NetworkUser GetUser(PingerController userPinger)
	{
		return GetUser((userPinger != null) ? ((Component)userPinger).GetComponent<CharacterMaster>() : null);
	}
}
public static class InventoryCostMath
{
	public static List<NetworkUser> GetUsersWithLessInventoryCosts(NetworkUser user)
	{
		List<NetworkUser> list = new List<NetworkUser>();
		int inventoryCost = GetInventoryCost(user);
		foreach (NetworkUser allUser in UsersHelper.GetAllUsers())
		{
			if (!((Object)(object)user == (Object)(object)allUser))
			{
				int inventoryCost2 = GetInventoryCost(allUser.master.inventory);
				if (inventoryCost - Math.Min(inventoryCost2, inventoryCost) >= GetInventoryDifferenceCostThreshold(inventoryCost))
				{
					list.Add(allUser);
				}
			}
		}
		return list;
	}

	public static (NetworkUser user, int cost) GetUserWithLeastInventoryCosts(bool ignoreDeadUsers = true)
	{
		int num = int.MaxValue;
		NetworkUser item = null;
		foreach (NetworkUser allUser in UsersHelper.GetAllUsers())
		{
			if (Object.op_Implicit((Object)(object)allUser.master) && Object.op_Implicit((Object)(object)allUser.master.inventory) && (!ignoreDeadUsers || !allUser.master.IsDeadAndOutOfLivesServer()))
			{
				int inventoryCost = GetInventoryCost(allUser.master.inventory);
				if (inventoryCost < num)
				{
					num = inventoryCost;
					item = allUser;
				}
			}
		}
		return (item, num);
	}

	public static int GetInventoryCost(NetworkUser user)
	{
		if (!Object.op_Implicit((Object)(object)user) || !Object.op_Implicit((Object)(object)user.master) || !Object.op_Implicit((Object)(object)user.master.inventory))
		{
			return 0;
		}
		return GetInventoryCost(user.master.inventory);
	}

	public static int GetInventoryCost(Inventory inventory)
	{
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: 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_004f: Unknown result type (might be due to invalid IL or missing references)
		int num = 0;
		foreach (ItemIndex itemIndex in inventory.itemAcquisitionOrder)
		{
			if (!Object.op_Implicit((Object)(object)PluginGlobals.IgnoredCalculationItems.Find((ItemDef i) => i.itemIndex == itemIndex)))
			{
				int itemCount = inventory.GetItemCount(itemIndex);
				num += ItemCostEvaluation.GetItemCostEvaluation(itemIndex, itemCount);
			}
		}
		return num;
	}

	public static bool CheckIfInventoryHasTooMuchInventoryCost(Inventory inventory)
	{
		return CheckIfInventoryCostExceedThreshold(GetInventoryCost(inventory));
	}

	public static bool CheckIfInventoryCostExceedThreshold(int inventoryCost)
	{
		int item = GetUserWithLeastInventoryCosts().cost;
		return inventoryCost - Math.Min(item, inventoryCost) >= GetInventoryDifferenceCostThreshold(inventoryCost);
	}

	public static int GetInventoryDifferenceCostThreshold(int inventoryCost)
	{
		int num = 0;
		if (PluginConfig.ItemsCostsDifferenceThresholdScale.Value >= 0f && PluginConfig.ItemsCostsDifferenceThresholdScale.Value <= 1f)
		{
			num = (int)((float)inventoryCost * PluginConfig.ItemsCostsDifferenceThresholdScale.Value);
		}
		if (PluginConfig.MinItemsCostsDifferenceThreshold.Value <= PluginConfig.MaxItemsCostsDifferenceThreshold.Value)
		{
			num = Math.Clamp(num, (int)PluginConfig.MinItemsCostsDifferenceThreshold.Value, (int)PluginConfig.MaxItemsCostsDifferenceThreshold.Value);
		}
		return num;
	}
}
public static class ItemCostEvaluation
{
	public static int GetItemCostEvaluation(ItemIndex item, int numberOfStacks = 1)
	{
		//IL_0001: 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)
		return numberOfStacks * GetItemTierCostEvaluation(ItemCatalog.GetItemDef(item).tier);
	}

	public static int GetItemTierCostEvaluation(ItemTier itemTier)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Expected I4, but got Unknown
		switch ((int)itemTier)
		{
		case 0:
		case 6:
			return (int)PluginConfig.WhiteItemsCost.Value;
		case 1:
		case 7:
			return (int)PluginConfig.GreenItemsCost.Value;
		case 2:
		case 8:
			return (int)PluginConfig.RedItemsCost.Value;
		case 4:
		case 9:
			return (int)PluginConfig.BossItemsCost.Value;
		case 3:
			return (int)PluginConfig.BlueItemsCost.Value;
		default:
			return 0;
		}
	}
}
public enum HowToHandleItemsDisproportion
{
	GiveRandomItemToLowestCostsPlayer,
	PreventBiggestCostsPlayerPickup
}
public class PickupItemsPermissionController : NetworkBehaviour
{
	private PrintedItemsWatcher printedItemsWatcher;

	private PingedItemsWatcher pingedItemsWatcher;

	public void Awake()
	{
		//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
		printedItemsWatcher = ((Component)this).gameObject.AddComponent<PrintedItemsWatcher>();
		pingedItemsWatcher = ((Component)this).gameObject.AddComponent<PingedItemsWatcher>();
		GenericPickupController.AttemptGrant += new hook_AttemptGrant(GenericPickupController_AttemptGrant);
		GenericPickupController.OnInteractionBegin += new hook_OnInteractionBegin(GenericPickupController_OnInteractionBegin);
	}

	private void GenericPickupController_OnInteractionBegin(orig_OnInteractionBegin orig, GenericPickupController self, Interactor activator)
	{
		//IL_000a: 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)
		if (!CheckIfCurrentStageQualifyForSharing() || !CheckIfItemQualifyForSharing(self.pickupIndex))
		{
			orig.Invoke(self, activator);
			return;
		}
		NetworkUser user = UsersHelper.GetUser(activator);
		if (printedItemsWatcher.CheckIfUserHasPrintedItems(user, self.pickupIndex) || CheckIfUserCanPickItem(user))
		{
			orig.Invoke(self, activator);
		}
		else if (PluginConfig.HowToHandleItemsDisproportion.Value == HowToHandleItemsDisproportion.GiveRandomItemToLowestCostsPlayer)
		{
			orig.Invoke(self, activator);
		}
		else if (pingedItemsWatcher.TryConsumeItemPingedByUser(user, self))
		{
			Interactor userInteractor = UsersHelper.GetUserInteractor(InventoryCostMath.GetUserWithLeastInventoryCosts().user);
			if (Object.op_Implicit((Object)(object)userInteractor))
			{
				self.OnInteractionBegin(userInteractor);
			}
		}
		else if (Object.op_Implicit((Object)(object)user))
		{
			ChatHelper.PlayerHasTooManyItems(user.userName);
		}
	}

	private void GenericPickupController_AttemptGrant(orig_AttemptGrant orig, GenericPickupController self, CharacterBody body)
	{
		//IL_000a: 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)
		if (!CheckIfCurrentStageQualifyForSharing() || !CheckIfItemQualifyForSharing(self.pickupIndex))
		{
			orig.Invoke(self, body);
			return;
		}
		NetworkUser user = UsersHelper.GetUser(body);
		if (printedItemsWatcher.TryConsumeUserPrintedItem(user, self.pickupIndex) || CheckIfUserCanPickItem(user))
		{
			orig.Invoke(self, body);
		}
		else
		{
			if (PluginConfig.HowToHandleItemsDisproportion.Value != 0)
			{
				return;
			}
			foreach (NetworkUser usersWithLessInventoryCost in InventoryCostMath.GetUsersWithLessInventoryCosts(user))
			{
				BoostUserWithRandomItem(usersWithLessInventoryCost);
			}
			orig.Invoke(self, body);
		}
	}

	private void BoostUserWithRandomItem(NetworkUser user)
	{
		//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e5->IL00e5: Incompatible stack types: O vs I4
		//IL_00df->IL00e5: Incompatible stack types: I4 vs O
		//IL_00df->IL00e5: Incompatible stack types: O vs I4
		if (!Object.op_Implicit((Object)(object)user) || !Object.op_Implicit((Object)(object)user.master) || !Object.op_Implicit((Object)(object)user.master.inventory))
		{
			return;
		}
		Inventory inventory = user.master.inventory;
		try
		{
			WeightedSelection<List<PickupIndex>> obj = new WeightedSelection<List<PickupIndex>>(8);
			obj.AddChoice(Run.instance.availableTier1DropList, Math.Clamp(PluginConfig.WhiteItemBoostWeight.Value, 0f, 100f));
			obj.AddChoice(Run.instance.availableTier2DropList, Math.Clamp(PluginConfig.GreenItemBoostWeight.Value, 0f, 100f));
			obj.AddChoice(Run.instance.availableTier3DropList, Math.Clamp(PluginConfig.RedItemBoostWeight.Value, 0f, 100f));
			List<PickupIndex> list = obj.Evaluate(Random.value);
			PickupDef pickupDef = PickupCatalog.GetPickupDef(list[Random.Range(0, list.Count)]);
			object obj2 = inventory;
			int num;
			if (pickupDef != null)
			{
				obj2 = pickupDef.itemIndex;
				num = (int)obj2;
			}
			else
			{
				num = -1;
				obj2 = num;
				num = (int)obj2;
			}
			((Inventory)num).GiveItem((ItemIndex)obj2, 1);
			ChatHelper.PlayerBoostedWithItem(user.userName, pickupDef.nameToken, pickupDef.baseColor);
		}
		catch (ArgumentException)
		{
		}
	}

	private bool CheckIfCurrentStageQualifyForSharing()
	{
		return !PluginGlobals.IgnoredStages.Contains(SceneCatalog.GetSceneDefForCurrentScene().baseSceneName);
	}

	private bool CheckIfItemQualifyForSharing(PickupIndex pickupIndex)
	{
		//IL_0007: 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_001e: Invalid comparison between Unknown and I4
		PickupDef pickupDef = PickupCatalog.GetPickupDef(pickupIndex);
		if ((int)pickupDef.itemIndex != -1 && !pickupDef.isLunar)
		{
			return !Object.op_Implicit((Object)(object)PluginGlobals.IgnoredPickupItems.Find((ItemDef i) => i.itemIndex == pickupDef.itemIndex));
		}
		return false;
	}

	private bool CheckIfUserCanPickItem(NetworkUser user)
	{
		if (!Object.op_Implicit((Object)(object)user) || !Object.op_Implicit((Object)(object)user.master))
		{
			return false;
		}
		Inventory inventory = user.master.inventory;
		if (Object.op_Implicit((Object)(object)inventory))
		{
			return !InventoryCostMath.CheckIfInventoryHasTooMuchInventoryCost(inventory);
		}
		return false;
	}
}
internal class PingedItemsWatcher : NetworkBehaviour
{
	private Dictionary<NetworkUserId, int> watchedPingedItems = new Dictionary<NetworkUserId, int>();

	public bool CheckIfItemPingedByUser(NetworkUser user, GenericPickupController pickupController)
	{
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		if (Object.op_Implicit((Object)(object)user))
		{
			if (watchedPingedItems.TryGetValue(user.id, out var value))
			{
				return value == ((Object)pickupController).GetInstanceID();
			}
			return false;
		}
		return false;
	}

	public bool TryConsumeItemPingedByUser(NetworkUser user, GenericPickupController pickupController)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		if (CheckIfItemPingedByUser(user, pickupController))
		{
			watchedPingedItems.Remove(user.id);
			return true;
		}
		return false;
	}

	public void Awake()
	{
		//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
		Run.OnDestroy += new hook_OnDestroy(Run_OnDestroy);
		Run.OnServerSceneChanged += new hook_OnServerSceneChanged(Run_OnServerSceneChanged);
		PingerController.SetCurrentPing += new hook_SetCurrentPing(PingerController_SetCurrentPing);
	}

	private void Run_OnDestroy(orig_OnDestroy orig, Run self)
	{
		orig.Invoke(self);
		watchedPingedItems.Clear();
	}

	private void Run_OnServerSceneChanged(orig_OnServerSceneChanged orig, Run self, string sceneName)
	{
		orig.Invoke(self, sceneName);
		watchedPingedItems.Clear();
	}

	private void PingerController_SetCurrentPing(orig_SetCurrentPing orig, PingerController self, PingInfo newPingInfo)
	{
		//IL_0002: 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_003a: Unknown result type (might be due to invalid IL or missing references)
		orig.Invoke(self, newPingInfo);
		NetworkUser user = UsersHelper.GetUser(self);
		GameObject targetGameObject = ((PingInfo)(ref newPingInfo)).targetGameObject;
		GenericPickupController val = ((targetGameObject != null) ? targetGameObject.GetComponent<GenericPickupController>() : null);
		if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)user))
		{
			watchedPingedItems[user.id] = ((Object)val).GetInstanceID();
		}
		else if (Object.op_Implicit((Object)(object)user))
		{
			watchedPingedItems.Remove(user.id);
		}
	}
}
public class PrintedItemsWatcher : NetworkBehaviour
{
	internal class PrintedItems
	{
		private SortedDictionary<ItemTier, uint> numberOfPrintedItemsByTier = new SortedDictionary<ItemTier, uint>();

		public bool HasAnyPrintedItemOfTier(ItemTier itemTier)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			if (numberOfPrintedItemsByTier.TryGetValue(itemTier, out var value))
			{
				return value != 0;
			}
			return false;
		}

		public void AddPrintedItem(ItemTier itemTier)
		{
			//IL_0001: 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_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: 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_0015: Unknown result type (might be due to invalid IL or missing references)
			if (HasAnyPrintedItemOfTier(itemTier))
			{
				numberOfPrintedItemsByTier[itemTier]++;
			}
			else
			{
				numberOfPrintedItemsByTier[itemTier] = 1u;
			}
		}

		public bool RemovePrintedItemIfExists(ItemTier itemTier)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: 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_0015: Unknown result type (might be due to invalid IL or missing references)
			if (HasAnyPrintedItemOfTier(itemTier))
			{
				numberOfPrintedItemsByTier[itemTier]--;
				return true;
			}
			return false;
		}
	}

	private Dictionary<NetworkUserId, PrintedItems> userPrintedItems = new Dictionary<NetworkUserId, PrintedItems>();

	public bool CheckIfUserHasPrintedItems(NetworkUser user, PickupIndex pickupIndex)
	{
		//IL_0000: 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_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_0023: Unknown result type (might be due to invalid IL or missing references)
		ItemTier tier = ItemCatalog.GetItemDef(PickupCatalog.GetPickupDef(pickupIndex).itemIndex).tier;
		return GetUserPrintedItems(user)?.HasAnyPrintedItemOfTier(tier) ?? false;
	}

	public bool TryConsumeUserPrintedItem(NetworkUser user, PickupIndex pickupIndex)
	{
		//IL_0000: 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_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_0023: Unknown result type (might be due to invalid IL or missing references)
		ItemTier tier = ItemCatalog.GetItemDef(PickupCatalog.GetPickupDef(pickupIndex).itemIndex).tier;
		return GetUserPrintedItems(user)?.RemovePrintedItemIfExists(tier) ?? false;
	}

	public void Awake()
	{
		//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
		Run.OnDestroy += new hook_OnDestroy(Run_OnDestroy);
		Run.OnServerSceneChanged += new hook_OnServerSceneChanged(Run_OnServerSceneChanged);
		PurchaseInteraction.OnInteractionBegin += new hook_OnInteractionBegin(PurchaseInteraction_OnInteractionBegin);
	}

	private void Run_OnDestroy(orig_OnDestroy orig, Run self)
	{
		orig.Invoke(self);
		userPrintedItems.Clear();
	}

	private void Run_OnServerSceneChanged(orig_OnServerSceneChanged orig, Run self, string sceneName)
	{
		orig.Invoke(self, sceneName);
		userPrintedItems.Clear();
	}

	private void PurchaseInteraction_OnInteractionBegin(orig_OnInteractionBegin orig, PurchaseInteraction self, Interactor activator)
	{
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: 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)
		orig.Invoke(self, activator);
		ShopTerminalBehavior component = ((Component)self).GetComponent<ShopTerminalBehavior>();
		NetworkUser user = UsersHelper.GetUser(activator);
		if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)user) && CheckIfCostTypeIsItem(self.costType))
		{
			if (!userPrintedItems.ContainsKey(user.id))
			{
				userPrintedItems[user.id] = new PrintedItems();
			}
			userPrintedItems[user.id].AddPrintedItem(component.itemTier);
		}
	}

	private PrintedItems GetUserPrintedItems(NetworkUser user)
	{
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		if (Object.op_Implicit((Object)(object)user) && userPrintedItems.TryGetValue(user.id, out var value))
		{
			return value;
		}
		return null;
	}

	private bool CheckIfCostTypeIsItem(CostTypeIndex costType)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: Invalid comparison between Unknown and I4
		//IL_0004: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Invalid comparison between Unknown and I4
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000a: Invalid comparison between Unknown and I4
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Invalid comparison between Unknown and I4
		if ((int)costType != 4 && (int)costType != 5 && (int)costType != 6)
		{
			return (int)costType == 10;
		}
		return true;
	}
}
public static class PluginConfig
{
	public static ConfigEntry<HowToHandleItemsDisproportion> HowToHandleItemsDisproportion;

	public static ConfigEntry<float> ItemsCostsDifferenceThresholdScale;

	public static ConfigEntry<float> WhiteItemBoostWeight;

	public static ConfigEntry<float> GreenItemBoostWeight;

	public static ConfigEntry<float> RedItemBoostWeight;

	public static ConfigEntry<uint> MinItemsCostsDifferenceThreshold;

	public static ConfigEntry<uint> MaxItemsCostsDifferenceThreshold;

	public static ConfigEntry<uint> WhiteItemsCost;

	public static ConfigEntry<uint> GreenItemsCost;

	public static ConfigEntry<uint> RedItemsCost;

	public static ConfigEntry<uint> BossItemsCost;

	public static ConfigEntry<uint> BlueItemsCost;
}
public static class PluginGlobals
{
	public static List<ItemDef> IgnoredCalculationItems = new List<ItemDef>
	{
		Items.ArtifactKey,
		Items.TitanGoldDuringTP,
		Items.TonicAffliction,
		Items.CaptainDefenseMatrix,
		Items.DrizzlePlayerHelper,
		Items.MonsoonPlayerHelper,
		Items.InvadingDoppelganger
	};

	public static List<ItemDef> IgnoredPickupItems = new List<ItemDef>
	{
		Items.ArtifactKey,
		Items.ExtraLifeConsumed,
		Items.TitanGoldDuringTP,
		Items.TonicAffliction,
		Items.CaptainDefenseMatrix,
		Items.ScrapWhite,
		Items.ScrapGreen,
		Items.ScrapRed,
		Items.ScrapYellow
	};

	public static List<string> IgnoredStages = new List<string> { "bazaar", "arena", "moon", "moon2" };
}