Decompiled source of Team Upgrades v0.2.1

BepInEx/plugins/team-upgrades/dev.lordfirespeed.team_upgrades.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using REPOLib.Modules;
using TeamUpgrades.Extensions;
using UnityEngine;
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: IgnoresAccessChecksTo("REPOLib")]
[assembly: AssemblyCompany("Lordfirespeed")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Team upgrades, done right. Vanilla upgrades only. Everyone should have this installed.")]
[assembly: AssemblyFileVersion("0.2.1.0")]
[assembly: AssemblyInformationalVersion("0.2.1+117ccaa58d35948ae343b438e8b0e3a488587a7f")]
[assembly: AssemblyProduct("Lordfirespeed's Team Upgrades")]
[assembly: AssemblyTitle("dev.lordfirespeed.team_upgrades")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/Lordfirespeed/repo-team-upgrades")]
[assembly: NeutralResourcesLanguage("en-GB")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace TeamUpgrades
{
	[BepInDependency("REPOLib", "2.1.0")]
	[BepInPlugin("dev.lordfirespeed.team_upgrades", "Lordfirespeed's Team Upgrades", "0.2.1")]
	public class Plugin : BaseUnityPlugin
	{
		private class Patches
		{
			[HarmonyPatch(typeof(StatsManager))]
			private static class StatsManagerPatches
			{
				[HarmonyPatch("PlayerAdd")]
				[HarmonyPostfix]
				private static void OnPlayerAdd_Postfix(StatsManager __instance, object[] __args)
				{
					if (!DoTeamUpgrades || !(__args[0] is string key))
					{
						return;
					}
					foreach (Dictionary<string, int> item in __instance.AllDictionariesWithPrefix("playerUpgrade"))
					{
						item[key] = item.Values.Max();
					}
				}
			}

			[HarmonyPatch(typeof(ItemUpgradePlayerHealth))]
			private static class ItemUpgradePlayerHealthPatches
			{
				[HarmonyPatch("Upgrade")]
				[HarmonyPrefix]
				private static bool Upgrade_Prefix(ref ItemUpgradePlayerHealth __instance)
				{
					TeamUpgradesManager.Instance?.ApplyUpgrade(__instance.itemToggle.GetTogglingPlayerSteamId(), "playerUpgradeHealth");
					return false;
				}
			}

			[HarmonyPatch(typeof(ItemUpgradePlayerEnergy))]
			private static class ItemUpgradePlayerEnergyPatches
			{
				[HarmonyPatch("Upgrade")]
				[HarmonyPrefix]
				private static bool Upgrade_Prefix(ref ItemUpgradePlayerEnergy __instance)
				{
					TeamUpgradesManager.Instance?.ApplyUpgrade(__instance.itemToggle.GetTogglingPlayerSteamId(), "playerUpgradeStamina");
					return false;
				}
			}

			[HarmonyPatch(typeof(ItemUpgradePlayerSprintSpeed))]
			private static class ItemUpgradePlayerSprintSpeedPatches
			{
				[HarmonyPatch("Upgrade")]
				[HarmonyPrefix]
				private static bool Upgrade_Prefix(ref ItemUpgradePlayerSprintSpeed __instance)
				{
					TeamUpgradesManager.Instance?.ApplyUpgrade(__instance.itemToggle.GetTogglingPlayerSteamId(), "playerUpgradeSpeed");
					return false;
				}
			}

			[HarmonyPatch(typeof(ItemUpgradePlayerGrabStrength))]
			private static class ItemUpgradePlayerGrabStrengthPatches
			{
				[HarmonyPatch("Upgrade")]
				[HarmonyPrefix]
				private static bool Upgrade_Prefix(ref ItemUpgradePlayerGrabStrength __instance)
				{
					TeamUpgradesManager.Instance?.ApplyUpgrade(__instance.itemToggle.GetTogglingPlayerSteamId(), "playerUpgradeStrength");
					return false;
				}
			}

			[HarmonyPatch(typeof(ItemUpgradePlayerGrabRange))]
			private static class ItemUpgradePlayerGrabRangePatches
			{
				[HarmonyPatch("Upgrade")]
				[HarmonyPrefix]
				private static bool Upgrade_Prefix(ref ItemUpgradePlayerGrabRange __instance)
				{
					TeamUpgradesManager.Instance?.ApplyUpgrade(__instance.itemToggle.GetTogglingPlayerSteamId(), "playerUpgradeRange");
					return false;
				}
			}

			[HarmonyPatch(typeof(ItemUpgradePlayerGrabThrow))]
			private static class ItemUpgradePlayerGrabThrowPatches
			{
				[HarmonyPatch("Upgrade")]
				[HarmonyPrefix]
				private static bool Upgrade_Prefix(ref ItemUpgradePlayerGrabThrow __instance)
				{
					TeamUpgradesManager.Instance?.ApplyUpgrade(__instance.itemToggle.GetTogglingPlayerSteamId(), "playerUpgradeThrow");
					return false;
				}
			}

			[HarmonyPatch(typeof(ItemUpgradePlayerTumbleLaunch))]
			private static class ItemUpgradePlayerTumbleLaunchPatches
			{
				[HarmonyPatch("Upgrade")]
				[HarmonyPrefix]
				private static bool Upgrade_Prefix(ref ItemUpgradePlayerTumbleLaunch __instance)
				{
					TeamUpgradesManager.Instance?.ApplyUpgrade(__instance.itemToggle.GetTogglingPlayerSteamId(), "playerUpgradeLaunch");
					return false;
				}
			}

			[HarmonyPatch(typeof(ItemUpgradePlayerExtraJump))]
			private static class ItemUpgradePlayerExtraJumpPatches
			{
				[HarmonyPatch("Upgrade")]
				[HarmonyPrefix]
				private static bool Upgrade_Prefix(ref ItemUpgradePlayerExtraJump __instance)
				{
					TeamUpgradesManager.Instance?.ApplyUpgrade(__instance.itemToggle.GetTogglingPlayerSteamId(), "playerUpgradeExtraJump");
					return false;
				}
			}

			[HarmonyPatch(typeof(ItemUpgradeMapPlayerCount))]
			private static class ItemUpgradeMapPlayerCountPatches
			{
				[HarmonyPatch("Upgrade")]
				[HarmonyPrefix]
				private static bool Upgrade_Prefix(ref ItemUpgradeMapPlayerCount __instance)
				{
					TeamUpgradesManager.Instance?.ApplyUpgrade(__instance.itemToggle.GetTogglingPlayerSteamId(), "playerUpgradeMapPlayerCount");
					return false;
				}
			}

			[HarmonyPatch(typeof(REPOLibItemUpgrade))]
			private static class REPOLibItemUpgradePatches
			{
				[HarmonyPatch("Upgrade")]
				[HarmonyPrefix]
				private static bool Upgrade_Prefix(ref REPOLibItemUpgrade __instance)
				{
					TeamUpgradesManager.Instance?.ApplyUpgrade(__instance._itemToggle.GetTogglingPlayerSteamId(), "playerUpgrade" + __instance.UpgradeId);
					return false;
				}
			}

			[HarmonyPatch(typeof(PhysGrabber))]
			private static class PhysGrabberPatches
			{
				[HarmonyPatch(/*Could not decode attribute arguments.*/)]
				[HarmonyTranspiler]
				private static IEnumerable<CodeInstruction> LateStart_MoveNext_Transpiler(IEnumerable<CodeInstruction> instructions)
				{
					//IL_0002: Unknown result type (might be due to invalid IL or missing references)
					//IL_0008: Expected O, but got Unknown
					//IL_0031: Unknown result type (might be due to invalid IL or missing references)
					//IL_0037: Expected O, but got Unknown
					//IL_0058: Unknown result type (might be due to invalid IL or missing references)
					//IL_005e: Expected O, but got Unknown
					//IL_006c: Unknown result type (might be due to invalid IL or missing references)
					//IL_0072: Expected O, but got Unknown
					//IL_0094: Unknown result type (might be due to invalid IL or missing references)
					//IL_009a: Expected O, but got Unknown
					//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
					//IL_00c1: Expected O, but got Unknown
					//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
					//IL_00e9: Expected O, but got Unknown
					//IL_014b: Unknown result type (might be due to invalid IL or missing references)
					//IL_0151: Expected O, but got Unknown
					//IL_0159: Unknown result type (might be due to invalid IL or missing references)
					//IL_015f: Expected O, but got Unknown
					//IL_017a: Unknown result type (might be due to invalid IL or missing references)
					//IL_0180: Expected O, but got Unknown
					//IL_019b: Unknown result type (might be due to invalid IL or missing references)
					//IL_01a1: Expected O, but got Unknown
					//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
					//IL_01af: Expected O, but got Unknown
					//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
					//IL_01bd: Expected O, but got Unknown
					//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
					//IL_01cb: Expected O, but got Unknown
					//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
					//IL_01de: Expected O, but got Unknown
					CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null);
					val.MatchForward(false, (CodeMatch[])(object)new CodeMatch[6]
					{
						new CodeMatch((OpCode?)OpCodes.Ldsfld, (object)typeof(StatsManager).GetField("instance"), (string)null),
						new CodeMatch((OpCode?)OpCodes.Ldfld, (object)typeof(StatsManager).GetField("playerUpgradeStrength"), (string)null),
						new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null),
						new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction instr) => instr.opcode == OpCodes.Ldfld), (string)null),
						new CodeMatch((OpCode?)OpCodes.Callvirt, (object)typeof(Dictionary<string, int>).GetMethod("ContainsKey"), (string)null),
						new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction instr) => instr.opcode == OpCodes.Brfalse), (string)null)
					});
					if (val.IsInvalid)
					{
						throw new InvalidOperationException();
					}
					if (!(val.InstructionAt(3).operand is FieldInfo fieldInfo))
					{
						throw new InvalidOperationException();
					}
					if (!(val.InstructionAt(5).operand is Label label))
					{
						throw new InvalidOperationException();
					}
					val.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[8]
					{
						new CodeInstruction(OpCodes.Ldarg_0, (object)null),
						new CodeInstruction(OpCodes.Ldloc_1, (object)null),
						new CodeInstruction(OpCodes.Ldfld, (object)typeof(PhysGrabber).GetField("playerAvatar")),
						new CodeInstruction(OpCodes.Call, (object)typeof(SemiFunc).GetMethod("PlayerGetSteamID")),
						new CodeInstruction(OpCodes.Stfld, (object)fieldInfo),
						new CodeInstruction(OpCodes.Ldarg_0, (object)null),
						new CodeInstruction(OpCodes.Ldfld, (object)fieldInfo),
						new CodeInstruction(OpCodes.Brfalse, (object)label)
					});
					CodeInstructionExtensions.MoveLabelsTo(val.Instruction, val.InstructionAt(-8));
					Logger.LogDebugInstructionsFrom(val);
					return val.InstructionEnumeration();
				}
			}
		}

		internal static readonly bool DoTeamUpgrades = true;

		internal const string MainScenePath = "Assets/Scenes/Main/Main.unity";

		internal static Plugin Instance { get; private set; } = null;


		internal static ManualLogSource Logger { get; private set; } = null;


		public Plugin()
		{
			if (Instance != null)
			{
				throw new InvalidOperationException(typeof(Plugin).AssemblyQualifiedName + " was instantiated twice");
			}
			Instance = this;
		}

		private void Awake()
		{
			//IL_0015: 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_0023: Expected O, but got Unknown
			//IL_002f: 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_003d: Expected O, but got Unknown
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Expected O, but got Unknown
			Logger = ((BaseUnityPlugin)this).Logger;
			GameObject val = new GameObject("TeamUpgradesPrefabContainer")
			{
				hideFlags = (HideFlags)61
			};
			val.SetActive(false);
			GameObject val2 = new GameObject("TeamUpgradesManagerPrefab")
			{
				hideFlags = (HideFlags)61
			};
			val2.transform.parent = val.transform;
			val2.AddComponent<PhotonView>();
			val2.AddComponent<TeamUpgradesManager>();
			string myPrefabId = "dev.lordfirespeed.team_upgrades/team-upgrades-manager";
			NetworkPrefabs.RegisterNetworkPrefab(myPrefabId, val2);
			SceneManager.sceneLoaded += delegate(Scene scene, LoadSceneMode loadSceneMode)
			{
				//IL_0038: 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)
				if (!(((Scene)(ref scene)).path != "Assets/Scenes/Main/Main.unity") && SemiFunc.IsMultiplayer() && SemiFunc.IsMasterClient() && !((Object)(object)TeamUpgradesManager.Instance != (Object)null))
				{
					PhotonNetwork.InstantiateRoomObject(myPrefabId, Vector3.zero, Quaternion.identity, (byte)0, (object[])null);
				}
			};
			HarmonyExtensions.PatchAllNestedTypes(new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID), typeof(Patches));
		}
	}
	public class TeamUpgradesManager : MonoBehaviour
	{
		private PhotonView _photonView;

		internal static TeamUpgradesManager? Instance { get; private set; }

		private static IEnumerable<string> AllPlayerSteamIds => StatsManager.instance.dictionaryOfDictionaries["playerColor"].Keys;

		public event EventHandler<UpgradeQuantityChangedEventArgs>? UpgradeQuantityChanged;

		private void Start()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			((Component)this).transform.parent = ((Component)PunManager.instance).transform;
			((Object)((Component)this).gameObject).name = "TeamUpgradesManager";
			GameObject gameObject = ((Component)this).gameObject;
			((Object)gameObject).hideFlags = (HideFlags)(((Object)gameObject).hideFlags & -62);
			_photonView = ((Component)this).GetComponent<PhotonView>();
			RegisterVanillaUpgradeQuantityChangedCallbacks();
			RegisterREPOLibUpgradeQuantityChangedCallbacks();
		}

		private void RegisterVanillaUpgradeQuantityChangedCallbacks()
		{
			UpgradeQuantityChanged += delegate(object sender, UpgradeQuantityChangedEventArgs args)
			{
				if (!(args.StatsKey != "playerUpgradeHealth") && args.IsLocalPlayer && args.NewQuantity != args.OldQuantity && Object.op_Implicit((Object)(object)args.PlayerAvatar))
				{
					int num5 = args.NewQuantity - args.OldQuantity;
					PlayerHealth playerHealth = args.PlayerAvatar.playerHealth;
					playerHealth.maxHealth += num5 * 20;
					if (num5 > 0)
					{
						args.PlayerAvatar.playerHealth.Heal(num5 * 20, false);
					}
				}
			};
			UpgradeQuantityChanged += delegate(object sender, UpgradeQuantityChangedEventArgs args)
			{
				if (!(args.StatsKey != "playerUpgradeStamina") && args.IsLocalPlayer && args.NewQuantity != args.OldQuantity && Object.op_Implicit((Object)(object)PlayerController.instance))
				{
					int num4 = args.NewQuantity - args.OldQuantity;
					PlayerController instance4 = PlayerController.instance;
					instance4.EnergyStart += (float)num4 * 10f;
					PlayerController.instance.EnergyCurrent = PlayerController.instance.EnergyStart;
				}
			};
			UpgradeQuantityChanged += delegate(object sender, UpgradeQuantityChangedEventArgs args)
			{
				if (!(args.StatsKey != "playerUpgradeSpeed") && args.IsLocalPlayer && args.NewQuantity != args.OldQuantity && Object.op_Implicit((Object)(object)PlayerController.instance))
				{
					int num3 = args.NewQuantity - args.OldQuantity;
					PlayerController instance2 = PlayerController.instance;
					instance2.SprintSpeed += (float)num3;
					PlayerController instance3 = PlayerController.instance;
					instance3.SprintSpeedUpgrades += (float)num3;
				}
			};
			UpgradeQuantityChanged += delegate(object sender, UpgradeQuantityChangedEventArgs args)
			{
				if (!(args.StatsKey != "playerUpgradeStrength") && Object.op_Implicit((Object)(object)args.PlayerAvatar) && args.NewQuantity != args.OldQuantity)
				{
					int num2 = args.NewQuantity - args.OldQuantity;
					PhysGrabber physGrabber3 = args.PlayerAvatar.physGrabber;
					physGrabber3.grabStrength += (float)num2 * 0.2f;
				}
			};
			UpgradeQuantityChanged += delegate(object sender, UpgradeQuantityChangedEventArgs args)
			{
				if (!(args.StatsKey != "playerUpgradeRange") && Object.op_Implicit((Object)(object)args.PlayerAvatar) && args.NewQuantity != args.OldQuantity)
				{
					PhysGrabber physGrabber2 = args.PlayerAvatar.physGrabber;
					physGrabber2.grabRange += (float)(args.NewQuantity - args.OldQuantity);
				}
			};
			UpgradeQuantityChanged += delegate(object sender, UpgradeQuantityChangedEventArgs args)
			{
				if (!(args.StatsKey != "playerUpgradeThrow") && Object.op_Implicit((Object)(object)args.PlayerAvatar) && args.NewQuantity != args.OldQuantity)
				{
					int num = args.NewQuantity - args.OldQuantity;
					PhysGrabber physGrabber = args.PlayerAvatar.physGrabber;
					physGrabber.throwStrength += (float)num * 0.3f;
				}
			};
			UpgradeQuantityChanged += delegate(object sender, UpgradeQuantityChangedEventArgs args)
			{
				if (!(args.StatsKey != "playerUpgradeLaunch") && args.NewQuantity != args.OldQuantity && Object.op_Implicit((Object)(object)args.PlayerAvatar))
				{
					PlayerTumble tumble = args.PlayerAvatar.tumble;
					tumble.tumbleLaunch += args.NewQuantity - args.OldQuantity;
				}
			};
			UpgradeQuantityChanged += delegate(object sender, UpgradeQuantityChangedEventArgs args)
			{
				if (!(args.StatsKey != "playerUpgradeExtraJump") && args.IsLocalPlayer && args.NewQuantity != args.OldQuantity && Object.op_Implicit((Object)(object)PlayerController.instance))
				{
					PlayerController instance = PlayerController.instance;
					instance.JumpExtra += args.NewQuantity - args.OldQuantity;
				}
			};
			UpgradeQuantityChanged += delegate(object sender, UpgradeQuantityChangedEventArgs args)
			{
				if (!(args.StatsKey != "playerUpgradeMapPlayerCount") && args.IsLocalPlayer && args.NewQuantity != args.OldQuantity && Object.op_Implicit((Object)(object)args.PlayerAvatar))
				{
					PlayerAvatar playerAvatar = args.PlayerAvatar;
					playerAvatar.upgradeMapPlayerCount += args.NewQuantity - args.OldQuantity;
				}
			};
		}

		private void RegisterREPOLibUpgradeQuantityChangedCallbacks()
		{
			UpgradeQuantityChanged += delegate(object sender, UpgradeQuantityChangedEventArgs args)
			{
				if (args.StatsKey.StartsWith("playerUpgrade"))
				{
					string statsKey = args.StatsKey;
					int length = "playerUpgrade".Length;
					PlayerUpgrade val = default(PlayerUpgrade);
					if (Upgrades.TryGetUpgrade(statsKey.Substring(length, statsKey.Length - length), ref val) && val._upgradeAction != null && Object.op_Implicit((Object)(object)args.PlayerAvatar))
					{
						val._upgradeAction(args.PlayerAvatar, args.NewQuantity);
					}
				}
			};
		}

		public void ApplyUpgrade(string playerSteamId, string playerUpgradeStatsKey)
		{
			if (!SemiFunc.IsMasterClient())
			{
				return;
			}
			Dictionary<string, int> valueOrDefault = StatsManager.instance.dictionaryOfDictionaries.GetValueOrDefault(playerUpgradeStatsKey, null);
			if (valueOrDefault != null)
			{
				if (Plugin.DoTeamUpgrades)
				{
					int num = valueOrDefault.Values.Max();
					AssignUpgradeQuantityToAllPlayers(playerUpgradeStatsKey, num + 1);
				}
				else
				{
					int num2 = valueOrDefault[playerSteamId];
					AssignUpgradeQuantity(playerSteamId, playerUpgradeStatsKey, num2 + 1);
				}
			}
		}

		public void AssignUpgradeQuantityImmediately(string playerSteamId, string playerUpgradeStatsKey, int quantity)
		{
			Dictionary<string, int> valueOrDefault = StatsManager.instance.dictionaryOfDictionaries.GetValueOrDefault(playerUpgradeStatsKey, null);
			if (valueOrDefault != null)
			{
				int oldQuantity = valueOrDefault[playerSteamId];
				valueOrDefault[playerSteamId] = quantity;
				UpgradeQuantityChangedEventArgs e = new UpgradeQuantityChangedEventArgs
				{
					PlayerSteamId = playerSteamId,
					StatsKey = playerUpgradeStatsKey,
					OldQuantity = oldQuantity,
					NewQuantity = quantity
				};
				this.UpgradeQuantityChanged?.Invoke(null, e);
			}
		}

		public void AssignUpgradeQuantity(string playerSteamId, string playerUpgradeStatsKey, int quantity)
		{
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				AssignUpgradeQuantityImmediately(playerSteamId, playerUpgradeStatsKey, quantity);
			}
			if (SemiFunc.IsMasterClient())
			{
				_photonView.RPC("AssignUpgradeQuantityRPC", (RpcTarget)1, new object[3] { playerSteamId, playerUpgradeStatsKey, quantity });
			}
		}

		[PunRPC]
		public void AssignUpgradeQuantityRPC(string playerSteamId, string playerUpgradeStatsKey, int quantity, PhotonMessageInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (info.Sender.IsMasterClient)
			{
				AssignUpgradeQuantityImmediately(playerSteamId, playerUpgradeStatsKey, quantity);
			}
		}

		public void AssignUpgradeQuantityToAllPlayersImmediately(string playerUpgradeStatsKey, int quantity)
		{
			Dictionary<string, int> valueOrDefault = StatsManager.instance.dictionaryOfDictionaries.GetValueOrDefault(playerUpgradeStatsKey, null);
			if (valueOrDefault == null)
			{
				return;
			}
			foreach (string allPlayerSteamId in AllPlayerSteamIds)
			{
				int oldQuantity = valueOrDefault[allPlayerSteamId];
				valueOrDefault[allPlayerSteamId] = quantity;
				UpgradeQuantityChangedEventArgs e = new UpgradeQuantityChangedEventArgs
				{
					PlayerSteamId = allPlayerSteamId,
					StatsKey = playerUpgradeStatsKey,
					OldQuantity = oldQuantity,
					NewQuantity = quantity
				};
				this.UpgradeQuantityChanged?.Invoke(null, e);
			}
		}

		public void AssignUpgradeQuantityToAllPlayers(string playerUpgradeStatsKey, int quantity)
		{
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				AssignUpgradeQuantityToAllPlayersImmediately(playerUpgradeStatsKey, quantity);
			}
			if (SemiFunc.IsMasterClient())
			{
				_photonView.RPC("AssignUpgradeQuantityToAllPlayersRPC", (RpcTarget)1, new object[2] { playerUpgradeStatsKey, quantity });
			}
		}

		[PunRPC]
		public void AssignUpgradeQuantityToAllPlayersRPC(string playerUpgradeStatsKey, int quantity, PhotonMessageInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (info.Sender.IsMasterClient)
			{
				AssignUpgradeQuantityToAllPlayersImmediately(playerUpgradeStatsKey, quantity);
			}
		}
	}
	public class UpgradeQuantityChangedEventArgs : EventArgs
	{
		public required string PlayerSteamId { get; init; }

		public required string StatsKey { get; init; }

		public required int OldQuantity { get; init; }

		public required int NewQuantity { get; init; }

		public PlayerAvatar PlayerAvatar => SemiFunc.PlayerAvatarGetFromSteamID(PlayerSteamId);

		public bool IsLocalPlayer => (Object)(object)PlayerAvatar == (Object)(object)SemiFunc.PlayerAvatarLocal();
	}
	internal static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "dev.lordfirespeed.team_upgrades";

		public const string PLUGIN_NAME = "Lordfirespeed's Team Upgrades";

		public const string PLUGIN_VERSION = "0.2.1";
	}
}
namespace TeamUpgrades.Extensions
{
	public static class HarmonyExtensions
	{
		public class SimpleEnumerator<T> : IEnumerable<T>, IEnumerable
		{
			public required IEnumerator<T> Enumerator { get; init; }

			public Action PrefixAction { get; init; } = delegate
			{
			};


			public Action PostfixAction { get; init; } = delegate
			{
			};


			public Action<T> PreItemAction { get; init; } = delegate
			{
			};


			public Action<T> PostItemAction { get; init; } = delegate
			{
			};


			public Func<T, T> ItemAction { get; init; } = (T item) => item;


			IEnumerator<T> IEnumerable<T>.GetEnumerator()
			{
				return _GetEnumerator();
			}

			IEnumerator IEnumerable.GetEnumerator()
			{
				return _GetEnumerator();
			}

			private IEnumerator<T> _GetEnumerator()
			{
				PrefixAction();
				while (Enumerator.MoveNext())
				{
					T item = Enumerator.Current;
					PreItemAction(item);
					yield return ItemAction(item);
					PostItemAction(item);
				}
				PostfixAction();
			}
		}

		private const BindingFlags SearchNestedTypeBindingFlags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

		private static Type[] AllNestedTypesOf(Type type)
		{
			return type.GetNestedTypes(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		}

		public static void PatchAllNestedTypes(this Harmony harmony, Type type)
		{
			Type[] array = AllNestedTypesOf(type);
			foreach (Type type2 in array)
			{
				harmony.PatchAll(type2);
			}
		}

		public static void PatchAllNestedTypesRecursively(this Harmony harmony, Type type)
		{
			Type[] array = AllNestedTypesOf(type);
			foreach (Type type2 in array)
			{
				harmony.PatchAll(type2);
				harmony.PatchAllNestedTypesRecursively(type2);
			}
		}
	}
	public static class ItemToggleExtensions
	{
		public static PlayerAvatar GetTogglingPlayerAvatar(this ItemToggle toggle)
		{
			return SemiFunc.PlayerAvatarGetFromPhotonID(toggle.playerTogglePhotonID);
		}

		public static string GetTogglingPlayerSteamId(this ItemToggle toggle)
		{
			return SemiFunc.PlayerGetSteamID(toggle.GetTogglingPlayerAvatar());
		}
	}
	public static class ManualLogSourceExtensions
	{
		private class CodeInstructionFormatter
		{
			private int _instructionIndexPadLength = instructionCount.ToString().Length;

			public CodeInstructionFormatter(int instructionCount)
			{
			}

			public string Format(CodeInstruction instruction, int index)
			{
				return $"    IL_{index.ToString().PadLeft(_instructionIndexPadLength, '0')}: {instruction}";
			}
		}

		public static void LogDebugInstructionsFrom(this ManualLogSource source, CodeMatcher matcher)
		{
			string name = new StackTrace().GetFrame(1).GetMethod().Name;
			CodeInstructionFormatter @object = new CodeInstructionFormatter(matcher.Length);
			StringBuilder stringBuilder = new StringBuilder("'" + name + "' Matcher Instructions:\n").AppendLine(string.Join("\n", matcher.InstructionEnumeration().Select(@object.Format))).AppendLine("End of matcher instructions.");
			source.LogDebug((object)stringBuilder.ToString());
		}
	}
}
namespace System.Diagnostics.CodeAnalysis
{
	[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ConstantExpectedAttribute : Attribute
	{
		public object? Min { get; set; }

		public object? Max { get; set; }
	}
	[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ExperimentalAttribute : Attribute
	{
		public string DiagnosticId { get; }

		public string? UrlFormat { get; set; }

		public ExperimentalAttribute(string diagnosticId)
		{
			DiagnosticId = diagnosticId;
		}
	}
	[AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class SetsRequiredMembersAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class StringSyntaxAttribute : Attribute
	{
		public const string CompositeFormat = "CompositeFormat";

		public const string DateOnlyFormat = "DateOnlyFormat";

		public const string DateTimeFormat = "DateTimeFormat";

		public const string EnumFormat = "EnumFormat";

		public const string GuidFormat = "GuidFormat";

		public const string Json = "Json";

		public const string NumericFormat = "NumericFormat";

		public const string Regex = "Regex";

		public const string TimeOnlyFormat = "TimeOnlyFormat";

		public const string TimeSpanFormat = "TimeSpanFormat";

		public const string Uri = "Uri";

		public const string Xml = "Xml";

		public string Syntax { get; }

		public object?[] Arguments { get; }

		public StringSyntaxAttribute(string syntax)
		{
			Syntax = syntax;
			Arguments = new object[0];
		}

		public StringSyntaxAttribute(string syntax, params object?[] arguments)
		{
			Syntax = syntax;
			Arguments = arguments;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class UnscopedRefAttribute : Attribute
	{
	}
}
namespace System.Runtime.Versioning
{
	[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class RequiresPreviewFeaturesAttribute : Attribute
	{
		public string? Message { get; }

		public string? Url { get; set; }

		public RequiresPreviewFeaturesAttribute()
		{
		}

		public RequiresPreviewFeaturesAttribute(string? message)
		{
			Message = message;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
	[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class CallerArgumentExpressionAttribute : Attribute
	{
		public string ParameterName { get; }

		public CallerArgumentExpressionAttribute(string parameterName)
		{
			ParameterName = parameterName;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class CollectionBuilderAttribute : Attribute
	{
		public Type BuilderType { get; }

		public string MethodName { get; }

		public CollectionBuilderAttribute(Type builderType, string methodName)
		{
			BuilderType = builderType;
			MethodName = methodName;
		}
	}
	[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class CompilerFeatureRequiredAttribute : Attribute
	{
		public const string RefStructs = "RefStructs";

		public const string RequiredMembers = "RequiredMembers";

		public string FeatureName { get; }

		public bool IsOptional { get; set; }

		public CompilerFeatureRequiredAttribute(string featureName)
		{
			FeatureName = featureName;
		}
	}
	[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class InterpolatedStringHandlerArgumentAttribute : Attribute
	{
		public string[] Arguments { get; }

		public InterpolatedStringHandlerArgumentAttribute(string argument)
		{
			Arguments = new string[1] { argument };
		}

		public InterpolatedStringHandlerArgumentAttribute(params string[] arguments)
		{
			Arguments = arguments;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class InterpolatedStringHandlerAttribute : Attribute
	{
	}
	[EditorBrowsable(EditorBrowsableState.Never)]
	[ExcludeFromCodeCoverage]
	internal static class IsExternalInit
	{
	}
	[AttributeUsage(AttributeTargets.Method, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ModuleInitializerAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class OverloadResolutionPriorityAttribute : Attribute
	{
		public int Priority { get; }

		public OverloadResolutionPriorityAttribute(int priority)
		{
			Priority = priority;
		}
	}
	[AttributeUsage(AttributeTargets.Parameter, Inherited = true, AllowMultiple = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ParamCollectionAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class RequiredMemberAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
	[EditorBrowsable(EditorBrowsableState.Never)]
	[ExcludeFromCodeCoverage]
	internal sealed class RequiresLocationAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event | AttributeTargets.Interface, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class SkipLocalsInitAttribute : Attribute
	{
	}
}