Decompiled source of SyncUpgrades v2.2.6

SyncUpgrades.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Concurrent;
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 BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using JetBrains.Annotations;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using REPOLib.Modules;
using SyncUpgrades.Core;
using SyncUpgrades.Core.Internal;
using UnityEngine;

[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("SyncUpgrades")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("2.2.6.0")]
[assembly: AssemblyInformationalVersion("2.2.6+560d41301aca3cc683bfddf7f157925c52b16e17")]
[assembly: AssemblyProduct("SyncUpgrades")]
[assembly: AssemblyTitle("SyncUpgrades")]
[assembly: AssemblyVersion("2.2.6.0")]
[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;
		}
	}
	internal static class IsExternalInit
	{
	}
	[AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Property, Inherited = false)]
	internal sealed class RequiredMemberAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = false)]
	internal sealed class CompilerFeatureRequiredAttribute : Attribute
	{
		internal CompilerFeatureRequiredAttribute(string featureName)
		{
		}
	}
}
namespace SyncUpgrades
{
	[BepInPlugin("TGO.SyncUpgrades", "Sync Upgrades", "2.2.6")]
	[BepInDependency("REPOLib", "2.1.0")]
	public class Entry : BaseUnityPlugin
	{
		private const string PluginName = "Sync Upgrades";

		private const string PluginVersion = "2.2.6";

		private const string PluginId = "TGO.SyncUpgrades";

		private static readonly Harmony Harmony = new Harmony("TGO.SyncUpgrades");

		internal static readonly ManualLogSource LogSource = Logger.CreateLogSource("Sync Upgrades");

		private static Entry? _instance;

		internal static ConfigFile BepConfig => ((BaseUnityPlugin)_instance).Config;

		private void Awake()
		{
			_instance = this;
			SyncManager.Init();
			Harmony.PatchAllSafe();
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)4;
			LogSource.LogInfo((object)"Sync Upgrades loaded!");
		}

		private void FixedUpdate()
		{
			SyncUtil.RunOneRPC();
		}
	}
}
namespace SyncUpgrades.Patches
{
	[HarmonyPatch(typeof(PunManager))]
	internal class PunManagerPatch
	{
		[HarmonyPrefix]
		[HarmonyWrapSafe]
		[IgnoreMethodPatchException]
		[HarmonyPatch("UpdateHealthRightAway", new Type[] { typeof(string) })]
		private static void UpdateHealthRightAway(PunManager __instance, PhotonView ___photonView, StatsManager ___statsManager, string _steamID)
		{
			UpgradeWrapper(__instance, ___photonView, ___statsManager, _steamID, SyncUtil.HealthId, "UpdateHealthRightAway");
		}

		[HarmonyPrefix]
		[HarmonyWrapSafe]
		[HarmonyPatch("UpdateEnergyRightAway", new Type[] { typeof(string) })]
		private static void UpdateEnergyRightAway(PunManager __instance, PhotonView ___photonView, StatsManager ___statsManager, string _steamID)
		{
			UpgradeWrapper(__instance, ___photonView, ___statsManager, _steamID, SyncUtil.StaminaId, "UpdateEnergyRightAway");
		}

		[HarmonyPrefix]
		[HarmonyWrapSafe]
		[HarmonyPatch("UpdateTumbleLaunchRightAway", new Type[] { typeof(string) })]
		private static void UpdateTumbleLaunchRightAway(PunManager __instance, PhotonView ___photonView, StatsManager ___statsManager, string _steamID)
		{
			UpgradeWrapper(__instance, ___photonView, ___statsManager, _steamID, SyncUtil.TumbleLaunchId, "UpdateTumbleLaunchRightAway");
		}

		[HarmonyPrefix]
		[HarmonyWrapSafe]
		[HarmonyPatch("UpdateSprintSpeedRightAway", new Type[] { typeof(string) })]
		private static void UpdateSprintSpeedRightAway(PunManager __instance, PhotonView ___photonView, StatsManager ___statsManager, string _steamID)
		{
			UpgradeWrapper(__instance, ___photonView, ___statsManager, _steamID, SyncUtil.SprintSpeedId, "UpdateSprintSpeedRightAway");
		}

		[HarmonyPrefix]
		[HarmonyWrapSafe]
		[HarmonyPatch("UpdateGrabStrengthRightAway", new Type[] { typeof(string) })]
		private static void UpdateGrabStrengthRightAway(PunManager __instance, PhotonView ___photonView, StatsManager ___statsManager, string _steamID)
		{
			UpgradeWrapper(__instance, ___photonView, ___statsManager, _steamID, SyncUtil.GrabStrengthId, "UpdateGrabStrengthRightAway");
		}

		[HarmonyPrefix]
		[HarmonyWrapSafe]
		[HarmonyPatch("UpdateThrowStrengthRightAway", new Type[] { typeof(string) })]
		private static void UpdateThrowStrengthRightAway(PunManager __instance, PhotonView ___photonView, StatsManager ___statsManager, string _steamID)
		{
			UpgradeWrapper(__instance, ___photonView, ___statsManager, _steamID, SyncUtil.ThrowStrengthId, "UpdateThrowStrengthRightAway");
		}

		[HarmonyPrefix]
		[HarmonyWrapSafe]
		[HarmonyPatch("UpdateGrabRangeRightAway", new Type[] { typeof(string) })]
		private static void UpdateGrabRangeRightAway(PunManager __instance, PhotonView ___photonView, StatsManager ___statsManager, string _steamID)
		{
			UpgradeWrapper(__instance, ___photonView, ___statsManager, _steamID, SyncUtil.GrabRangeId, "UpdateGrabRangeRightAway");
		}

		[HarmonyPrefix]
		[HarmonyWrapSafe]
		[HarmonyPatch("UpdateExtraJumpRightAway", new Type[] { typeof(string) })]
		private static void UpdateExtraJumpRightAway(PunManager __instance, PhotonView ___photonView, StatsManager ___statsManager, string _steamID)
		{
			UpgradeWrapper(__instance, ___photonView, ___statsManager, _steamID, SyncUtil.ExtraJumpId, "UpdateExtraJumpRightAway");
		}

		[HarmonyPrefix]
		[HarmonyWrapSafe]
		[HarmonyPatch("UpdateMapPlayerCountRightAway", new Type[] { typeof(string) })]
		private static void UpdateMapPlayerCountRightAway(PunManager __instance, PhotonView ___photonView, StatsManager ___statsManager, string _steamID)
		{
			UpgradeWrapper(__instance, ___photonView, ___statsManager, _steamID, SyncUtil.MapPlayerCountId, "UpdateMapPlayerCountRightAway");
		}

		[HarmonyPrefix]
		[HarmonyWrapSafe]
		[IgnoreMethodPatchException]
		[HarmonyPatch("UpdateTumbleWingsRightAway", new Type[] { typeof(string) })]
		private static void UpdateTumbleWingsRightAway(PunManager __instance, PhotonView ___photonView, StatsManager ___statsManager, string _steamID)
		{
			UpgradeWrapper(__instance, ___photonView, ___statsManager, _steamID, SyncUtil.TumbleWingsId, "UpdateTumbleWingsRightAway");
		}

		[HarmonyPrefix]
		[HarmonyWrapSafe]
		[IgnoreMethodPatchException]
		[HarmonyPatch("UpdateCrouchRestRightAway", new Type[] { typeof(string) })]
		private static void UpdateCrouchRestRightAway(PunManager __instance, PhotonView ___photonView, StatsManager ___statsManager, string _steamID)
		{
			UpgradeWrapper(__instance, ___photonView, ___statsManager, _steamID, SyncUtil.CrouchRestId, "UpdateCrouchRestRightAway");
		}

		private static void UpgradeWrapper(PunManager __instance, PhotonView ___photonView, StatsManager ___statsManager, string _steamID, UpgradeId upgrade, [CallerMemberName] string methodName = "Unknown Caller Method")
		{
			if (!SemiFunc.IsNotMasterClient())
			{
				SyncManager.PlayerConsumedUpgrade(new SyncBundle(new PunManagerWrapper(__instance), ___photonView, ___statsManager, _steamID), upgrade);
			}
		}
	}
	[HarmonyPatch(typeof(RunManager))]
	internal class RunManagerPatch
	{
		[HarmonyPostfix]
		[HarmonyWrapSafe]
		[HarmonyPatch("ChangeLevel")]
		private static void ChangeLevel(bool _completedLevel, bool _levelFailed, bool ___restarting)
		{
			if (!(SemiFunc.IsNotMasterClient() || _levelFailed))
			{
				SyncManager.SyncHostToAll();
			}
		}
	}
	[HarmonyPatch(typeof(StatsManager))]
	internal class StatsManagerPatch
	{
		[HarmonyPostfix]
		[HarmonyWrapSafe]
		[HarmonyPatch("PlayerAdd", new Type[]
		{
			typeof(string),
			typeof(string)
		})]
		private static void PlayerAdd(string _steamID, string _playerName)
		{
			if (!SemiFunc.IsNotMasterClient() && !SemiFunc.MenuLevel())
			{
				SyncManager.SyncHostToTarget(_steamID);
			}
		}
	}
	[HarmonyPatch(typeof(Upgrades))]
	internal class UpgradesPatch
	{
		[HarmonyPostfix]
		[HarmonyWrapSafe]
		[HarmonyPatch("HandleUpgradeEvent")]
		private static void HandleUpgradeEvent(EventData eventData)
		{
			if (SemiFunc.IsNotMasterClient())
			{
				return;
			}
			object customData = eventData.CustomData;
			Hashtable val = (Hashtable)((customData is Hashtable) ? customData : null);
			if (val != null)
			{
				string text = (string)val[(object)"UpgradeId"];
				string steamId = (string)val[(object)"SteamId"];
				int newLevel = (int)val[(object)"Level"];
				PlayerUpgrade val2 = default(PlayerUpgrade);
				if (Upgrades.TryGetUpgrade(text, ref val2))
				{
					string rawName = SyncUtil.FixKey(text);
					SyncManager.PlayerConsumedUpgrade(steamId, UpgradeId.New(rawName), newLevel);
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyWrapSafe]
		[HarmonyPatch("RaiseUpgradeEvent")]
		private static void RaiseUpgradeEvent(string upgradeId, string steamId, int level)
		{
			if (!SemiFunc.IsNotMasterClient() && !(steamId != SyncUtil.HostSteamId))
			{
				string rawName = SyncUtil.FixKey(upgradeId);
				SyncManager.PlayerConsumedUpgrade(steamId, UpgradeId.New(rawName), level);
			}
		}

		[HarmonyPostfix]
		[HarmonyWrapSafe]
		[HarmonyPatch("RegisterUpgrade", new Type[]
		{
			typeof(string),
			typeof(Item),
			typeof(Action<PlayerAvatar, int>),
			typeof(Action<PlayerAvatar, int>)
		})]
		public static void RegisterUpgrade(PlayerUpgrade? __result)
		{
			if (!SemiFunc.IsNotMasterClient() && __result != null)
			{
				SyncManager.RegisterModdedUpgrade(__result);
			}
		}
	}
}
namespace SyncUpgrades.Core
{
	internal static class Extensions
	{
		public static string SteamId(this PlayerAvatar avatar)
		{
			return SemiFunc.PlayerGetSteamID(avatar);
		}

		public static PhotonView GetView(this PunManager instance)
		{
			return ((Component)instance).GetComponent<PhotonView>();
		}

		public static string ToName(this UpgradeType key)
		{
			return SyncUtil.GetUpgradeName(key);
		}

		public static void LogRPC(this PhotonView view, string methodName, Player target, params object[] parameters)
		{
			SyncUtil.QueueRPC(view, methodName, target, parameters);
		}

		public static void LogRPC(this PhotonView view, string methodName, RpcTarget target, params object[] parameters)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			SyncUtil.QueueRPC(view, methodName, target, parameters);
		}
	}
	internal interface ISyncRequest
	{
		void Run();
	}
	public class PunManagerWrapper
	{
		[CompilerGenerated]
		private PunManager <manager>P;

		public static PunManagerWrapper instance => new PunManagerWrapper(PunManager.instance);

		public PunManagerWrapper(PunManager manager)
		{
			<manager>P = manager;
			base..ctor();
		}

		public PhotonView GetView()
		{
			return <manager>P.GetView();
		}

		public int UpgradePlayerTumbleWings(string steamId)
		{
			return <manager>P.UpgradePlayerTumbleWings(steamId);
		}

		public int UpgradePlayerCrouchRest(string steamId)
		{
			return <manager>P.UpgradePlayerCrouchRest(steamId);
		}

		public void SyncAllDictionaries()
		{
			<manager>P.SyncAllDictionaries();
		}

		public int UpgradePlayerHealth(string steamId)
		{
			return <manager>P.UpgradePlayerHealth(steamId);
		}

		public int UpgradePlayerEnergy(string steamId)
		{
			return <manager>P.UpgradePlayerEnergy(steamId);
		}

		public int UpgradePlayerExtraJump(string steamId)
		{
			return <manager>P.UpgradePlayerExtraJump(steamId);
		}

		public int UpgradePlayerTumbleLaunch(string steamId)
		{
			return <manager>P.UpgradePlayerTumbleLaunch(steamId);
		}

		public int UpgradeMapPlayerCount(string steamId)
		{
			return <manager>P.UpgradeMapPlayerCount(steamId);
		}

		public int UpgradePlayerSprintSpeed(string steamId)
		{
			return <manager>P.UpgradePlayerSprintSpeed(steamId);
		}

		public int UpgradePlayerGrabStrength(string steamId)
		{
			return <manager>P.UpgradePlayerGrabStrength(steamId);
		}

		public int UpgradePlayerGrabRange(string steamId)
		{
			return <manager>P.UpgradePlayerGrabRange(steamId);
		}

		public int UpgradePlayerThrowStrength(string steamId)
		{
			return <manager>P.UpgradePlayerThrowStrength(steamId);
		}
	}
	internal record PunRequest(PhotonView View, string MethodName, object Target, object[] Parameters) : ISyncRequest
	{
		public static PunRequest New(PhotonView view, string methodName, object target, object[] parameters)
		{
			return new PunRequest(view, methodName, target, parameters);
		}

		public void Run()
		{
		}
	}
	[PublicAPI]
	public record SyncBundle(PunManagerWrapper Manager, PhotonView View, StatsManager Stats, string SteamId)
	{
		private SyncBundle(PunManagerWrapper mgr, StatsManager sts, string sId)
			: this(mgr, mgr.GetView(), sts, sId)
		{
		}

		public override string ToString()
		{
			return SteamId;
		}

		public static SyncBundle Default(string steamId)
		{
			return new SyncBundle(PunManagerWrapper.instance, StatsManager.instance, steamId);
		}
	}
	[PublicAPI]
	public static class SyncManager
	{
		private const string Section = "Default Upgrades";

		private const string ModdedSection = "Modded Upgrades";

		private static ConfigEntry<bool> _syncHealth = Entry.BepConfig.Bind<bool>("Default Upgrades", "Health", true, "Sync Max Health");

		private static ConfigEntry<bool> _syncStamina = Entry.BepConfig.Bind<bool>("Default Upgrades", "Stamina", true, "Sync Max Stamina");

		private static ConfigEntry<bool> _syncExtraJump = Entry.BepConfig.Bind<bool>("Default Upgrades", "Extra Jump", true, "Sync Extra Jump");

		private static ConfigEntry<bool> _syncMapPlayerCount = Entry.BepConfig.Bind<bool>("Default Upgrades", "Map Player Count", true, "Sync Map Player Count");

		private static ConfigEntry<bool> _syncGrabRange = Entry.BepConfig.Bind<bool>("Default Upgrades", "Grab Range", true, "Sync Grab Range");

		private static ConfigEntry<bool> _syncGrabStrength = Entry.BepConfig.Bind<bool>("Default Upgrades", "Grab Strength", true, "Sync Grab Strength");

		private static ConfigEntry<bool> _syncThrowStrength = Entry.BepConfig.Bind<bool>("Default Upgrades", "Throw Strength", true, "Sync Throw Strength");

		private static ConfigEntry<bool> _syncSprintSpeed = Entry.BepConfig.Bind<bool>("Default Upgrades", "Sprint Speed", true, "Sync Sprint Speed");

		private static ConfigEntry<bool> _syncTumbleLaunch = Entry.BepConfig.Bind<bool>("Default Upgrades", "Tumble Launch", true, "Sync Tumble Launch");

		private static ConfigEntry<bool> _syncTumbleWings = Entry.BepConfig.Bind<bool>("Default Upgrades", "Tumble Wings", true, "Sync Tumble Wings");

		private static ConfigEntry<bool> _syncCrouchRest = Entry.BepConfig.Bind<bool>("Default Upgrades", "Crouch Rest", true, "Sync Crouch Rest");

		internal static ConcurrentDictionary<UpgradeId, ConfigEntry<bool>> registeredModdedUpgrades = new ConcurrentDictionary<UpgradeId, ConfigEntry<bool>>();

		internal static void Init()
		{
			foreach (PlayerUpgrade playerUpgrade in Upgrades.PlayerUpgrades)
			{
				RegisterModdedUpgrade(playerUpgrade);
			}
		}

		public static void RegisterModdedUpgrade(PlayerUpgrade upgrade)
		{
			UpgradeId upgradeId = UpgradeId.New(SyncUtil.FixKey(upgrade.UpgradeId));
			if (!registeredModdedUpgrades.ContainsKey(upgradeId))
			{
				registeredModdedUpgrades.TryAdd(upgradeId, Entry.BepConfig.Bind<bool>("Modded Upgrades", SyncUtil.TrimKey(upgradeId.RawName), true, "Sync " + upgradeId.RawName));
			}
		}

		public static void PlayerConsumedUpgrade(string steamId, UpgradeId upgrade, int newLevel)
		{
			PlayerConsumedUpgrade(SyncBundle.Default(steamId), upgrade, newLevel);
		}

		public static void PlayerConsumedUpgrade(SyncBundle bundle, UpgradeId upgrade, int newLevel = 0)
		{
			if (!ShouldSync(upgrade) || !(bundle.SteamId != SyncUtil.HostSteamId))
			{
				return;
			}
			if (newLevel > 0)
			{
				int valueOrDefault = SyncUtil.GetUpgrades(bundle.Stats, upgrade).GetValueOrDefault(SyncUtil.HostSteamId, 0);
				int num = newLevel - valueOrDefault;
				for (int i = 0; i < num; i++)
				{
					SyncUtil.CallUpdateFunction(bundle, SyncUtil.HostSteamId, upgrade);
				}
			}
			else
			{
				SyncUtil.CallUpdateFunction(bundle, SyncUtil.HostSteamId, upgrade);
			}
		}

		public static bool SyncHostToTarget(string targetSteamId)
		{
			SyncBundle bundle = SyncBundle.Default(targetSteamId);
			if (!SyncHostToTarget(bundle, SyncUtil.GetPlayer(targetSteamId)))
			{
				return false;
			}
			SyncUtil.SyncStatsDictionaryToAll(bundle);
			return true;
		}

		public static void SyncHostToAll()
		{
			SyncHostToAll(SyncBundle.Default(SyncUtil.HostSteamId));
		}

		public static void SyncHostToAll(SyncBundle bundle)
		{
			SyncBundle bundle2 = bundle;
			if ((from player in SemiFunc.PlayerGetAll().Where(NotHost).ToArray()
				select SyncHostToTarget(bundle2, player)).ToArray().Any())
			{
				SyncUtil.SyncStatsDictionaryToAll(bundle2);
			}
		}

		private static bool SyncHostToTarget(SyncBundle bundle, PlayerAvatar target)
		{
			return SyncFromSourceToTarget(bundle, SyncUtil.Local, target);
		}

		private static bool SyncFromSourceToTarget(SyncBundle bundle, PlayerAvatar source, PlayerAvatar target)
		{
			string text = source.SteamId();
			string text2 = target.SteamId();
			if (text2 == text)
			{
				return false;
			}
			bool flag = false;
			foreach (UpgradeId item in SyncUtil.GetUpgradeTypes(bundle).Where(ShouldSync))
			{
				Dictionary<string, int> upgrades = SyncUtil.GetUpgrades(bundle.Stats, item);
				int valueOrDefault = upgrades.GetValueOrDefault(text2, 0);
				int valueOrDefault2 = upgrades.GetValueOrDefault(text, 0);
				if (valueOrDefault2 <= valueOrDefault)
				{
					continue;
				}
				int num = valueOrDefault2 - valueOrDefault;
				if (flag = flag || num > 0)
				{
					if (item.Type != 0)
					{
						SyncUtil.AddToStatsDictionary(bundle, text2, item, num);
					}
					else
					{
						SyncUtil.UpgradeModded(bundle, target, item, num);
					}
					Entry.LogSource.LogInfo((object)string.Format("[{0}] Synchronized upgrade for player {1}: {2} ({3}), from {4} to {5}", "SyncFromSourceToTarget", text2, item.RawName, item.Type, valueOrDefault, valueOrDefault2));
				}
			}
			return flag;
		}

		private static bool NotHost(PlayerAvatar avatar)
		{
			return avatar.SteamId() != SyncUtil.HostSteamId;
		}

		private static bool ShouldSync(UpgradeId key)
		{
			ConfigEntry<bool> value;
			return key.Type switch
			{
				UpgradeType.Health => _syncHealth.Value, 
				UpgradeType.Stamina => _syncStamina.Value, 
				UpgradeType.ExtraJump => _syncExtraJump.Value, 
				UpgradeType.TumbleLaunch => _syncTumbleLaunch.Value, 
				UpgradeType.MapPlayerCount => _syncMapPlayerCount.Value, 
				UpgradeType.SprintSpeed => _syncSprintSpeed.Value, 
				UpgradeType.GrabStrength => _syncGrabStrength.Value, 
				UpgradeType.GrabRange => _syncGrabRange.Value, 
				UpgradeType.ThrowStrength => _syncThrowStrength.Value, 
				UpgradeType.TumbleWings => _syncTumbleWings.Value, 
				UpgradeType.CrouchRest => _syncCrouchRest.Value, 
				UpgradeType.Modded => registeredModdedUpgrades.TryGetValue(key, out value) && value.Value, 
				_ => false, 
			};
		}
	}
	internal record SyncRequest(SyncBundle Bundle) : ISyncRequest
	{
		public void Run()
		{
			Bundle.Manager.SyncAllDictionaries();
		}

		public static ISyncRequest New(SyncBundle bundle)
		{
			return new SyncRequest(bundle);
		}
	}
	[PublicAPI]
	public static class SyncUtil
	{
		private const RpcTarget Others = 1;

		private const string PlayerUpgrade = "playerUpgrade";

		private const string AppliedPlayerUpgrade = "appliedPlayerUpgrade";

		public static readonly UpgradeId HealthId = new UpgradeId(UpgradeType.Health);

		public static readonly UpgradeId StaminaId = new UpgradeId(UpgradeType.Stamina);

		public static readonly UpgradeId ExtraJumpId = new UpgradeId(UpgradeType.ExtraJump);

		public static readonly UpgradeId TumbleLaunchId = new UpgradeId(UpgradeType.TumbleLaunch);

		public static readonly UpgradeId MapPlayerCountId = new UpgradeId(UpgradeType.MapPlayerCount);

		public static readonly UpgradeId SprintSpeedId = new UpgradeId(UpgradeType.SprintSpeed);

		public static readonly UpgradeId GrabStrengthId = new UpgradeId(UpgradeType.GrabStrength);

		public static readonly UpgradeId GrabRangeId = new UpgradeId(UpgradeType.GrabRange);

		public static readonly UpgradeId ThrowStrengthId = new UpgradeId(UpgradeType.ThrowStrength);

		public static readonly UpgradeId TumbleWingsId = new UpgradeId(UpgradeType.TumbleWings);

		public static readonly UpgradeId CrouchRestId = new UpgradeId(UpgradeType.CrouchRest);

		private static readonly ConcurrentQueue<ISyncRequest> SyncQueue = new ConcurrentQueue<ISyncRequest>();

		public static string HostSteamId => Local.SteamId();

		public static PlayerAvatar Local => SemiFunc.PlayerAvatarLocal();

		public static string TrimKey(string? key)
		{
			if (string.IsNullOrEmpty(key))
			{
				return string.Empty;
			}
			string text;
			if (key.StartsWith("appliedPlayerUpgrade"))
			{
				text = key;
				return text.Substring(20, text.Length - 20);
			}
			if (!key.StartsWith("playerUpgrade"))
			{
				return key;
			}
			text = key;
			return text.Substring(13, text.Length - 13);
		}

		public static string FixKey(string? key)
		{
			if (string.IsNullOrEmpty(key))
			{
				return string.Empty;
			}
			if (!key.StartsWith("playerUpgrade"))
			{
				return "playerUpgrade" + key;
			}
			return key;
		}

		public static PlayerAvatar GetPlayer(string targetSteamId)
		{
			return SemiFunc.PlayerAvatarGetFromSteamID(targetSteamId);
		}

		public static IEnumerable<UpgradeId> GetUpgradeTypes(SyncBundle bundle)
		{
			return bundle.Stats.dictionaryOfDictionaries.Where((KeyValuePair<string, Dictionary<string, int>> kvp) => kvp.Key.StartsWith("playerUpgrade") || kvp.Key.StartsWith("appliedPlayerUpgrade")).Select(UpgradeId.New).Union(SyncManager.registeredModdedUpgrades.Keys);
		}

		public static UpgradeType GetUpgradeType(string? key)
		{
			return TrimKey(key) switch
			{
				"Health" => UpgradeType.Health, 
				"Stamina" => UpgradeType.Stamina, 
				"ExtraJump" => UpgradeType.ExtraJump, 
				"Launch" => UpgradeType.TumbleLaunch, 
				"MapPlayerCount" => UpgradeType.MapPlayerCount, 
				"Speed" => UpgradeType.SprintSpeed, 
				"Strength" => UpgradeType.GrabStrength, 
				"Range" => UpgradeType.GrabRange, 
				"Throw" => UpgradeType.ThrowStrength, 
				"TumbleWings" => UpgradeType.TumbleWings, 
				"CrouchRest" => UpgradeType.CrouchRest, 
				_ => UpgradeType.Modded, 
			};
		}

		public static string GetUpgradeName(UpgradeType key)
		{
			return key switch
			{
				UpgradeType.Health => "Health", 
				UpgradeType.Stamina => "Stamina", 
				UpgradeType.ExtraJump => "ExtraJump", 
				UpgradeType.TumbleLaunch => "Launch", 
				UpgradeType.MapPlayerCount => "MapPlayerCount", 
				UpgradeType.SprintSpeed => "Speed", 
				UpgradeType.GrabStrength => "Strength", 
				UpgradeType.GrabRange => "Range", 
				UpgradeType.ThrowStrength => "Throw", 
				UpgradeType.TumbleWings => "TumbleWings", 
				UpgradeType.CrouchRest => "CrouchRest", 
				UpgradeType.Modded => "Modded: Unknown", 
				_ => throw new ArgumentException("Invalid UpgradeType for GetUpgradeName"), 
			};
		}

		public static Dictionary<string, int> GetUpgrades(StatsManager stats, UpgradeId id)
		{
			return id.Type switch
			{
				UpgradeType.Health => stats.playerUpgradeHealth, 
				UpgradeType.Stamina => stats.playerUpgradeStamina, 
				UpgradeType.ExtraJump => stats.playerUpgradeExtraJump, 
				UpgradeType.TumbleLaunch => stats.playerUpgradeLaunch, 
				UpgradeType.MapPlayerCount => stats.playerUpgradeMapPlayerCount, 
				UpgradeType.SprintSpeed => stats.playerUpgradeSpeed, 
				UpgradeType.GrabStrength => stats.playerUpgradeStrength, 
				UpgradeType.GrabRange => stats.playerUpgradeRange, 
				UpgradeType.ThrowStrength => stats.playerUpgradeThrow, 
				UpgradeType.TumbleWings => stats.playerUpgradeTumbleWings, 
				UpgradeType.CrouchRest => stats.playerUpgradeCrouchRest, 
				UpgradeType.Modded => stats.dictionaryOfDictionaries[id.RawName], 
				_ => throw new ArgumentException("Invalid UpgradeType for GetUpgrades"), 
			};
		}

		public static void SyncStatsDictionaryToAll(SyncBundle bundle)
		{
			SyncQueue.Enqueue(SyncRequest.New(bundle));
		}

		public static int CallUpdateFunction(SyncBundle bundle, string steamId, UpgradeId key)
		{
			return key.Type switch
			{
				UpgradeType.Health => bundle.Manager.UpgradePlayerHealth(steamId), 
				UpgradeType.Stamina => bundle.Manager.UpgradePlayerEnergy(steamId), 
				UpgradeType.ExtraJump => bundle.Manager.UpgradePlayerExtraJump(steamId), 
				UpgradeType.TumbleLaunch => bundle.Manager.UpgradePlayerTumbleLaunch(steamId), 
				UpgradeType.MapPlayerCount => bundle.Manager.UpgradeMapPlayerCount(steamId), 
				UpgradeType.SprintSpeed => bundle.Manager.UpgradePlayerSprintSpeed(steamId), 
				UpgradeType.GrabStrength => bundle.Manager.UpgradePlayerGrabStrength(steamId), 
				UpgradeType.GrabRange => bundle.Manager.UpgradePlayerGrabRange(steamId), 
				UpgradeType.ThrowStrength => bundle.Manager.UpgradePlayerThrowStrength(steamId), 
				UpgradeType.TumbleWings => bundle.Manager.UpgradePlayerTumbleWings(steamId), 
				UpgradeType.CrouchRest => bundle.Manager.UpgradePlayerCrouchRest(steamId), 
				UpgradeType.Modded => UpgradeModded(bundle, SemiFunc.PlayerAvatarGetFromSteamID(steamId), key, 1), 
				_ => throw new ArgumentException("Invalid UpgradeType for CallUpdateFunction"), 
			};
		}

		public static int UpgradeModded(SyncBundle bundle, PlayerAvatar workingPlayer, UpgradeId key, int amount)
		{
			string steamId = workingPlayer.SteamId();
			int num = AddToStatsDictionary(bundle, steamId, key, amount);
			PlayerUpgrade val = default(PlayerUpgrade);
			if (Upgrades.TryGetUpgrade(TrimKey(key.RawName), ref val))
			{
				val.SetLevel(workingPlayer, num);
			}
			return num;
		}

		public static int AddToStatsDictionary(SyncBundle bundle, string steamId, UpgradeId key, int incrementAmount)
		{
			return bundle.Stats.dictionaryOfDictionaries[key.RawName][steamId] += incrementAmount;
		}

		internal static void QueueRPC(PhotonView view, string methodName, object target, object[] parameters)
		{
			SyncQueue.Enqueue(PunRequest.New(view, methodName, target, parameters));
		}

		internal static void RunOneRPC()
		{
			if (SyncQueue.TryDequeue(out ISyncRequest result))
			{
				result.Run();
			}
		}
	}
	[PublicAPI]
	public record UpgradeId(string RawName)
	{
		public UpgradeType Type { get; } = SyncUtil.GetUpgradeType(RawName);


		public UpgradeId(UpgradeType upgradeType)
			: this(SyncUtil.GetUpgradeName(upgradeType))
		{
			Type = upgradeType;
		}

		public override string ToString()
		{
			return "{ Type = \"" + Type.ToName() + "\", RawName = \"" + RawName + "\" }";
		}

		public static UpgradeId New(string rawName)
		{
			return new UpgradeId(rawName);
		}

		public static UpgradeId New<T>(KeyValuePair<string, T> item)
		{
			return new UpgradeId(item.Key);
		}
	}
	[PublicAPI]
	public enum UpgradeType
	{
		Modded,
		Health,
		Stamina,
		ExtraJump,
		TumbleLaunch,
		MapPlayerCount,
		SprintSpeed,
		GrabStrength,
		GrabRange,
		ThrowStrength,
		TumbleWings,
		CrouchRest
	}
}
namespace SyncUpgrades.Core.Internal
{
	internal class IgnoreMethodPatchExceptionAttribute : HarmonyAttribute
	{
	}
	internal static class HarmonyExtensions
	{
		private enum CallType
		{
			Prefix,
			Postfix,
			Transpiler,
			Finalizer,
			ILManipulator
		}

		private static bool IsDefined<T>(this Type type)
		{
			return type.IsDefined(typeof(T));
		}

		private static bool IsDefined<T>(this MethodInfo method)
		{
			return method.IsDefined(typeof(T));
		}

		private static bool IsDefined<T>(this MethodInfo method, bool inherit)
		{
			return method.IsDefined(typeof(T), inherit);
		}

		public static void PatchAllSafe(this Harmony harmony)
		{
			foreach (Type item in from t in AccessTools.GetTypesFromAssembly(Assembly.GetExecutingAssembly())
				where t.IsDefined<HarmonyPatch>() && t.IsClass
				select t)
			{
				MethodInfo[] array = (from m in item.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
					where m.IsDefined<HarmonyPatch>()
					select m).ToArray();
				foreach (MethodInfo method in array)
				{
					harmony.SafePatch(item, method);
				}
			}
		}

		private static void SafePatch(this Harmony harmony, Type @class, MethodInfo method)
		{
			Type type = ((HarmonyAttribute)(((MemberInfo)@class).GetCustomAttribute<HarmonyPatch>()?)).info.declaringType ?? ((HarmonyAttribute)(((MemberInfo)method).GetCustomAttribute<HarmonyPatch>()?)).info.declaringType ?? throw new InvalidOperationException("Could not find target @class for Harmony patch.");
			string text = ((HarmonyAttribute)(((MemberInfo)@class).GetCustomAttribute<HarmonyPatch>()?)).info.methodName ?? ((HarmonyAttribute)(((MemberInfo)method).GetCustomAttribute<HarmonyPatch>()?)).info.methodName ?? throw new InvalidOperationException("Could not find target method name for Harmony patch.");
			Type[] array = ((HarmonyAttribute)(((MemberInfo)@class).GetCustomAttribute<HarmonyPatch>()?)).info.argumentTypes ?? ((HarmonyAttribute)(((MemberInfo)method).GetCustomAttribute<HarmonyPatch>()?)).info.argumentTypes ?? null;
			CallType callType = GetCallType(method);
			MethodInfo methodInfo = AccessTools.Method(type, text, array, (Type[])null);
			bool flag = method.IsDefined<IgnoreMethodPatchExceptionAttribute>();
			if (flag && (object)methodInfo == null)
			{
				Entry.LogSource.LogWarning((object)("[IgnoreMethodPatchException] [WARN] [NOFAIL] Failed to patch method " + text + " in " + type.FullName));
				return;
			}
			try
			{
				DoRawPatch(harmony, methodInfo, method, callType);
			}
			catch (Exception innerException)
			{
				harmony.Unpatch((MethodBase)methodInfo, method);
				if (!flag)
				{
					throw new InvalidOperationException("Failed to patch method " + text + " in " + type.FullName, innerException);
				}
				Entry.LogSource.LogWarning((object)("[IgnoreMethodPatchException] [WARN] [NOFAIL] Failed to patch method " + text + " in " + type.FullName));
			}
		}

		private static void DoRawPatch(Harmony harmony, MethodInfo targetMethod, MethodInfo method, CallType callType)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Expected O, but got Unknown
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Expected O, but got Unknown
			switch (callType)
			{
			case CallType.Prefix:
				harmony.Patch((MethodBase)targetMethod, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				break;
			case CallType.Postfix:
				harmony.Patch((MethodBase)targetMethod, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				break;
			case CallType.Transpiler:
				harmony.Patch((MethodBase)targetMethod, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null);
				break;
			case CallType.Finalizer:
				harmony.Patch((MethodBase)targetMethod, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null);
				break;
			case CallType.ILManipulator:
				harmony.Patch((MethodBase)targetMethod, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(method));
				break;
			default:
				throw new InvalidOperationException($"Unknown call type: {callType}");
			}
		}

		private static CallType GetCallType(MethodInfo method)
		{
			if (method.IsDefined<HarmonyPrefix>())
			{
				return CallType.Prefix;
			}
			if (method.IsDefined<HarmonyPostfix>())
			{
				return CallType.Postfix;
			}
			if (method.IsDefined<HarmonyTranspiler>())
			{
				return CallType.Transpiler;
			}
			if (method.IsDefined<HarmonyFinalizer>())
			{
				return CallType.Finalizer;
			}
			if (method.IsDefined<HarmonyILManipulator>())
			{
				return CallType.ILManipulator;
			}
			throw new InvalidOperationException("Method " + method.Name + " does not have a valid Harmony call type defined.");
		}
	}
}