Decompiled source of Empress SharedUpgrades v2.5.0

EmpressSharedUpgrades.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
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 UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Empress")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("2.0.0.0")]
[assembly: AssemblyInformationalVersion("2.0.0+5f1b735e473ca4ccf3b383128fbebd889cb564da")]
[assembly: AssemblyProduct("EmpressSharedUpgrades")]
[assembly: AssemblyTitle("EmpressSharedUpgrades")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.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 Empress.SharedUpgrades
{
	internal static class RepOLibCompat
	{
		private readonly struct RemoteUpgradeState
		{
			internal readonly object? PlayerUpgrade;

			internal readonly string SourceSteamId;

			internal readonly int PreviousLevel;

			internal readonly int IncomingLevel;

			internal RemoteUpgradeState(object playerUpgrade, string sourceSteamId, int previousLevel, int incomingLevel)
			{
				PlayerUpgrade = playerUpgrade;
				SourceSteamId = sourceSteamId;
				PreviousLevel = previousLevel;
				IncomingLevel = incomingLevel;
			}
		}

		private static MethodInfo? _addLevelMethod;

		private static MethodInfo? _getLevelMethod;

		private static MethodInfo? _getUpgradeMethod;

		private static bool _installed;

		[ThreadStatic]
		private static bool _localGuard;

		internal static void Bootstrap(Harmony harmony)
		{
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Expected O, but got Unknown
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Expected O, but got Unknown
			//IL_018a: Expected O, but got Unknown
			if (_installed)
			{
				return;
			}
			Type type = AccessTools.TypeByName("REPOLib.Modules.PlayerUpgrade");
			if (type == null)
			{
				return;
			}
			_addLevelMethod = AccessTools.Method(type, "AddLevel", new Type[2]
			{
				typeof(PlayerAvatar),
				typeof(int)
			}, (Type[])null);
			_getLevelMethod = AccessTools.Method(type, "GetLevel", new Type[1] { typeof(string) }, (Type[])null);
			if (!(_addLevelMethod == null) && !(_getLevelMethod == null))
			{
				Type type2 = AccessTools.TypeByName("REPOLib.Modules.Upgrades");
				MethodInfo methodInfo = ((type2 == null) ? null : AccessTools.Method(type2, "HandleUpgradeEvent", new Type[1] { typeof(EventData) }, (Type[])null));
				_getUpgradeMethod = ((type2 == null) ? null : AccessTools.Method(type2, "GetUpgrade", new Type[1] { typeof(string) }, (Type[])null));
				harmony.Patch((MethodBase)_addLevelMethod, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(RepOLibCompat), "AddLevelPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				if (methodInfo != null)
				{
					harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.Method(typeof(RepOLibCompat), "HandleUpgradeEventPrefix", (Type[])null, (Type[])null)), new HarmonyMethod(AccessTools.Method(typeof(RepOLibCompat), "HandleUpgradeEventPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				_installed = true;
				EmpressSharedUpgradesPlugin.Log.LogInfo((object)"Empress SharedUpgrades enabled REPOLib compatibility.");
			}
		}

		private static void AddLevelPostfix(object __instance, PlayerAvatar playerAvatar, int amount)
		{
			if (__instance == null || (Object)(object)playerAvatar == (Object)null || amount == 0)
			{
				return;
			}
			MethodInfo addLevelMethod = _addLevelMethod;
			if (addLevelMethod == null || _localGuard || EmpressSharedUpgradesPlugin.Guard || !EmpressSharedUpgradesPlugin.CanShare() || MoreUpgradesTeamSharingEnabledFor(__instance))
			{
				return;
			}
			try
			{
				_localGuard = true;
				EmpressSharedUpgradesPlugin.Guard = true;
				string text = SemiFunc.PlayerGetSteamID(playerAvatar);
				if (string.IsNullOrEmpty(text))
				{
					return;
				}
				foreach (string item in EmpressSharedUpgradesPlugin.AllSteamIDs())
				{
					if (!string.Equals(item, text, StringComparison.Ordinal))
					{
						PlayerAvatar val = SemiFunc.PlayerAvatarGetFromSteamID(item);
						if (Object.op_Implicit((Object)(object)val))
						{
							addLevelMethod.Invoke(__instance, new object[2] { val, amount });
						}
					}
				}
			}
			catch (Exception arg)
			{
				EmpressSharedUpgradesPlugin.Log.LogWarning((object)$"Empress SharedUpgrades REPOLib mirror failed: {arg}");
			}
			finally
			{
				EmpressSharedUpgradesPlugin.Guard = false;
				_localGuard = false;
			}
			EmpressSharedUpgradesPlugin.SyncStatsIfHost();
		}

		private static void HandleUpgradeEventPrefix(EventData eventData, ref RemoteUpgradeState __state)
		{
			__state = default(RemoteUpgradeState);
			MethodInfo getUpgradeMethod = _getUpgradeMethod;
			if (!(getUpgradeMethod == null) && TryParseUpgradeEvent(eventData, out string upgradeId, out string sourceSteamId, out int level))
			{
				object obj = getUpgradeMethod.Invoke(null, new object[1] { upgradeId });
				if (obj != null)
				{
					__state = new RemoteUpgradeState(obj, sourceSteamId, GetLevel(obj, sourceSteamId), level);
				}
			}
		}

		private static void HandleUpgradeEventPostfix(RemoteUpgradeState __state)
		{
			if (__state.PlayerUpgrade == null || _localGuard || EmpressSharedUpgradesPlugin.Guard || !EmpressSharedUpgradesPlugin.CanShare())
			{
				return;
			}
			int num = __state.IncomingLevel - __state.PreviousLevel;
			if (num <= 0 || MoreUpgradesTeamSharingEnabledFor(__state.PlayerUpgrade))
			{
				return;
			}
			MethodInfo addLevelMethod = _addLevelMethod;
			if (addLevelMethod == null)
			{
				return;
			}
			try
			{
				_localGuard = true;
				EmpressSharedUpgradesPlugin.Guard = true;
				foreach (string item in EmpressSharedUpgradesPlugin.AllSteamIDs())
				{
					if (!string.Equals(item, __state.SourceSteamId, StringComparison.Ordinal))
					{
						PlayerAvatar val = SemiFunc.PlayerAvatarGetFromSteamID(item);
						if (Object.op_Implicit((Object)(object)val))
						{
							addLevelMethod.Invoke(__state.PlayerUpgrade, new object[2] { val, num });
						}
					}
				}
			}
			catch (Exception arg)
			{
				EmpressSharedUpgradesPlugin.Log.LogWarning((object)$"Empress SharedUpgrades REPOLib remote mirror failed: {arg}");
			}
			finally
			{
				EmpressSharedUpgradesPlugin.Guard = false;
				_localGuard = false;
			}
			EmpressSharedUpgradesPlugin.SyncStatsIfHost();
		}

		private static int GetLevel(object playerUpgrade, string steamId)
		{
			MethodInfo getLevelMethod = _getLevelMethod;
			if (getLevelMethod == null)
			{
				return 0;
			}
			return (getLevelMethod.Invoke(playerUpgrade, new object[1] { steamId }) is int num) ? num : 0;
		}

		private static bool TryParseUpgradeEvent(EventData eventData, out string upgradeId, out string sourceSteamId, out int level)
		{
			upgradeId = string.Empty;
			sourceSteamId = string.Empty;
			level = 0;
			object obj = ((eventData != null) ? eventData.CustomData : null);
			Hashtable val = (Hashtable)((obj is Hashtable) ? obj : null);
			if (val == null)
			{
				return false;
			}
			upgradeId = (val[(object)"UpgradeId"] as string) ?? string.Empty;
			sourceSteamId = (val[(object)"SteamId"] as string) ?? string.Empty;
			object obj2 = val[(object)"Level"];
			if (obj2 is int num)
			{
				level = num;
			}
			else if (obj2 is byte b)
			{
				level = b;
			}
			else if (obj2 is short num2)
			{
				level = num2;
			}
			else if (!int.TryParse(obj2?.ToString(), out level))
			{
				return false;
			}
			return !string.IsNullOrEmpty(upgradeId) && !string.IsNullOrEmpty(sourceSteamId);
		}

		private static bool MoreUpgradesTeamSharingEnabledFor(object playerUpgrade)
		{
			try
			{
				Type type = AccessTools.TypeByName("MoreUpgrades.Plugin");
				if (type == null)
				{
					return false;
				}
				object obj = AccessTools.Field(type, "instance")?.GetValue(null);
				if (obj == null)
				{
					return false;
				}
				FieldInfo fieldInfo = AccessTools.Field(type, "upgradeItems");
				if (fieldInfo == null)
				{
					return false;
				}
				if (!(fieldInfo.GetValue(obj) is IEnumerable enumerable))
				{
					return false;
				}
				foreach (object item in enumerable)
				{
					if (item == null)
					{
						continue;
					}
					object obj2 = AccessTools.Field(item.GetType(), "playerUpgrade")?.GetValue(item);
					if (obj2 != playerUpgrade)
					{
						continue;
					}
					MethodInfo methodInfo = AccessTools.Method(item.GetType(), "HasConfig", new Type[1] { typeof(string) }, (Type[])null);
					if (methodInfo == null)
					{
						return false;
					}
					if (!(bool)methodInfo.Invoke(item, new object[1] { "Allow Team Upgrades" }))
					{
						return false;
					}
					MethodInfo methodInfo2 = AccessTools.Method(item.GetType(), "GetConfig", new Type[1] { typeof(string) }, (Type[])null);
					if (methodInfo2 == null)
					{
						return false;
					}
					MethodInfo methodInfo3 = methodInfo2.MakeGenericMethod(typeof(bool));
					return (bool)methodInfo3.Invoke(item, new object[1] { "Allow Team Upgrades" });
				}
			}
			catch
			{
				return false;
			}
			return false;
		}
	}
	[BepInPlugin("Empress.Empress_SharedUpgrades", "Empress SharedUpgrades", "2.0.0")]
	public sealed class EmpressSharedUpgradesPlugin : BaseUnityPlugin
	{
		internal const string PluginGuid = "Empress.Empress_SharedUpgrades";

		internal const string PluginName = "Empress SharedUpgrades";

		internal const string PluginVersion = "2.0.0";

		internal static bool Guard;

		internal static readonly VanillaUpgradeSpec Health = new VanillaUpgradeSpec("playerUpgradeHealth", "Health", delegate(PunManager punManager, string steamId, int amount)
		{
			punManager.UpgradePlayerHealth(steamId, amount);
		});

		internal static readonly VanillaUpgradeSpec Energy = new VanillaUpgradeSpec("playerUpgradeStamina", "Stamina", delegate(PunManager punManager, string steamId, int amount)
		{
			punManager.UpgradePlayerEnergy(steamId, amount);
		});

		internal static readonly VanillaUpgradeSpec ExtraJump = new VanillaUpgradeSpec("playerUpgradeExtraJump", "ExtraJump", delegate(PunManager punManager, string steamId, int amount)
		{
			punManager.UpgradePlayerExtraJump(steamId, amount);
		});

		internal static readonly VanillaUpgradeSpec MapPlayerCount = new VanillaUpgradeSpec("playerUpgradeMapPlayerCount", "MapPlayerCount", delegate(PunManager punManager, string steamId, int amount)
		{
			punManager.UpgradeMapPlayerCount(steamId, amount);
		});

		internal static readonly VanillaUpgradeSpec SprintSpeed = new VanillaUpgradeSpec("playerUpgradeSpeed", "Speed", delegate(PunManager punManager, string steamId, int amount)
		{
			punManager.UpgradePlayerSprintSpeed(steamId, amount);
		});

		internal static readonly VanillaUpgradeSpec GrabStrength = new VanillaUpgradeSpec("playerUpgradeStrength", "Strength", delegate(PunManager punManager, string steamId, int amount)
		{
			punManager.UpgradePlayerGrabStrength(steamId, amount);
		});

		internal static readonly VanillaUpgradeSpec ThrowStrength = new VanillaUpgradeSpec("playerUpgradeThrow", "Throw", delegate(PunManager punManager, string steamId, int amount)
		{
			punManager.UpgradePlayerThrowStrength(steamId, amount);
		});

		internal static readonly VanillaUpgradeSpec GrabRange = new VanillaUpgradeSpec("playerUpgradeRange", "Range", delegate(PunManager punManager, string steamId, int amount)
		{
			punManager.UpgradePlayerGrabRange(steamId, amount);
		});

		internal static readonly VanillaUpgradeSpec CrouchRest = new VanillaUpgradeSpec("playerUpgradeCrouchRest", "CrouchRest", delegate(PunManager punManager, string steamId, int amount)
		{
			punManager.UpgradePlayerCrouchRest(steamId, amount);
		});

		internal static readonly VanillaUpgradeSpec TumbleClimb = new VanillaUpgradeSpec("playerUpgradeTumbleClimb", "TumbleClimb", delegate(PunManager punManager, string steamId, int amount)
		{
			punManager.UpgradePlayerTumbleClimb(steamId, amount);
		});

		internal static readonly VanillaUpgradeSpec TumbleLaunch = new VanillaUpgradeSpec("playerUpgradeLaunch", "Launch", delegate(PunManager punManager, string steamId, int amount)
		{
			punManager.UpgradePlayerTumbleLaunch(steamId, amount);
		});

		internal static readonly VanillaUpgradeSpec TumbleWings = new VanillaUpgradeSpec("playerUpgradeTumbleWings", "TumbleWings", delegate(PunManager punManager, string steamId, int amount)
		{
			punManager.UpgradePlayerTumbleWings(steamId, amount);
		});

		private static readonly VanillaUpgradeSpec[] VanillaUpgrades = new VanillaUpgradeSpec[12]
		{
			Health, Energy, ExtraJump, MapPlayerCount, SprintSpeed, GrabStrength, ThrowStrength, GrabRange, CrouchRest, TumbleClimb,
			TumbleLaunch, TumbleWings
		};

		private static readonly HashSet<string> VanillaDictionaryNames = new HashSet<string>(StringComparer.Ordinal)
		{
			Health.DictionaryName, Energy.DictionaryName, ExtraJump.DictionaryName, MapPlayerCount.DictionaryName, SprintSpeed.DictionaryName, GrabStrength.DictionaryName, ThrowStrength.DictionaryName, GrabRange.DictionaryName, CrouchRest.DictionaryName, TumbleClimb.DictionaryName,
			TumbleLaunch.DictionaryName, TumbleWings.DictionaryName
		};

		private static readonly HashSet<int> QueuedLateJoinSyncViewIds = new HashSet<int>();

		private Harmony? _harmony;

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


		internal static ManualLogSource Log => ((BaseUnityPlugin)Instance).Logger;

		private void Awake()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			Instance = this;
			((Component)this).transform.parent = null;
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			_harmony = new Harmony("Empress.Empress_SharedUpgrades");
			_harmony.PatchAll();
			RepOLibCompat.Bootstrap(_harmony);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Empress SharedUpgrades v2.0.0 loaded");
		}

		internal static bool Ready()
		{
			if (SemiFunc.MenuLevel())
			{
				return false;
			}
			if ((Object)(object)LevelGenerator.Instance == (Object)null || !LevelGenerator.Instance.Generated)
			{
				return false;
			}
			return Object.op_Implicit((Object)(object)SemiFunc.PlayerAvatarLocal());
		}

		internal static bool CanShare()
		{
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				return false;
			}
			if (SemiFunc.IsMultiplayer() && (!PhotonNetwork.IsConnected || !PhotonNetwork.InRoom))
			{
				return false;
			}
			return Ready();
		}

		internal static bool CanLateJoinSync()
		{
			if (!SemiFunc.IsMultiplayer())
			{
				return false;
			}
			if (!PhotonNetwork.IsMasterClient || !PhotonNetwork.IsConnected || !PhotonNetwork.InRoom)
			{
				return false;
			}
			if ((Object)(object)PunManager.instance == (Object)null || (Object)(object)StatsManager.instance == (Object)null || (Object)(object)RunManager.instance == (Object)null)
			{
				return false;
			}
			Level levelCurrent = RunManager.instance.levelCurrent;
			if ((Object)(object)levelCurrent == (Object)(object)RunManager.instance.levelMainMenu)
			{
				return false;
			}
			if ((Object)(object)levelCurrent == (Object)(object)RunManager.instance.levelRecording)
			{
				return false;
			}
			if ((Object)(object)levelCurrent == (Object)(object)RunManager.instance.levelSplashScreen)
			{
				return false;
			}
			return true;
		}

		internal static IEnumerable<string> AllSteamIDs()
		{
			if ((Object)(object)GameDirector.instance == (Object)null)
			{
				yield break;
			}
			List<PlayerAvatar> players = GameDirector.instance.PlayerList;
			if (players == null)
			{
				yield break;
			}
			foreach (PlayerAvatar player in players)
			{
				if (Object.op_Implicit((Object)(object)player))
				{
					string steamId = SemiFunc.PlayerGetSteamID(player);
					if (!string.IsNullOrEmpty(steamId))
					{
						yield return steamId;
					}
				}
			}
		}

		internal static void ShareVanilla(VanillaUpgradeSpec spec, string sourceSteamId, int amount)
		{
			if (amount == 0 || Guard || !CanShare())
			{
				return;
			}
			PunManager instance = PunManager.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			Guard = true;
			try
			{
				foreach (string item in AllSteamIDs())
				{
					if (!string.Equals(item, sourceSteamId, StringComparison.Ordinal))
					{
						spec.ApplyLocal(instance, item, amount);
						if (SemiFunc.IsMultiplayer() && (Object)(object)instance.photonView != (Object)null)
						{
							instance.photonView.RPC("TesterUpgradeCommandRPC", (RpcTarget)1, new object[3] { item, spec.CommandName, amount });
						}
					}
				}
			}
			finally
			{
				Guard = false;
			}
			SyncStatsIfHost();
		}

		internal static void SyncStatsIfHost()
		{
			if (SemiFunc.IsMultiplayer() && PhotonNetwork.IsMasterClient && PhotonNetwork.IsConnected && PhotonNetwork.InRoom && !((Object)(object)PunManager.instance == (Object)null) && !((Object)(object)StatsManager.instance == (Object)null))
			{
				SemiFunc.StatSyncAll();
			}
		}

		internal static void QueueLateJoinSync(PlayerAvatar playerAvatar)
		{
			if (!((Object)(object)Instance == (Object)null) && !((Object)(object)playerAvatar == (Object)null) && SemiFunc.IsMultiplayer() && PhotonNetwork.IsMasterClient && PhotonNetwork.IsConnected && PhotonNetwork.InRoom && !((Object)(object)playerAvatar.photonView == (Object)null))
			{
				int viewID = playerAvatar.photonView.ViewID;
				if (QueuedLateJoinSyncViewIds.Add(viewID))
				{
					((MonoBehaviour)Instance).StartCoroutine(LateJoinSync(playerAvatar, viewID));
				}
			}
		}

		private static IEnumerator LateJoinSync(PlayerAvatar playerAvatar, int viewId)
		{
			try
			{
				while ((Object)(object)playerAvatar != (Object)null && SemiFunc.IsMultiplayer() && PhotonNetwork.IsMasterClient && PhotonNetwork.IsConnected && PhotonNetwork.InRoom)
				{
					if ((Object)(object)RunManager.instance != (Object)null)
					{
						Level currentLevel = RunManager.instance.levelCurrent;
						if ((Object)(object)currentLevel == (Object)(object)RunManager.instance.levelMainMenu || (Object)(object)currentLevel == (Object)(object)RunManager.instance.levelRecording || (Object)(object)currentLevel == (Object)(object)RunManager.instance.levelSplashScreen)
						{
							break;
						}
					}
					if ((Object)(object)PunManager.instance == (Object)null || (Object)(object)StatsManager.instance == (Object)null || (Object)(object)LevelGenerator.Instance == (Object)null || !LevelGenerator.Instance.Generated)
					{
						yield return null;
						continue;
					}
					if (!playerAvatar.levelAnimationCompleted)
					{
						yield return null;
						continue;
					}
					string targetSteamId = SemiFunc.PlayerGetSteamID(playerAvatar);
					if (string.IsNullOrEmpty(targetSteamId))
					{
						yield return null;
						continue;
					}
					PunManager punManager = PunManager.instance;
					StatsManager statsManager = StatsManager.instance;
					if ((Object)(object)punManager == (Object)null || (Object)(object)statsManager == (Object)null)
					{
						yield return null;
						continue;
					}
					bool changed = false;
					Guard = true;
					try
					{
						VanillaUpgradeSpec[] vanillaUpgrades = VanillaUpgrades;
						for (int i = 0; i < vanillaUpgrades.Length; i++)
						{
							VanillaUpgradeSpec spec = vanillaUpgrades[i];
							if (!statsManager.dictionaryOfDictionaries.TryGetValue(spec.DictionaryName, out var dictionary))
							{
								continue;
							}
							int targetLevel = GetLevel(dictionary, targetSteamId);
							int teamLevel = GetTeamLevel(dictionary, targetSteamId);
							int missingLevels = teamLevel - targetLevel;
							if (missingLevels > 0)
							{
								spec.ApplyLocal(punManager, targetSteamId, missingLevels);
								if ((Object)(object)punManager.photonView != (Object)null)
								{
									punManager.photonView.RPC("TesterUpgradeCommandRPC", (RpcTarget)1, new object[3] { targetSteamId, spec.CommandName, missingLevels });
								}
								changed = true;
								dictionary = null;
							}
						}
						foreach (KeyValuePair<string, Dictionary<string, int>> entry in statsManager.dictionaryOfDictionaries)
						{
							if (!entry.Key.StartsWith("playerUpgrade", StringComparison.Ordinal) || VanillaDictionaryNames.Contains(entry.Key))
							{
								continue;
							}
							int targetLevel2 = GetLevel(entry.Value, targetSteamId);
							int teamLevel2 = GetTeamLevel(entry.Value, targetSteamId);
							if (teamLevel2 > targetLevel2)
							{
								entry.Value[targetSteamId] = teamLevel2;
								if ((Object)(object)punManager.photonView != (Object)null)
								{
									punManager.photonView.RPC("UpdateStatRPC", (RpcTarget)1, new object[3] { entry.Key, targetSteamId, teamLevel2 });
								}
								changed = true;
							}
						}
					}
					finally
					{
						Guard = false;
					}
					if (changed)
					{
						SyncStatsIfHost();
					}
					break;
				}
			}
			finally
			{
				QueuedLateJoinSyncViewIds.Remove(viewId);
			}
		}

		private static int GetLevel(Dictionary<string, int> dictionary, string steamId)
		{
			if (dictionary.TryGetValue(steamId, out var value))
			{
				return value;
			}
			return 0;
		}

		private static int GetTeamLevel(Dictionary<string, int> dictionary, string excludedSteamId = "")
		{
			int num = 0;
			foreach (string item in AllSteamIDs())
			{
				if ((string.IsNullOrEmpty(excludedSteamId) || !string.Equals(item, excludedSteamId, StringComparison.Ordinal)) && dictionary.TryGetValue(item, out var value) && value > num)
				{
					num = value;
				}
			}
			return num;
		}
	}
	internal readonly struct VanillaUpgradeSpec
	{
		internal readonly string DictionaryName;

		internal readonly string CommandName;

		internal readonly Action<PunManager, string, int> ApplyLocal;

		internal VanillaUpgradeSpec(string dictionaryName, string commandName, Action<PunManager, string, int> applyLocal)
		{
			DictionaryName = dictionaryName;
			CommandName = commandName;
			ApplyLocal = applyLocal;
		}
	}
	[HarmonyPatch(typeof(PlayerAvatar), "AddToStatsManagerRPC")]
	internal static class Patch_PlayerAvatar_AddToStatsManagerRPC
	{
		private static void Postfix(PlayerAvatar __instance)
		{
			EmpressSharedUpgradesPlugin.QueueLateJoinSync(__instance);
		}
	}
	[HarmonyPatch(typeof(PlayerAvatar), "LoadingLevelAnimationCompletedRPC")]
	internal static class Patch_PlayerAvatar_LoadingLevelAnimationCompletedRPC
	{
		private static void Postfix(PlayerAvatar __instance)
		{
			EmpressSharedUpgradesPlugin.QueueLateJoinSync(__instance);
		}
	}
	internal static class VanillaUpgradePatchHelper
	{
		internal static void Capture(Dictionary<string, int> dictionary, string steamId, ref int state)
		{
			state = 0;
			dictionary.TryGetValue(steamId, out state);
		}

		internal static void Share(VanillaUpgradeSpec spec, string steamId, int result, int previous)
		{
			int num = result - previous;
			if (num != 0)
			{
				EmpressSharedUpgradesPlugin.ShareVanilla(spec, steamId, num);
			}
		}
	}
	[HarmonyPatch(typeof(PunManager), "UpgradePlayerHealth")]
	internal static class Patch_UpgradePlayerHealth
	{
		private static void Prefix(string _steamID, ref int __state)
		{
			VanillaUpgradePatchHelper.Capture(StatsManager.instance.playerUpgradeHealth, _steamID, ref __state);
		}

		private static void Postfix(string _steamID, int __result, int __state)
		{
			VanillaUpgradePatchHelper.Share(EmpressSharedUpgradesPlugin.Health, _steamID, __result, __state);
		}
	}
	[HarmonyPatch(typeof(PunManager), "UpgradePlayerEnergy")]
	internal static class Patch_UpgradePlayerEnergy
	{
		private static void Prefix(string _steamID, ref int __state)
		{
			VanillaUpgradePatchHelper.Capture(StatsManager.instance.playerUpgradeStamina, _steamID, ref __state);
		}

		private static void Postfix(string _steamID, int __result, int __state)
		{
			VanillaUpgradePatchHelper.Share(EmpressSharedUpgradesPlugin.Energy, _steamID, __result, __state);
		}
	}
	[HarmonyPatch(typeof(PunManager), "UpgradePlayerExtraJump")]
	internal static class Patch_UpgradePlayerExtraJump
	{
		private static void Prefix(string _steamID, ref int __state)
		{
			VanillaUpgradePatchHelper.Capture(StatsManager.instance.playerUpgradeExtraJump, _steamID, ref __state);
		}

		private static void Postfix(string _steamID, int __result, int __state)
		{
			VanillaUpgradePatchHelper.Share(EmpressSharedUpgradesPlugin.ExtraJump, _steamID, __result, __state);
		}
	}
	[HarmonyPatch(typeof(PunManager), "UpgradeMapPlayerCount")]
	internal static class Patch_UpgradeMapPlayerCount
	{
		private static void Prefix(string _steamID, ref int __state)
		{
			VanillaUpgradePatchHelper.Capture(StatsManager.instance.playerUpgradeMapPlayerCount, _steamID, ref __state);
		}

		private static void Postfix(string _steamID, int __result, int __state)
		{
			VanillaUpgradePatchHelper.Share(EmpressSharedUpgradesPlugin.MapPlayerCount, _steamID, __result, __state);
		}
	}
	[HarmonyPatch(typeof(PunManager), "UpgradePlayerSprintSpeed")]
	internal static class Patch_UpgradePlayerSprintSpeed
	{
		private static void Prefix(string _steamID, ref int __state)
		{
			VanillaUpgradePatchHelper.Capture(StatsManager.instance.playerUpgradeSpeed, _steamID, ref __state);
		}

		private static void Postfix(string _steamID, int __result, int __state)
		{
			VanillaUpgradePatchHelper.Share(EmpressSharedUpgradesPlugin.SprintSpeed, _steamID, __result, __state);
		}
	}
	[HarmonyPatch(typeof(PunManager), "UpgradePlayerGrabStrength")]
	internal static class Patch_UpgradePlayerGrabStrength
	{
		private static void Prefix(string _steamID, ref int __state)
		{
			VanillaUpgradePatchHelper.Capture(StatsManager.instance.playerUpgradeStrength, _steamID, ref __state);
		}

		private static void Postfix(string _steamID, int __result, int __state)
		{
			VanillaUpgradePatchHelper.Share(EmpressSharedUpgradesPlugin.GrabStrength, _steamID, __result, __state);
		}
	}
	[HarmonyPatch(typeof(PunManager), "UpgradePlayerThrowStrength")]
	internal static class Patch_UpgradePlayerThrowStrength
	{
		private static void Prefix(string _steamID, ref int __state)
		{
			VanillaUpgradePatchHelper.Capture(StatsManager.instance.playerUpgradeThrow, _steamID, ref __state);
		}

		private static void Postfix(string _steamID, int __result, int __state)
		{
			VanillaUpgradePatchHelper.Share(EmpressSharedUpgradesPlugin.ThrowStrength, _steamID, __result, __state);
		}
	}
	[HarmonyPatch(typeof(PunManager), "UpgradePlayerGrabRange")]
	internal static class Patch_UpgradePlayerGrabRange
	{
		private static void Prefix(string _steamID, ref int __state)
		{
			VanillaUpgradePatchHelper.Capture(StatsManager.instance.playerUpgradeRange, _steamID, ref __state);
		}

		private static void Postfix(string _steamID, int __result, int __state)
		{
			VanillaUpgradePatchHelper.Share(EmpressSharedUpgradesPlugin.GrabRange, _steamID, __result, __state);
		}
	}
	[HarmonyPatch(typeof(PunManager), "UpgradePlayerCrouchRest")]
	internal static class Patch_UpgradePlayerCrouchRest
	{
		private static void Prefix(string _steamID, ref int __state)
		{
			VanillaUpgradePatchHelper.Capture(StatsManager.instance.playerUpgradeCrouchRest, _steamID, ref __state);
		}

		private static void Postfix(string _steamID, int __result, int __state)
		{
			VanillaUpgradePatchHelper.Share(EmpressSharedUpgradesPlugin.CrouchRest, _steamID, __result, __state);
		}
	}
	[HarmonyPatch(typeof(PunManager), "UpgradePlayerTumbleClimb")]
	internal static class Patch_UpgradePlayerTumbleClimb
	{
		private static void Prefix(string _steamID, ref int __state)
		{
			VanillaUpgradePatchHelper.Capture(StatsManager.instance.playerUpgradeTumbleClimb, _steamID, ref __state);
		}

		private static void Postfix(string _steamID, int __result, int __state)
		{
			VanillaUpgradePatchHelper.Share(EmpressSharedUpgradesPlugin.TumbleClimb, _steamID, __result, __state);
		}
	}
	[HarmonyPatch(typeof(PunManager), "UpgradePlayerTumbleLaunch")]
	internal static class Patch_UpgradePlayerTumbleLaunch
	{
		private static void Prefix(string _steamID, ref int __state)
		{
			VanillaUpgradePatchHelper.Capture(StatsManager.instance.playerUpgradeLaunch, _steamID, ref __state);
		}

		private static void Postfix(string _steamID, int __result, int __state)
		{
			VanillaUpgradePatchHelper.Share(EmpressSharedUpgradesPlugin.TumbleLaunch, _steamID, __result, __state);
		}
	}
	[HarmonyPatch(typeof(PunManager), "UpgradePlayerTumbleWings")]
	internal static class Patch_UpgradePlayerTumbleWings
	{
		private static void Prefix(string _steamID, ref int __state)
		{
			VanillaUpgradePatchHelper.Capture(StatsManager.instance.playerUpgradeTumbleWings, _steamID, ref __state);
		}

		private static void Postfix(string _steamID, int __result, int __state)
		{
			VanillaUpgradePatchHelper.Share(EmpressSharedUpgradesPlugin.TumbleWings, _steamID, __result, __state);
		}
	}
}