Decompiled source of DefaultUpgrade v4.0.0

DefaultUpgrade.dll

Decompiled a month 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.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using UnityEngine.SceneManagement;

[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: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("REPOJP")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("zabuMod")]
[assembly: AssemblyTitle("zabuMod")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace REPOJP.DefaultUpgrade
{
	[BepInPlugin("REPOJP.DefaultUpgrade", "DefaultUpgrade", "4.0.0")]
	public sealed class DefaultUpgradePlugin : BaseUnityPlugin
	{
		[CompilerGenerated]
		private sealed class <CoNewJoinSync>d__41 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public PlayerAvatar playerAvatar;

			public string reason;

			private float <timeout>5__1;

			private float <elapsed>5__2;

			private string <finalSteamId>5__3;

			private string <processKey>5__4;

			private string <steamId>5__5;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <CoNewJoinSync>d__41(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<finalSteamId>5__3 = null;
				<processKey>5__4 = null;
				<steamId>5__5 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d5: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<timeout>5__1 = ((CfgJoinSyncWindowSeconds != null) ? Mathf.Clamp(CfgJoinSyncWindowSeconds.Value, 5f, 120f) : 30f);
					<elapsed>5__2 = 0f;
					break;
				case 1:
					<>1__state = -1;
					<steamId>5__5 = null;
					break;
				}
				if (<elapsed>5__2 < <timeout>5__1)
				{
					if ((Object)(object)playerAvatar == (Object)null)
					{
						return false;
					}
					if (!IsTargetGameplaySceneSafe() || !IsLevelGeneratedSafe())
					{
						return false;
					}
					<steamId>5__5 = GetSteamId(playerAvatar);
					if (string.IsNullOrEmpty(<steamId>5__5))
					{
						<elapsed>5__2 += 0.25f;
						<>2__current = (object)new WaitForSeconds(0.25f);
						<>1__state = 1;
						return true;
					}
				}
				if ((Object)(object)playerAvatar == (Object)null)
				{
					return false;
				}
				<finalSteamId>5__3 = GetSteamId(playerAvatar);
				if (string.IsNullOrEmpty(<finalSteamId>5__3))
				{
					return false;
				}
				<processKey>5__4 = GetCurrentLevelSignature() + "|" + <finalSteamId>5__3;
				if (processedJoinSyncKeys.Contains(<processKey>5__4))
				{
					return false;
				}
				processedJoinSyncKeys.Add(<processKey>5__4);
				ApplyDefaultUpgradesForPlayers(new List<PlayerAvatar> { playerAvatar }, "NewJoinSync:" + reason);
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <CoPostLoadRepair>d__39 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public string reason;

			public DefaultUpgradePlugin <>4__this;

			private float <timeout>5__1;

			private float <elapsed>5__2;

			private float <delay>5__3;

			private string <signature>5__4;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <CoPostLoadRepair>d__39(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<signature>5__4 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_014d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0157: Expected O, but got Unknown
				//IL_009d: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a7: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<timeout>5__1 = 30f;
					<elapsed>5__2 = 0f;
					goto IL_00b8;
				case 1:
					<>1__state = -1;
					goto IL_00b8;
				case 2:
					{
						<>1__state = -1;
						break;
					}
					IL_00b8:
					if (<elapsed>5__2 < <timeout>5__1)
					{
						if (!IsModEnabled() || !IsHostOrSingleSafe())
						{
							<>4__this.postLoadRepairCoroutine = null;
							return false;
						}
						if (!IsTargetGameplaySceneSafe() || !IsLevelGeneratedSafe())
						{
							<elapsed>5__2 += 0.25f;
							<>2__current = (object)new WaitForSeconds(0.25f);
							<>1__state = 1;
							return true;
						}
					}
					if (!IsTargetGameplaySceneSafe() || !IsLevelGeneratedSafe())
					{
						<>4__this.postLoadRepairCoroutine = null;
						return false;
					}
					<delay>5__3 = 1f;
					try
					{
						<delay>5__3 = Mathf.Clamp(CfgPostLoadApplyDelay.Value, 0f, 10f);
					}
					catch
					{
						<delay>5__3 = 1f;
					}
					if (<delay>5__3 > 0f)
					{
						<>2__current = (object)new WaitForSeconds(<delay>5__3);
						<>1__state = 2;
						return true;
					}
					break;
				}
				<signature>5__4 = GetCurrentLevelSignature();
				if (lastPostLoadRepairSignature == <signature>5__4)
				{
					<>4__this.postLoadRepairCoroutine = null;
					return false;
				}
				ApplyDefaultUpgradesForCurrentPlayers("PostLoadRepair:" + reason);
				lastPostLoadRepairSignature = <signature>5__4;
				<>4__this.postLoadRepairCoroutine = null;
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <CoPreLoadApplyThenChangeLevel>d__37 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public RunManager runManager;

			public bool completedLevel;

			public bool levelFailed;

			public ChangeLevelType changeLevelType;

			public DefaultUpgradePlugin <>4__this;

			private float <wait>5__1;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <CoPreLoadApplyThenChangeLevel>d__37(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ab: Expected O, but got Unknown
				//IL_0102: Unknown result type (might be due to invalid IL or missing references)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					preLoadChangeLevelInProgress = true;
					ApplyDefaultUpgradesForCurrentPlayers("PreLoadBeforeChangeLevel");
					<wait>5__1 = 0.5f;
					try
					{
						<wait>5__1 = Mathf.Clamp(CfgPreLoadSyncWaitSeconds.Value, 0f, 3f);
					}
					catch
					{
						<wait>5__1 = 0.5f;
					}
					if (<wait>5__1 > 0f && IsMultiplayerSafe())
					{
						<>2__current = (object)new WaitForSeconds(<wait>5__1);
						<>1__state = 1;
						return true;
					}
					<>2__current = null;
					<>1__state = 2;
					return true;
				case 1:
					<>1__state = -1;
					break;
				case 2:
					<>1__state = -1;
					break;
				}
				suppressChangeLevelPrefix = true;
				try
				{
					if ((Object)(object)runManager != (Object)null)
					{
						runManager.ChangeLevel(completedLevel, levelFailed, changeLevelType);
					}
				}
				finally
				{
					suppressChangeLevelPrefix = false;
					preLoadChangeLevelInProgress = false;
				}
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		public const string PluginGuid = "REPOJP.DefaultUpgrade";

		public const string PluginName = "DefaultUpgrade";

		public const string PluginVersion = "4.0.0";

		internal static DefaultUpgradePlugin Instance;

		internal static ManualLogSource Log;

		private Harmony harmony;

		internal static ConfigEntry<bool> CfgEnableMod;

		internal static ConfigEntry<bool> CfgPreLoadApply;

		internal static ConfigEntry<bool> CfgPostLoadRepairApply;

		internal static ConfigEntry<bool> CfgNewJoinSync;

		internal static ConfigEntry<float> CfgPreLoadSyncWaitSeconds;

		internal static ConfigEntry<float> CfgPostLoadApplyDelay;

		internal static ConfigEntry<float> CfgJoinSyncWindowSeconds;

		internal static ConfigEntry<int> CfgHealth;

		internal static ConfigEntry<int> CfgStamina;

		internal static ConfigEntry<int> CfgExtraJump;

		internal static ConfigEntry<int> CfgLaunch;

		internal static ConfigEntry<int> CfgTumbleClimb;

		internal static ConfigEntry<int> CfgMapPlayerCount;

		internal static ConfigEntry<int> CfgDeathHeadBattery;

		internal static ConfigEntry<int> CfgSpeed;

		internal static ConfigEntry<int> CfgStrength;

		internal static ConfigEntry<int> CfgThrow;

		internal static ConfigEntry<int> CfgRange;

		internal static ConfigEntry<int> CfgCrouchRest;

		internal static ConfigEntry<int> CfgTumbleWings;

		internal static ConfigEntry<bool> CfgEnableLog;

		private static bool suppressChangeLevelPrefix;

		private static bool preLoadChangeLevelInProgress;

		private static string lastPostLoadRepairSignature = string.Empty;

		private static readonly HashSet<string> processedJoinSyncKeys = new HashSet<string>();

		private Coroutine postLoadRepairCoroutine;

		private void Awake()
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			((Component)this).transform.parent = null;
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			BindConfig();
			harmony = new Harmony("REPOJP.DefaultUpgrade");
			harmony.PatchAll();
			WriteInfo("Loaded DefaultUpgrade v4.0.0");
		}

		private void OnDestroy()
		{
			if (postLoadRepairCoroutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(postLoadRepairCoroutine);
				postLoadRepairCoroutine = null;
			}
			if (harmony != null)
			{
				harmony.UnpatchSelf();
				harmony = null;
			}
		}

		private void BindConfig()
		{
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Expected O, but got Unknown
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Expected O, but got Unknown
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Expected O, but got Unknown
			CfgEnableMod = ((BaseUnityPlugin)this).Config.Bind<bool>("A General", "EnableMod", true, "Enable this mod. このMODの有効無効");
			CfgPreLoadApply = ((BaseUnityPlugin)this).Config.Bind<bool>("A General", "PreLoadApply", true, "Apply default upgrades before level loading starts. レベルロード開始前にデフォルトアップグレードを先行付与");
			CfgPostLoadRepairApply = ((BaseUnityPlugin)this).Config.Bind<bool>("A General", "PostLoadRepairApply", true, "Repair missing upgrades after level generation as a fallback. レベル生成後に不足分を補修するフォールバック");
			CfgNewJoinSync = ((BaseUnityPlugin)this).Config.Bind<bool>("A General", "NewJoinSync", true, "Apply missing default upgrades to late join players. 途中参加者に不足分だけ同期付与");
			CfgPreLoadSyncWaitSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("A General", "PreLoadSyncWaitSeconds", 0.5f, new ConfigDescription("Wait seconds after Stats sync before starting level load. Stats同期後にレベルロードを開始するまでの待機秒数", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3f), Array.Empty<object>()));
			CfgPostLoadApplyDelay = ((BaseUnityPlugin)this).Config.Bind<float>("A General", "PostLoadApplyDelay", 1f, new ConfigDescription("Delay seconds before post-load repair. ロード後補修までの待機秒数", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>()));
			CfgJoinSyncWindowSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("A General", "JoinSyncWindowSeconds", 30f, new ConfigDescription("Retry window seconds for late join sync. 途中参加同期の再試行秒数", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 120f), Array.Empty<object>()));
			CfgHealth = BindUpgrade("Health", "Health upgrade default value. ヘルスアップグレード初期値");
			CfgStamina = BindUpgrade("Stamina", "Stamina upgrade default value. スタミナアップグレード初期値");
			CfgExtraJump = BindUpgrade("ExtraJump", "Extra jump upgrade default value. ジャンプアップグレード初期値");
			CfgLaunch = BindUpgrade("Launch", "Tumble launch upgrade default value. 打ち上げアップグレード初期値");
			CfgTumbleClimb = BindUpgrade("TumbleClimb", "Tumble climb upgrade default value. よじ登りアップグレード初期値");
			CfgMapPlayerCount = BindUpgrade("MapPlayerCount", "Map player count upgrade default value. プレイヤーカウントアップグレード初期値");
			CfgDeathHeadBattery = BindUpgrade("DeathHeadBattery", "Death head battery upgrade default value. デスヘッドバッテリーアップグレード初期値");
			CfgSpeed = BindUpgrade("Speed", "Speed upgrade default value. スピードアップグレード初期値");
			CfgStrength = BindUpgrade("Strength", "Strength upgrade default value. 筋力アップグレード初期値");
			CfgThrow = BindUpgrade("Throw", "Throw upgrade default value. 投擲力アップグレード初期値");
			CfgRange = BindUpgrade("Range", "Grab range upgrade default value. 掴み範囲アップグレード初期値");
			CfgCrouchRest = BindUpgrade("CrouchRest", "Crouch rest upgrade default value. しゃがみ回復アップグレード初期値");
			CfgTumbleWings = BindUpgrade("TumbleWings", "Tumble wings upgrade default value. 羽アップグレード初期値");
			CfgEnableLog = ((BaseUnityPlugin)this).Config.Bind<bool>("Z Debug", "EnableLog", true, "Enable log output. ログ出力有効無効");
		}

		private ConfigEntry<int> BindUpgrade(string key, string description)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			return ((BaseUnityPlugin)this).Config.Bind<int>("B Upgrades", key, 1, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 50), Array.Empty<object>()));
		}

		internal void StartPreLoadChangeLevel(RunManager runManager, bool completedLevel, bool levelFailed, ChangeLevelType changeLevelType)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if (!preLoadChangeLevelInProgress)
			{
				((MonoBehaviour)this).StartCoroutine(CoPreLoadApplyThenChangeLevel(runManager, completedLevel, levelFailed, changeLevelType));
			}
		}

		[IteratorStateMachine(typeof(<CoPreLoadApplyThenChangeLevel>d__37))]
		private IEnumerator CoPreLoadApplyThenChangeLevel(RunManager runManager, bool completedLevel, bool levelFailed, ChangeLevelType changeLevelType)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <CoPreLoadApplyThenChangeLevel>d__37(0)
			{
				<>4__this = this,
				runManager = runManager,
				completedLevel = completedLevel,
				levelFailed = levelFailed,
				changeLevelType = changeLevelType
			};
		}

		internal void SchedulePostLoadRepair(string reason)
		{
			if (IsModEnabled() && CfgPostLoadRepairApply.Value)
			{
				if (postLoadRepairCoroutine != null)
				{
					((MonoBehaviour)this).StopCoroutine(postLoadRepairCoroutine);
					postLoadRepairCoroutine = null;
				}
				postLoadRepairCoroutine = ((MonoBehaviour)this).StartCoroutine(CoPostLoadRepair(reason));
			}
		}

		[IteratorStateMachine(typeof(<CoPostLoadRepair>d__39))]
		private IEnumerator CoPostLoadRepair(string reason)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <CoPostLoadRepair>d__39(0)
			{
				<>4__this = this,
				reason = reason
			};
		}

		internal static void StartNewJoinSync(PlayerAvatar playerAvatar, string reason)
		{
			if (IsModEnabled() && CfgNewJoinSync != null && CfgNewJoinSync.Value && IsHostOrSingleSafe() && IsTargetGameplaySceneSafe() && IsLevelGeneratedSafe() && !((Object)(object)Instance == (Object)null) && !((Object)(object)playerAvatar == (Object)null))
			{
				((MonoBehaviour)Instance).StartCoroutine(CoNewJoinSync(playerAvatar, reason));
			}
		}

		[IteratorStateMachine(typeof(<CoNewJoinSync>d__41))]
		private static IEnumerator CoNewJoinSync(PlayerAvatar playerAvatar, string reason)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <CoNewJoinSync>d__41(0)
			{
				playerAvatar = playerAvatar,
				reason = reason
			};
		}

		internal static void ApplyDefaultUpgradesForCurrentPlayers(string reason)
		{
			if (IsModEnabled() && IsHostOrSingleSafe())
			{
				ApplyDefaultUpgradesForPlayers(GetSafePlayerList(), reason);
			}
		}

		internal static void ApplyDefaultUpgradesForPlayers(List<PlayerAvatar> playerList, string reason)
		{
			if ((Object)(object)StatsManager.instance == (Object)null)
			{
				WriteWarning("StatsManager.instance が null のため付与を中止: " + reason);
				return;
			}
			if (playerList == null || playerList.Count == 0)
			{
				WriteWarning("プレイヤー一覧が空のため付与を中止: " + reason);
				return;
			}
			bool flag = false;
			int num = 0;
			WriteInfo("デフォルトアップグレード付与開始: reason=" + reason + " / playerCount=" + playerList.Count);
			for (int i = 0; i < playerList.Count; i++)
			{
				PlayerAvatar val = playerList[i];
				if (!((Object)(object)val == (Object)null))
				{
					string steamId = GetSteamId(val);
					string playerName = GetPlayerName(val);
					if (string.IsNullOrEmpty(steamId))
					{
						WriteWarning("steamID 未取得プレイヤーをスキップ: " + playerName);
					}
					else if (ApplyMissingUpgradesToPlayer(steamId, playerName, reason))
					{
						flag = true;
						num++;
					}
				}
			}
			if (flag)
			{
				SyncStatsSafe(reason);
				WriteInfo("デフォルトアップグレード付与完了: reason=" + reason + " / changedPlayers=" + num + " / 同期実行");
			}
			else
			{
				WriteInfo("デフォルトアップグレード付与完了: reason=" + reason + " / 変更なし");
			}
		}

		internal static bool ApplyMissingUpgradesToPlayer(string steamId, string playerName, string reason)
		{
			if (string.IsNullOrEmpty(steamId))
			{
				return false;
			}
			if ((Object)(object)StatsManager.instance == (Object)null)
			{
				return false;
			}
			List<UpgradeEntry> upgradeEntries = GetUpgradeEntries();
			bool result = false;
			for (int i = 0; i < upgradeEntries.Count; i++)
			{
				UpgradeEntry upgradeEntry = upgradeEntries[i];
				int num = Mathf.Clamp(upgradeEntry.Target.Value, 0, 50);
				Dictionary<string, int> dictionary = upgradeEntry.DictionaryGetter();
				if (dictionary == null)
				{
					continue;
				}
				if (!dictionary.ContainsKey(steamId))
				{
					dictionary[steamId] = 0;
				}
				int num2 = dictionary[steamId];
				int num3 = num - num2;
				if (num3 > 0)
				{
					dictionary[steamId] = num2 + num3;
					if (upgradeEntry.Name == "Health")
					{
						ApplyHealthRecoveryToStats(steamId, num3, reason);
					}
					if (!IsPreLoadApplyReason(reason))
					{
						ApplyUpgradeRightAwayWithoutPunManager(upgradeEntry.Name, steamId, num3);
					}
					result = true;
					WriteInfo("適用: reason=" + reason + " / player=" + playerName + " / upgrade=" + upgradeEntry.Name + " / current=" + num2 + " / target=" + num + " / add=" + num3);
				}
			}
			return result;
		}

		private static bool IsPreLoadApplyReason(string reason)
		{
			if (string.IsNullOrEmpty(reason))
			{
				return false;
			}
			return reason.IndexOf("PreLoadBeforeChangeLevel", StringComparison.OrdinalIgnoreCase) >= 0;
		}

		private static void ApplyHealthRecoveryToStats(string steamId, int diff, string reason)
		{
			if ((Object)(object)StatsManager.instance == (Object)null || string.IsNullOrEmpty(steamId) || diff <= 0)
			{
				return;
			}
			try
			{
				int num = StatsManager.instance.GetPlayerHealth(steamId);
				if (num <= 0)
				{
					num = 1;
				}
				int num2 = 100 + StatsManager.instance.GetPlayerMaxHealth(steamId);
				int num3 = 20 * diff;
				int num4 = Mathf.Clamp(num + num3, 0, num2);
				StatsManager.instance.SetPlayerHealth(steamId, num4, true);
				WriteInfo("ヘルス回復反映: reason=" + reason + " / steamId=" + steamId + " / current=" + num + " / add=" + num3 + " / result=" + num4 + " / max=" + num2);
			}
			catch (Exception ex)
			{
				WriteException("ヘルス回復Stats反映失敗", ex);
			}
		}

		private static void ApplyHealthStateRightAway(string steamId, PlayerAvatar playerAvatar, string reason)
		{
			if ((Object)(object)StatsManager.instance == (Object)null || string.IsNullOrEmpty(steamId) || (Object)(object)playerAvatar == (Object)null || (Object)(object)playerAvatar.playerHealth == (Object)null)
			{
				return;
			}
			try
			{
				int playerHealth = StatsManager.instance.GetPlayerHealth(steamId);
				int num = 100 + StatsManager.instance.GetPlayerMaxHealth(steamId);
				playerHealth = Mathf.Clamp(playerHealth, 0, num);
				PlayerHealth playerHealth2 = playerAvatar.playerHealth;
				playerHealth2.maxHealth = num;
				if (GameManager.Multiplayer() && (Object)(object)playerHealth2.photonView != (Object)null)
				{
					playerHealth2.photonView.RPC("UpdateHealthRPC", (RpcTarget)0, new object[4] { playerHealth, num, false, false });
				}
				else
				{
					playerHealth2.health = playerHealth;
				}
				WriteInfo("ヘルス即時反映: reason=" + reason + " / steamId=" + steamId + " / health=" + playerHealth + " / max=" + num);
			}
			catch (Exception ex)
			{
				WriteException("ヘルス即時反映失敗", ex);
			}
		}

		private static void ApplyUpgradeRightAwayWithoutPunManager(string upgradeName, string steamId, int diff)
		{
			if (diff <= 0 || string.IsNullOrEmpty(upgradeName) || string.IsNullOrEmpty(steamId))
			{
				return;
			}
			PlayerAvatar val = null;
			try
			{
				val = SemiFunc.PlayerAvatarGetFromSteamID(steamId);
			}
			catch
			{
				val = null;
			}
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			try
			{
				switch (upgradeName)
				{
				case "Health":
					ApplyHealthStateRightAway(steamId, val, "RightAwayWithoutPunManager");
					break;
				case "Stamina":
					if ((Object)(object)val == (Object)(object)SemiFunc.PlayerAvatarLocal() && (Object)(object)PlayerController.instance != (Object)null)
					{
						PlayerController instance5 = PlayerController.instance;
						instance5.EnergyStart += 10f * (float)diff;
						PlayerController.instance.EnergyCurrent = PlayerController.instance.EnergyStart;
					}
					break;
				case "ExtraJump":
					if ((Object)(object)val == (Object)(object)SemiFunc.PlayerAvatarLocal() && (Object)(object)PlayerController.instance != (Object)null)
					{
						PlayerController instance4 = PlayerController.instance;
						instance4.JumpExtra += diff;
					}
					break;
				case "Launch":
					if ((Object)(object)val.tumble != (Object)null)
					{
						PlayerTumble tumble = val.tumble;
						tumble.tumbleLaunch += diff;
					}
					break;
				case "TumbleClimb":
				{
					PlayerAvatar obj4 = val;
					obj4.upgradeTumbleClimb += (float)diff;
					break;
				}
				case "MapPlayerCount":
				{
					PlayerAvatar obj6 = val;
					obj6.upgradeMapPlayerCount += diff;
					break;
				}
				case "DeathHeadBattery":
				{
					PlayerAvatar obj5 = val;
					obj5.upgradeDeathHeadBattery += (float)diff;
					break;
				}
				case "Speed":
					if ((Object)(object)val == (Object)(object)SemiFunc.PlayerAvatarLocal() && (Object)(object)PlayerController.instance != (Object)null)
					{
						PlayerController instance = PlayerController.instance;
						instance.SprintSpeed += (float)diff;
						PlayerController instance2 = PlayerController.instance;
						instance2.SprintSpeedUpgrades += (float)diff;
						PlayerController instance3 = PlayerController.instance;
						instance3.playerOriginalSprintSpeed += (float)diff;
					}
					break;
				case "Strength":
					if ((Object)(object)val.physGrabber != (Object)null)
					{
						PhysGrabber physGrabber3 = val.physGrabber;
						physGrabber3.grabStrength += 0.2f * (float)diff;
					}
					break;
				case "Throw":
					if ((Object)(object)val.physGrabber != (Object)null)
					{
						PhysGrabber physGrabber2 = val.physGrabber;
						physGrabber2.throwStrength += 0.3f * (float)diff;
					}
					break;
				case "Range":
					if ((Object)(object)val.physGrabber != (Object)null)
					{
						PhysGrabber physGrabber = val.physGrabber;
						physGrabber.grabRange += (float)diff;
					}
					break;
				case "CrouchRest":
				{
					PlayerAvatar obj3 = val;
					obj3.upgradeCrouchRest += (float)diff;
					break;
				}
				case "TumbleWings":
				{
					PlayerAvatar obj2 = val;
					obj2.upgradeTumbleWings += (float)diff;
					break;
				}
				}
			}
			catch (Exception ex)
			{
				WriteException("直接アップグレード即時反映失敗: " + upgradeName, ex);
			}
		}

		private static void SyncStatsSafe(string reason)
		{
			try
			{
				SemiFunc.StatSyncAll();
			}
			catch (Exception ex)
			{
				WriteException("StatSyncAll 失敗: " + reason, ex);
			}
		}

		internal static List<UpgradeEntry> GetUpgradeEntries()
		{
			StatsManager statsManager = StatsManager.instance;
			return new List<UpgradeEntry>
			{
				new UpgradeEntry("Health", CfgHealth, () => statsManager.playerUpgradeHealth),
				new UpgradeEntry("Stamina", CfgStamina, () => statsManager.playerUpgradeStamina),
				new UpgradeEntry("ExtraJump", CfgExtraJump, () => statsManager.playerUpgradeExtraJump),
				new UpgradeEntry("Launch", CfgLaunch, () => statsManager.playerUpgradeLaunch),
				new UpgradeEntry("TumbleClimb", CfgTumbleClimb, () => statsManager.playerUpgradeTumbleClimb),
				new UpgradeEntry("MapPlayerCount", CfgMapPlayerCount, () => statsManager.playerUpgradeMapPlayerCount),
				new UpgradeEntry("DeathHeadBattery", CfgDeathHeadBattery, () => statsManager.playerUpgradeDeathHeadBattery),
				new UpgradeEntry("Speed", CfgSpeed, () => statsManager.playerUpgradeSpeed),
				new UpgradeEntry("Strength", CfgStrength, () => statsManager.playerUpgradeStrength),
				new UpgradeEntry("Throw", CfgThrow, () => statsManager.playerUpgradeThrow),
				new UpgradeEntry("Range", CfgRange, () => statsManager.playerUpgradeRange),
				new UpgradeEntry("CrouchRest", CfgCrouchRest, () => statsManager.playerUpgradeCrouchRest),
				new UpgradeEntry("TumbleWings", CfgTumbleWings, () => statsManager.playerUpgradeTumbleWings)
			};
		}

		internal static bool ShouldInterceptChangeLevel(RunManager runManager, bool completedLevel, bool levelFailed, ChangeLevelType changeLevelType)
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Invalid comparison between Unknown and I4
			if (!IsModEnabled())
			{
				return false;
			}
			if (CfgPreLoadApply == null || !CfgPreLoadApply.Value)
			{
				return false;
			}
			if (suppressChangeLevelPrefix || preLoadChangeLevelInProgress)
			{
				return false;
			}
			if ((Object)(object)runManager == (Object)null)
			{
				return false;
			}
			if (!IsHostOrSingleSafe())
			{
				return false;
			}
			try
			{
				if ((Object)(object)runManager.levelCurrent == (Object)(object)runManager.levelLobby)
				{
					return (int)changeLevelType == 0 || (int)changeLevelType == 1;
				}
			}
			catch
			{
				return false;
			}
			return false;
		}

		internal static bool IsModEnabled()
		{
			return CfgEnableMod != null && CfgEnableMod.Value;
		}

		internal static bool IsHostOrSingleSafe()
		{
			try
			{
				return SemiFunc.IsMasterClientOrSingleplayer();
			}
			catch
			{
				try
				{
					return !PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient;
				}
				catch
				{
					return false;
				}
			}
		}

		internal static bool IsMultiplayerSafe()
		{
			try
			{
				return SemiFunc.IsMultiplayer();
			}
			catch
			{
				try
				{
					return PhotonNetwork.InRoom;
				}
				catch
				{
					return false;
				}
			}
		}

		internal static bool IsTargetGameplaySceneSafe()
		{
			try
			{
				return SemiFunc.RunIsLevel() || SemiFunc.RunIsArena() || SemiFunc.RunIsTutorial();
			}
			catch
			{
				return false;
			}
		}

		internal static bool IsLevelGeneratedSafe()
		{
			try
			{
				return (Object)(object)LevelGenerator.Instance != (Object)null && LevelGenerator.Instance.Generated;
			}
			catch
			{
				return false;
			}
		}

		internal static string GetCurrentLevelSignature()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			Scene activeScene = SceneManager.GetActiveScene();
			string name = ((Scene)(ref activeScene)).name;
			int num = -1;
			string text = string.Empty;
			try
			{
				if ((Object)(object)RunManager.instance != (Object)null)
				{
					num = RunManager.instance.levelsCompleted;
					text = (((Object)(object)RunManager.instance.levelCurrent != (Object)null) ? ((Object)RunManager.instance.levelCurrent).name : string.Empty);
				}
			}
			catch
			{
			}
			return name + "|" + text + "|" + num;
		}

		private static List<PlayerAvatar> GetSafePlayerList()
		{
			Dictionary<string, PlayerAvatar> dictionary = new Dictionary<string, PlayerAvatar>();
			try
			{
				List<PlayerAvatar> list = SemiFunc.PlayerGetList();
				if (list != null)
				{
					for (int i = 0; i < list.Count; i++)
					{
						AddPlayerToMap(dictionary, list[i]);
					}
				}
			}
			catch
			{
			}
			if (dictionary.Count == 0)
			{
				try
				{
					PlayerAvatar[] array = Resources.FindObjectsOfTypeAll<PlayerAvatar>();
					for (int j = 0; j < array.Length; j++)
					{
						AddPlayerToMap(dictionary, array[j]);
					}
				}
				catch
				{
				}
			}
			return new List<PlayerAvatar>(dictionary.Values);
		}

		private static void AddPlayerToMap(Dictionary<string, PlayerAvatar> map, PlayerAvatar avatar)
		{
			if (map == null || (Object)(object)avatar == (Object)null)
			{
				return;
			}
			string text = GetSteamId(avatar);
			if (string.IsNullOrEmpty(text))
			{
				try
				{
					text = "instance:" + ((Object)avatar).GetInstanceID();
				}
				catch
				{
					return;
				}
			}
			map[text] = avatar;
		}

		private static string GetSteamId(PlayerAvatar avatar)
		{
			if ((Object)(object)avatar == (Object)null)
			{
				return string.Empty;
			}
			try
			{
				if (!string.IsNullOrEmpty(avatar.steamID))
				{
					return avatar.steamID;
				}
			}
			catch
			{
			}
			try
			{
				string text = SemiFunc.PlayerGetSteamID(avatar);
				if (!string.IsNullOrEmpty(text))
				{
					return text;
				}
			}
			catch
			{
			}
			return string.Empty;
		}

		private static string GetPlayerName(PlayerAvatar avatar)
		{
			if ((Object)(object)avatar == (Object)null)
			{
				return "Unknown";
			}
			try
			{
				if (!string.IsNullOrEmpty(avatar.playerName))
				{
					return avatar.playerName;
				}
			}
			catch
			{
			}
			try
			{
				string text = SemiFunc.PlayerGetName(avatar);
				if (!string.IsNullOrEmpty(text))
				{
					return text;
				}
			}
			catch
			{
			}
			try
			{
				return ((Object)avatar).name;
			}
			catch
			{
				return "Unknown";
			}
		}

		internal static void WriteInfo(string message)
		{
			if (Log != null && (CfgEnableLog == null || CfgEnableLog.Value))
			{
				Log.LogInfo((object)message);
			}
		}

		internal static void WriteWarning(string message)
		{
			if (Log != null && (CfgEnableLog == null || CfgEnableLog.Value))
			{
				Log.LogWarning((object)message);
			}
		}

		internal static void WriteException(string title, Exception ex)
		{
			if (Log != null && (CfgEnableLog == null || CfgEnableLog.Value))
			{
				Log.LogError((object)(title + "\n" + ex));
			}
		}
	}
	internal sealed class UpgradeEntry
	{
		public string Name;

		public ConfigEntry<int> Target;

		public Func<Dictionary<string, int>> DictionaryGetter;

		public UpgradeEntry(string name, ConfigEntry<int> target, Func<Dictionary<string, int>> dictionaryGetter)
		{
			Name = name;
			Target = target;
			DictionaryGetter = dictionaryGetter;
		}
	}
	[HarmonyPatch(typeof(RunManager), "ChangeLevel")]
	internal static class RunManager_ChangeLevel_Patch
	{
		private static bool Prefix(RunManager __instance, bool _completedLevel, bool _levelFailed, ChangeLevelType _changeLevelType)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!DefaultUpgradePlugin.ShouldInterceptChangeLevel(__instance, _completedLevel, _levelFailed, _changeLevelType))
				{
					return true;
				}
				if ((Object)(object)DefaultUpgradePlugin.Instance != (Object)null)
				{
					DefaultUpgradePlugin.Instance.StartPreLoadChangeLevel(__instance, _completedLevel, _levelFailed, _changeLevelType);
					return false;
				}
			}
			catch (Exception ex)
			{
				DefaultUpgradePlugin.WriteException("RunManager.ChangeLevel Prefix 失敗", ex);
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(LevelGenerator), "GenerateDone")]
	internal static class LevelGenerator_GenerateDone_Patch
	{
		private static void Postfix()
		{
			try
			{
				if ((Object)(object)DefaultUpgradePlugin.Instance != (Object)null)
				{
					DefaultUpgradePlugin.Instance.SchedulePostLoadRepair("GenerateDone");
				}
			}
			catch (Exception ex)
			{
				DefaultUpgradePlugin.WriteException("GenerateDone Postfix 失敗", ex);
			}
		}
	}
	[HarmonyPatch(typeof(PlayerAvatar), "Awake")]
	internal static class PlayerAvatar_Awake_Patch
	{
		private static void Postfix(PlayerAvatar __instance)
		{
			try
			{
				DefaultUpgradePlugin.StartNewJoinSync(__instance, "PlayerAvatar.Awake");
			}
			catch (Exception ex)
			{
				DefaultUpgradePlugin.WriteException("PlayerAvatar Awake Postfix 失敗", ex);
			}
		}
	}
	[HarmonyPatch(typeof(PlayerAvatar), "LateStart")]
	internal static class PlayerAvatar_LateStart_Patch
	{
		private static void Postfix(PlayerAvatar __instance)
		{
			try
			{
				DefaultUpgradePlugin.StartNewJoinSync(__instance, "PlayerAvatar.LateStart");
			}
			catch (Exception ex)
			{
				DefaultUpgradePlugin.WriteException("PlayerAvatar LateStart Postfix 失敗", ex);
			}
		}
	}
	[HarmonyPatch(typeof(NetworkManager), "OnPlayerEnteredRoom")]
	internal static class NetworkManager_OnPlayerEnteredRoom_Patch
	{
		private static void Postfix(Player newPlayer)
		{
			try
			{
				if (newPlayer != null)
				{
					DefaultUpgradePlugin.WriteInfo("プレイヤー参加検知: actor=" + newPlayer.ActorNumber + " / name=" + newPlayer.NickName + " / NewJoinSync=" + (DefaultUpgradePlugin.CfgNewJoinSync != null && DefaultUpgradePlugin.CfgNewJoinSync.Value));
				}
			}
			catch (Exception ex)
			{
				DefaultUpgradePlugin.WriteException("OnPlayerEnteredRoom Postfix 失敗", ex);
			}
		}
	}
}