Decompiled source of Online Mod Plus TABS v1.1.0

plugins\Online_Mod_Plus.dll

Decompiled 4 days ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using BepInEx;
using BepInEx.Bootstrap;
using BitCode.UI;
using DM;
using GamepadUI.StateManager.Core;
using HarmonyLib;
using InControl;
using Landfall.TABC;
using Landfall.TABS;
using Landfall.TABS.AI;
using Landfall.TABS.AI.Components;
using Landfall.TABS.AI.Systems;
using Landfall.TABS.Budget;
using Landfall.TABS.Budget.Wallets;
using Landfall.TABS.GameMode;
using Landfall.TABS.GameState;
using Landfall.TABS.Services;
using Landfall.TABS.TeamEdge;
using Landfall.TABS.UnitPlacement;
using Landfall.TABS.WinConditions;
using Landfall.TABS.Workshop;
using Landfall.TABS_Input;
using Lilzalupa.FourTeams;
using Microsoft.CodeAnalysis;
using Mod_Name;
using Photon.Bolt;
using Photon.Bolt.Channel;
using Photon.Bolt.Internal;
using Photon.Bolt.Matchmaking;
using Photon.Bolt.SceneManagement;
using Photon.Bolt.Utils;
using Photon.Realtime;
using Steamworks;
using TFBG;
using TFBGames;
using TMPro;
using UIStateManager;
using UdpKit;
using UdpKit.Platform;
using UdpKit.Platform.Photon;
using Unity.Entities;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Multiplayer16")]
[assembly: AssemblyDescription("16人联机Mod for TABS")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Multiplayer16")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("a1b2c3d4-e5f6-7890-abcd-ef1234567890")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: InternalsVisibleTo("MP16TestHarness")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("bolt")]
[assembly: IgnoresAccessChecksTo("bolt.user")]
[assembly: IgnoresAccessChecksTo("Foreign_forces")]
[assembly: IgnoresAccessChecksTo("FourTeams")]
[assembly: IgnoresAccessChecksTo("Photon3Unity3D")]
[assembly: IgnoresAccessChecksTo("PhotonBolt")]
[assembly: IgnoresAccessChecksTo("PhotonRealtime")]
[assembly: IgnoresAccessChecksTo("udpkit.common")]
[assembly: IgnoresAccessChecksTo("udpkit")]
[assembly: IgnoresAccessChecksTo("udpkit.platform.photon")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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 Multiplayer16
{
	internal static class BattleRestartPatches
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static UnityAction <>9__6_1;

			internal void <ShowRestartConfirm>b__6_1()
			{
				_restartConfirmOpen = false;
			}
		}

		private static Harmony _harmony;

		private static bool _restartConfirmOpen;

		public static void ApplyPatches()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Expected O, but got Unknown
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Expected O, but got Unknown
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Expected O, but got Unknown
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Expected O, but got Unknown
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Expected O, but got Unknown
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Expected O, but got Unknown
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Expected O, but got Unknown
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Expected O, but got Unknown
			_harmony = new Harmony("Multiplayer16.BattleRestart");
			_harmony.Patch((MethodBase)AccessTools.Method(typeof(OnlineMultiplayerGameMode), "RequestEndBattle", (Type[])null, (Type[])null), new HarmonyMethod(typeof(BattleRestartPatches), "RequestEndBattlePrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			_harmony.Patch((MethodBase)AccessTools.Method(typeof(OnlineMultiplayerGameMode), "BeginEndingMatch", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(BattleRestartPatches), "BeginEndingMatchPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			_harmony.Patch((MethodBase)AccessTools.Method(typeof(OnlineMultiplayerGameMode), "OnCountDownTimerEnded", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(BattleRestartPatches), "OnCountDownTimerEndedPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			_harmony.Patch((MethodBase)AccessTools.Method(typeof(NetworkBattleController), "SetReadyForPlacement", (Type[])null, (Type[])null), new HarmonyMethod(typeof(BattleRestartPatches), "SetReadyForPlacementPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			_harmony.Patch((MethodBase)AccessTools.Method(typeof(NetworkBattleController), "ServerStartPlacement", (Type[])null, (Type[])null), new HarmonyMethod(typeof(BattleRestartPatches), "ServerStartPlacementPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			_harmony.Patch((MethodBase)AccessTools.Method(typeof(OnlineMultiplayerGameMode), "OnEnterPlacementState", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(BattleRestartPatches), "OnlineOnEnterPlacementStatePostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			_harmony.Patch((MethodBase)AccessTools.Method(typeof(NetworkBattleController), "OnEvent", new Type[1] { typeof(StartPlacementEvent) }, (Type[])null), new HarmonyMethod(typeof(BattleRestartPatches), "OnEventStartPlacementPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			_harmony.Patch((MethodBase)AccessTools.Method(typeof(BaseGameMode), "OnEnterPlacementState", (Type[])null, (Type[])null), new HarmonyMethod(typeof(BattleRestartPatches), "OnEnterPlacementStatePrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			Debug.Log((object)"[Multiplayer16] BattleRestartPatches: 主机控制战斗结束与返回放置");
		}

		private static bool RequestEndBattlePrefix(OnlineMultiplayerGameMode __instance)
		{
			if (BoltNetwork.IsClient && !BoltNetwork.IsServer)
			{
				return false;
			}
			if (!BoltNetwork.IsServer)
			{
				return true;
			}
			if (IsBattleInProgress(__instance))
			{
				if (!_restartConfirmOpen)
				{
					ShowRestartConfirm(__instance);
				}
				return false;
			}
			ContinueAfterMatch(__instance);
			return false;
		}

		private static void ContinueAfterMatch(OnlineMultiplayerGameMode gameMode)
		{
			if (!CampaignModeSystem.TryHostContinueAfterWin(gameMode))
			{
				HostReturnToPlacement(gameMode);
			}
		}

		private static bool IsBattleInProgress(OnlineMultiplayerGameMode gameMode)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Invalid comparison between Unknown and I4
			if (gameMode != null && !((BaseGameMode)gameMode).MatchOver)
			{
				GameStateManager service = ServiceLocator.GetService<GameStateManager>();
				if (service == null)
				{
					return false;
				}
				return (int)service.GameState == 1;
			}
			return false;
		}

		private static void ShowRestartConfirm(OnlineMultiplayerGameMode gameMode)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Expected O, but got Unknown
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			ModalPanel service = ServiceLocator.GetService<ModalPanel>();
			if ((Object)(object)service == (Object)null)
			{
				HostReturnToPlacement(gameMode);
				return;
			}
			_restartConfirmOpen = true;
			try
			{
				string empty = string.Empty;
				string text = ModL10n.T("restart_battle_confirm");
				UnityAction val = delegate
				{
					_restartConfirmOpen = false;
					HostReturnToPlacement(gameMode);
				};
				object obj = <>c.<>9__6_1;
				if (obj == null)
				{
					UnityAction val2 = delegate
					{
						_restartConfirmOpen = false;
					};
					<>c.<>9__6_1 = val2;
					obj = (object)val2;
				}
				service.Choice(empty, text, val, (UnityAction)obj, new string[2]
				{
					ModL10n.T("yes"),
					ModL10n.T("no")
				});
			}
			catch (Exception ex)
			{
				_restartConfirmOpen = false;
				Debug.LogWarning((object)("[Multiplayer16] 重启确认弹窗失败: " + ex.Message));
				HostReturnToPlacement(gameMode);
			}
		}

		private static void CloseRestartConfirmIfOpen()
		{
			if (_restartConfirmOpen)
			{
				_restartConfirmOpen = false;
				ModalPanel service = ServiceLocator.GetService<ModalPanel>();
				if (service != null)
				{
					service.ForcePopUpClose();
				}
			}
		}

		private static void BeginEndingMatchPostfix(Team winningTeam)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			CampaignModeSystem.NotifyWinner(winningTeam);
		}

		private static void OnCountDownTimerEndedPostfix(OnlineMultiplayerGameMode __instance)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Invalid comparison between Unknown and I4
			if (BoltNetwork.IsRunning && BoltNetwork.IsServer && __instance != null && ((BaseGameMode)__instance).MatchOver)
			{
				GameStateManager service = ServiceLocator.GetService<GameStateManager>();
				if (service != null && (int)service.GameState == 1)
				{
					ContinueAfterMatch(__instance);
				}
			}
		}

		private static bool SetReadyForPlacementPrefix()
		{
			return !BoltNetwork.IsRunning;
		}

		private static bool ServerStartPlacementPrefix()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Invalid comparison between Unknown and I4
			if (!BoltNetwork.IsRunning)
			{
				return true;
			}
			GameStateManager service = ServiceLocator.GetService<GameStateManager>();
			if (service == null)
			{
				return true;
			}
			return (int)service.GameState > 0;
		}

		private static void OnlineOnEnterPlacementStatePostfix()
		{
			if (ShouldFastReturnFromBattle())
			{
				RestoreTimeImmediate();
			}
		}

		private static bool ShouldFastReturnFromBattle()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Invalid comparison between Unknown and I4
			if (IsOnlineClient())
			{
				GameStateManager service = ServiceLocator.GetService<GameStateManager>();
				if (service == null)
				{
					return false;
				}
				return (int)service.PreviousGameState == 1;
			}
			return false;
		}

		private static void RestoreTimeImmediate()
		{
			ITimeService service = ServiceLocator.GetService<ITimeService>();
			if (service != null)
			{
				service.Unlock();
				service.UnPause();
				service.SetState(1f, 0f, true);
			}
			BoltRuntimeSettings.instance.overrideTimeScale = true;
		}

		private static void ResetCountdown()
		{
			CountdownTimerService service = ServiceLocator.GetService<CountdownTimerService>();
			if ((Object)(object)service != (Object)null)
			{
				service.countingDown = false;
				service.canCountDown = true;
				service.elapsedTime = 0f;
				service.timeLeft = 0f;
			}
		}

		internal static void HostReturnToPlacement(OnlineMultiplayerGameMode gameMode)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			CloseRestartConfirmIfOpen();
			if (!BoltNetwork.IsServer || gameMode == null)
			{
				return;
			}
			GameStateManager service = ServiceLocator.GetService<GameStateManager>();
			if (service == null || (int)service.GameState != 0)
			{
				CleanupBattleEndForReturnToPlacement(gameMode);
				if (service != null)
				{
					service.EnterPlacementState();
				}
				((Event)StartPlacementEvent.Create((GlobalTargets)4, (ReliabilityModes)2)).Send();
			}
		}

		internal static void CleanupBattleEndForReturnToPlacement(OnlineMultiplayerGameMode gameMode)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Invalid comparison between Unknown and I4
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Invalid comparison between Unknown and I4
			if (gameMode == null)
			{
				return;
			}
			gameMode.Unsubscribe();
			ResetCountdown();
			((BaseGameMode)gameMode).MatchOver = false;
			VerticalCurtainController curtainController = ((BaseGameMode)gameMode).CurtainController;
			if (curtainController != null)
			{
				curtainController.OpenCurtains();
			}
			gameMode.SetTimeToPaused(false);
			RestoreTimeImmediate();
			NetworkBattleController service = ServiceLocator.GetService<NetworkBattleController>();
			if ((Object)(object)service != (Object)null)
			{
				service.m_battleStarted = false;
				NetworkGamePhase phase = service.Phase;
				if ((int)phase == 4 || (int)phase == 5)
				{
					service.SetPhase((NetworkGamePhase)1);
				}
			}
		}

		private static void OnEventStartPlacementPrefix()
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Invalid comparison between Unknown and I4
			if (!IsOnlineClient())
			{
				return;
			}
			GameModeService service = ServiceLocator.GetService<GameModeService>();
			BaseGameMode obj = ((service != null) ? service.CurrentGameMode : null);
			OnlineMultiplayerGameMode val = (OnlineMultiplayerGameMode)(object)((obj is OnlineMultiplayerGameMode) ? obj : null);
			if (val != null)
			{
				GameStateManager service2 = ServiceLocator.GetService<GameStateManager>();
				if (service2 != null && (int)service2.GameState == 1)
				{
					Debug.Log((object)"[Multiplayer16] 客机收到 StartPlacementEvent(自战斗返回),清理结算状态");
					CleanupBattleEndForReturnToPlacement(val);
					ForceSnapPlacementCamera();
				}
			}
		}

		private static bool OnEnterPlacementStatePrefix(BaseGameMode __instance)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			if (!ShouldFastReturnFromBattle() || !(__instance is OnlineMultiplayerGameMode))
			{
				return true;
			}
			Debug.Log((object)"[Multiplayer16] 客机自战斗返回放置: 跳过 TaskSequencer");
			TeamLayouts teamLayouts = __instance.TeamLayouts;
			if (teamLayouts != null)
			{
				foreach (Team item in teamLayouts.m_layouts.Keys.ToList())
				{
					teamLayouts.ClearTeamLayout(item, true);
				}
			}
			__instance.ResetMatchVariables();
			BattleBudget battleBudget = __instance.BattleBudget;
			if (battleBudget != null)
			{
				battleBudget.ResetBudgetAll();
			}
			UnitPlacementBrush brush = __instance.Brush;
			if (brush != null)
			{
				brush.OnEnterPlacementState();
			}
			return false;
		}

		private static bool IsOnlineClient()
		{
			if (BoltNetwork.IsRunning && BoltNetwork.IsClient)
			{
				return !BoltNetwork.IsServer;
			}
			return false;
		}

		private static void ForceSnapPlacementCamera()
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			SandboxPlacementCamera val = Object.FindObjectOfType<SandboxPlacementCamera>();
			if (!((Object)(object)val == (Object)null))
			{
				((MonoBehaviour)val).StopAllCoroutines();
				val.m_isGoingToPos = false;
				val.IsResettingRotation = false;
				if (val.IsInFreeLook())
				{
					val.ExitFreeLook();
					val.m_isGoingToPos = false;
					((Component)val).transform.position = val.cameraPlacementStartPosition;
				}
			}
		}
	}
	internal static class BattleRestartUnitSync
	{
		private static Harmony _harmony;

		public static void ApplyPatches()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Expected O, but got Unknown
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Expected O, but got Unknown
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Expected O, but got Unknown
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Expected O, but got Unknown
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Expected O, but got Unknown
			_harmony = new Harmony("Multiplayer16.BattleRestartUnitSync");
			MethodInfo methodInfo = AccessTools.Method(typeof(BrushBehaviourOnlineMultiplayer), "PlaceLayoutUnit", (Type[])null, (Type[])null);
			if (methodInfo != null)
			{
				_harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(BattleRestartUnitSync), "PlaceLayoutUnitPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Debug.Log((object)"[Multiplayer16] 已Patch BrushBehaviourOnlineMultiplayer.PlaceLayoutUnit (仅主机还原布局)");
			}
			MethodInfo methodInfo2 = AccessTools.Method(typeof(TeamLayouts), "AddUnitToLayout", (Type[])null, (Type[])null);
			if (methodInfo2 != null)
			{
				_harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(BattleRestartUnitSync), "AddUnitToLayoutPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo methodInfo3 = AccessTools.Method(typeof(TeamLayouts), "RemoveUnitFromLayout", (Type[])null, (Type[])null);
			if (methodInfo3 != null)
			{
				_harmony.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, new HarmonyMethod(typeof(BattleRestartUnitSync), "RemoveUnitFromLayoutPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo methodInfo4 = AccessTools.Method(typeof(OnlineMultiplayerGameMode), "OnEnterNewScene", (Type[])null, (Type[])null);
			if (methodInfo4 != null)
			{
				_harmony.Patch((MethodBase)methodInfo4, (HarmonyMethod)null, new HarmonyMethod(typeof(BattleRestartUnitSync), "OnEnterNewScenePostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			Debug.Log((object)"[Multiplayer16] BattleRestartUnitSync 补丁应用完成");
		}

		private static uint GetLocalOwnerId()
		{
			if (!BoltNetwork.IsServer)
			{
				return PossessionSync.GetMyServerConnectionId();
			}
			return 0u;
		}

		private static bool PlaceLayoutUnitPrefix(BrushBehaviourOnlineMultiplayer __instance, TABSLayoutUnit unit, Team team, Quaternion unitRotation)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			if (!BoltNetwork.IsRunning || __instance == null || unit == null)
			{
				return true;
			}
			if (!BoltNetwork.IsServer)
			{
				return false;
			}
			UnitPlacementBrush unitPlacementBrush = ((BrushBehaviourBase)__instance).UnitPlacementBrush;
			if (unitPlacementBrush == null)
			{
				return false;
			}
			bool flag = !unit.CampaignUnit;
			unitPlacementBrush.PlaceLayoutUnitInternal(unit, team, true, unitRotation, flag);
			return false;
		}

		private static void AddUnitToLayoutPostfix(Unit unit)
		{
			if (BoltNetwork.IsRunning && ((unit != null) ? unit.RuntimeReference : null) != null)
			{
				uint connectionId;
				uint ownerConnectionId = (UnitPlacementSync.TryConsumePendingLayoutOwner(out connectionId) ? connectionId : GetLocalOwnerId());
				UnitOwnershipSystem.RecordLayoutOwner(((RuntimeReference)unit.RuntimeReference).Guid, ownerConnectionId);
			}
		}

		private static void RemoveUnitFromLayoutPostfix(RuntimeReference reference)
		{
			if (reference != null)
			{
				UnitOwnershipSystem.ClearLayoutOwner(reference.Guid);
			}
		}

		private static void OnEnterNewScenePostfix()
		{
			UnitOwnershipSystem.ClearAllLayoutOwners();
		}
	}
	internal static class BlindModePatches
	{
		public static void ApplyPatches()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Expected O, but got Unknown
			Harmony val = new Harmony("Multiplayer16.BlindMode");
			MethodInfo methodInfo = AccessTools.Method(typeof(NetworkUnitsManager), "ApplyProjectMarsBlindModeSettings", (Type[])null, (Type[])null);
			if (methodInfo != null)
			{
				val.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(BlindModePatches), "ApplyProjectMarsBlindModeSettingsPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo methodInfo2 = AccessTools.Method(typeof(OnlineMultiplayerGameMode), "ShowBlindPlacementUnits", (Type[])null, (Type[])null);
			if (methodInfo2 != null)
			{
				val.Patch((MethodBase)methodInfo2, new HarmonyMethod(typeof(BlindModePatches), "ShowBlindPlacementUnitsPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			Debug.Log((object)"[Multiplayer16] BlindModePatches: 黑箱模式按本方队伍隐藏");
		}

		private static bool ApplyProjectMarsBlindModeSettingsPrefix(Unit spawnedUnit, Team spawnedUnitTeam)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)spawnedUnit == (Object)null || !BoltNetwork.IsRunning)
			{
				return false;
			}
			NetworkBattleController service = ServiceLocator.GetService<NetworkBattleController>();
			if ((Object)(object)service == (Object)null || !service.blindMode)
			{
				return false;
			}
			if (spawnedUnitTeam == PlayerTeamMapping.GetLocalPlayerTeam())
			{
				return false;
			}
			spawnedUnit.IsSpawnedInBlindPlacement = true;
			ShowProjectile[] componentsInChildren = ((Component)spawnedUnit).GetComponentsInChildren<ShowProjectile>();
			if (componentsInChildren != null)
			{
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					if ((Object)(object)componentsInChildren[i] != (Object)null)
					{
						componentsInChildren[i].IsInBlindGame = true;
					}
				}
			}
			spawnedUnit.GetAllRenderers();
			if ((Object)(object)spawnedUnit.SpawnEffects != (Object)null)
			{
				((Component)spawnedUnit.SpawnEffects).gameObject.SetActive(false);
			}
			spawnedUnit.ShowRenderers(false);
			return false;
		}

		private static bool ShowBlindPlacementUnitsPrefix()
		{
			if (!BoltNetwork.IsRunning || TABSSceneManager.IsInMainMenuScene())
			{
				return false;
			}
			NetworkBattleController service = ServiceLocator.GetService<NetworkBattleController>();
			if ((Object)(object)service == (Object)null || !service.blindMode)
			{
				return false;
			}
			Unit[] array = Object.FindObjectsOfType<Unit>();
			if (array == null)
			{
				return false;
			}
			Unit[] array2 = array;
			foreach (Unit val in array2)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				val.IsSpawnedInBlindPlacement = false;
				ShowProjectile[] componentsInChildren = ((Component)val).GetComponentsInChildren<ShowProjectile>();
				if (componentsInChildren != null)
				{
					for (int j = 0; j < componentsInChildren.Length; j++)
					{
						if ((Object)(object)componentsInChildren[j] != (Object)null)
						{
							componentsInChildren[j].IsInBlindGame = false;
						}
					}
				}
				val.ShowRenderers(true);
			}
			return false;
		}
	}
	internal static class BoltConnectionPatches
	{
		private static uint _handledConnectId;

		private static int _handledConnectFrame;

		private static uint _handledDisconnectId;

		private static int _handledDisconnectFrame;

		private static readonly HashSet<uint> VerifyingConnections = new HashSet<uint>();

		public static void ApplyPatches()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Expected O, but got Unknown
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Expected O, but got Unknown
			Harmony val = new Harmony("Multiplayer16.BoltConnection");
			MethodInfo methodInfo = AccessTools.Method(typeof(GlobalEventListener), "ConnectRequest", (Type[])null, (Type[])null);
			if (methodInfo != null)
			{
				HarmonyMethod val2 = new HarmonyMethod(typeof(BoltConnectionPatches), "ConnectRequestPrefix", (Type[])null);
				val.Patch((MethodBase)methodInfo, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Debug.Log((object)"[Multiplayer16] 已Patch GlobalEventListener.ConnectRequest");
			}
			MethodInfo methodInfo2 = AccessTools.Method(typeof(GlobalEventListener), "Connected", (Type[])null, (Type[])null);
			if (methodInfo2 != null)
			{
				HarmonyMethod val3 = new HarmonyMethod(typeof(BoltConnectionPatches), "ConnectedPostfix", (Type[])null);
				val.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, val3, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Debug.Log((object)"[Multiplayer16] 已Patch GlobalEventListener.Connected");
			}
			MethodInfo methodInfo3 = AccessTools.Method(typeof(GlobalEventListener), "Disconnected", (Type[])null, (Type[])null);
			if (methodInfo3 != null)
			{
				HarmonyMethod val4 = new HarmonyMethod(typeof(BoltConnectionPatches), "DisconnectedPostfix", (Type[])null);
				val.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, val4, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Debug.Log((object)"[Multiplayer16] 已Patch GlobalEventListener.Disconnected");
			}
			Debug.Log((object)"[Multiplayer16] BoltConnection 补丁应用完成");
		}

		private static bool ConnectRequestPrefix(UdpEndPoint endpoint, IProtocolToken token)
		{
			if (!BoltNetwork.IsServer || !BoltNetwork.IsRunning)
			{
				return true;
			}
			try
			{
				string currentRoomPassword = RoomPasswordSystem.GetCurrentRoomPassword();
				if (string.IsNullOrEmpty(currentRoomPassword))
				{
					return true;
				}
				Debug.Log((object)("[Multiplayer16] 服务器端:收到连接请求(房间有暗号: " + currentRoomPassword + "),将在Connected阶段验证"));
				return true;
			}
			catch (Exception ex)
			{
				Debug.LogError((object)("[Multiplayer16] ConnectRequestPrefix 错误: " + ex.Message));
				return true;
			}
		}

		private static void ConnectedPostfix(BoltConnection connection)
		{
			if (connection == null)
			{
				return;
			}
			int frameCount = Time.frameCount;
			if (_handledConnectId == connection.ConnectionId && _handledConnectFrame == frameCount)
			{
				return;
			}
			_handledConnectId = connection.ConnectionId;
			_handledConnectFrame = frameCount;
			if (BoltNetwork.IsServer)
			{
				if (!VerifyAndAcceptConnection(connection))
				{
					Debug.LogWarning((object)$"[Multiplayer16] 服务器端:连接 {connection.ConnectionId} 未通过暗号验证,已断开");
					return;
				}
				RoomPasswordSystem.MarkConnectionAuthorized(connection.ConnectionId);
			}
			PlayerTeamMapping.RegisterPlayer(connection);
			RoomPasswordSystem.SendMapStartToConnectionIfNeeded(connection);
			PossessionSync.OnClientConnected(connection);
		}

		private static bool VerifyAndAcceptConnection(BoltConnection connection)
		{
			try
			{
				UdpSession currentSession = BoltMatchmaking.CurrentSession;
				if (currentSession == null || !(currentSession is PhotonSession))
				{
					return true;
				}
				string currentRoomPassword = RoomPasswordSystem.GetCurrentRoomPassword();
				if (!VerifyingConnections.Add(connection.ConnectionId) && RoomPasswordSystem.IsConnectionAuthorized(connection.ConnectionId))
				{
					return true;
				}
				GameModeSwitchPatches.CoroutineRunner coroutineRunner = GameModeSwitchPatches.GetCoroutineRunner();
				if ((Object)(object)coroutineRunner != (Object)null)
				{
					((MonoBehaviour)coroutineRunner).StartCoroutine(ImmediatePasswordVerification(connection, currentRoomPassword));
					return true;
				}
				Debug.LogWarning((object)"[Multiplayer16] 无法找到 MonoBehaviour,无法进行服务器端验证");
				DisconnectUnauthorizedConnection(connection);
				return false;
			}
			catch (Exception ex)
			{
				Debug.LogError((object)("[Multiplayer16] VerifyAndAcceptConnection 错误: " + ex.Message));
				if (connection != null)
				{
					DisconnectUnauthorizedConnection(connection);
				}
				return false;
			}
		}

		private static IEnumerator ImmediatePasswordVerification(BoltConnection connection, string roomPassword)
		{
			Debug.Log((object)$"[Multiplayer16] 服务器端:等待连接 {connection.ConnectionId} 发送 Mod 握手包...");
			float timeout = 15f;
			for (float elapsed = 0f; elapsed < timeout; elapsed += 0.5f)
			{
				if (connection == null)
				{
					yield break;
				}
				if (RoomPasswordSystem.IsConnectionAuthorized(connection.ConnectionId))
				{
					Debug.Log((object)$"[Multiplayer16] 服务器端:连接 {connection.ConnectionId} 已通过 Mod 握手验证");
					yield break;
				}
				yield return (object)new WaitForSeconds(0.5f);
			}
			if (!RoomPasswordSystem.IsConnectionAuthorized(connection.ConnectionId))
			{
				Debug.LogWarning((object)$"[Multiplayer16] 服务器端:连接 {connection.ConnectionId} 验证超时(未收到 Mod 握手包),判定为非 Mod 玩家,断开连接");
				DisconnectUnauthorizedConnection(connection);
			}
		}

		private static void SendRoomLockedAndDisconnect(BoltConnection connection)
		{
			if (connection == null)
			{
				return;
			}
			try
			{
				PlayerInfoEvent val = PlayerInfoEvent.Create(connection, (ReliabilityModes)2);
				if (val != null)
				{
					byte[] array = new byte[4];
					BitConverter.GetBytes(3405643785u).CopyTo(array, 0);
					((Event)val).BinaryData = array;
					val.PlayerName = "ROOM_LOCKED";
					((Event)val).Send();
				}
			}
			catch
			{
			}
			GameModeSwitchPatches.CoroutineRunner coroutineRunner = GameModeSwitchPatches.GetCoroutineRunner();
			if ((Object)(object)coroutineRunner != (Object)null)
			{
				((MonoBehaviour)coroutineRunner).StartCoroutine(DelayedDisconnectLocked(connection));
			}
			else
			{
				DisconnectUnauthorizedConnection(connection);
			}
		}

		private static IEnumerator DelayedDisconnectLocked(BoltConnection connection)
		{
			yield return (object)new WaitForSecondsRealtime(0.2f);
			DisconnectUnauthorizedConnection(connection);
		}

		private static void DisconnectUnauthorizedConnection(BoltConnection connection)
		{
			if (connection == null || RoomPasswordSystem.IsConnectionAuthorized(connection.ConnectionId))
			{
				return;
			}
			try
			{
				Debug.LogWarning((object)$"[Multiplayer16] 服务器端:断开未授权连接 {connection.ConnectionId}(房间需要暗号)");
				connection.Disconnect();
			}
			catch (Exception ex)
			{
				Debug.LogError((object)("[Multiplayer16] DisconnectUnauthorizedConnection 错误: " + ex.Message));
			}
		}

		private static void DisconnectedPostfix(BoltConnection connection)
		{
			if (connection != null)
			{
				int frameCount = Time.frameCount;
				if (_handledDisconnectId == connection.ConnectionId && _handledDisconnectFrame == frameCount)
				{
					return;
				}
				_handledDisconnectId = connection.ConnectionId;
				_handledDisconnectFrame = frameCount;
				VerifyingConnections.Remove(connection.ConnectionId);
				RoomPasswordSystem.ClearConnectionAuthorization(connection.ConnectionId);
				PossessionSync.OnClientDisconnected(connection.ConnectionId);
				PlayerTeamMapping.UnregisterPlayer(connection.ConnectionId);
				NetworkBattleControllerPatches.OnPlayerDisconnected(connection.ConnectionId);
			}
			if (BoltMatchmaking.CurrentSession == null && !RoomPasswordSystem.IsCreatingRoom)
			{
				PossessionSync.ClearSessionPlayers();
				GameModeSwitchPatches.Reset();
				Debug.Log((object)"[Multiplayer16] 检测到会话已断开,重置游戏模式切换标志");
			}
		}
	}
	internal static class BugDlcPatches
	{
		public static void ApplyPatches()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Expected O, but got Unknown
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Expected O, but got Unknown
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Expected O, but got Unknown
			Harmony val = new Harmony("Multiplayer16.BugDlc");
			MethodInfo methodInfo = AccessTools.Method(typeof(GameModeService), "IsGameModeRestricted", (Type[])null, (Type[])null);
			if (methodInfo != null)
			{
				val.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(BugDlcPatches), "IsGameModeRestrictedPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Debug.Log((object)"[Multiplayer16] 已Patch GameModeService.IsGameModeRestricted (主机允许 Bug DLC)");
			}
			MethodInfo methodInfo2 = AccessTools.Method(typeof(SettingsHandler), "GetSettingsForTab", (Type[])null, (Type[])null);
			if (methodInfo2 != null)
			{
				val.Patch((MethodBase)methodInfo2, new HarmonyMethod(typeof(BugDlcPatches), "GetSettingsForTabPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Debug.Log((object)"[Multiplayer16] 已Patch SettingsHandler.GetSettingsForTab (联机 Bug DLC)");
			}
			MethodInfo methodInfo3 = AccessTools.Method(typeof(SettingsHandler), "OpenSettingsMenu", new Type[1] { typeof(int) }, (Type[])null);
			if (methodInfo3 != null)
			{
				val.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, new HarmonyMethod(typeof(BugDlcPatches), "OpenSettingsMenuPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Debug.Log((object)"[Multiplayer16] 已Patch SettingsHandler.OpenSettingsMenu (去掉联机 Bug 不可用提示)");
			}
			MethodInfo methodInfo4 = AccessTools.Method(typeof(SettingsInstance), "SaveSettings", (Type[])null, (Type[])null);
			if (methodInfo4 != null)
			{
				val.Patch((MethodBase)methodInfo4, new HarmonyMethod(typeof(BugDlcPatches), "SaveSettingsPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			Debug.Log((object)"[Multiplayer16] BugDlc 补丁应用完成");
		}

		public static void RestoreClientBugSettings()
		{
			try
			{
				GlobalSettingsHandler service = ServiceLocator.GetService<GlobalSettingsHandler>();
				SettingsInstance[] array = ((service != null) ? service.BugsSettings : null);
				if (array == null)
				{
					return;
				}
				SettingsProfileManager service2 = ServiceLocator.GetService<SettingsProfileManager>();
				SettingsProfile val = ((service2 != null) ? service2.CurrentSettingsProfile : null);
				SettingsInstance[] array2 = array;
				foreach (SettingsInstance val2 in array2)
				{
					if (val2 != null)
					{
						val2.DisableChanges = false;
						if ((Object)(object)val != (Object)null)
						{
							val2.LoadSettings(val);
						}
					}
				}
			}
			catch
			{
			}
		}

		public static void LockClientBugs()
		{
			try
			{
				GlobalSettingsHandler service = ServiceLocator.GetService<GlobalSettingsHandler>();
				SettingsInstance[] array = ((service != null) ? service.BugsSettings : null);
				if (array != null)
				{
					ApplyClientLock(array);
				}
			}
			catch
			{
			}
		}

		private static void IsGameModeRestrictedPostfix(ref bool __result)
		{
			if (__result && BoltNetwork.IsRunning && BoltNetwork.IsServer)
			{
				__result = false;
			}
		}

		private static bool GetSettingsForTabPrefix(int tabID, ref SettingsInstance[] __result)
		{
			if (tabID != 4 || !BoltNetwork.IsRunning || !BoltNetwork.IsServer || !Bugs._DLC_ACTIVATED)
			{
				return true;
			}
			GlobalSettingsHandler service = ServiceLocator.GetService<GlobalSettingsHandler>();
			SettingsInstance[] array = ((service != null) ? service.BugsSettings : null);
			if (array == null || array.Length == 0)
			{
				return true;
			}
			__result = array;
			return false;
		}

		private static void OpenSettingsMenuPostfix(SettingsHandler __instance, int tabID)
		{
			if (tabID != 4 || !BoltNetwork.IsRunning || !BoltNetwork.IsServer)
			{
				return;
			}
			try
			{
				__instance.ShowCenterMessage(false, (string)null);
			}
			catch
			{
			}
		}

		private static bool SaveSettingsPrefix(SettingsInstance __instance)
		{
			if (!BoltNetwork.IsClient || !BoltNetwork.IsRunning || __instance == null)
			{
				return true;
			}
			string settingsKey = __instance.m_settingsKey;
			if (!string.IsNullOrEmpty(settingsKey) && settingsKey.StartsWith("BUG_"))
			{
				return false;
			}
			return true;
		}

		private static void ApplyClientLock(SettingsInstance[] bugs)
		{
			if (!BoltNetwork.IsClient)
			{
				return;
			}
			foreach (SettingsInstance val in bugs)
			{
				if (val != null)
				{
					val.DisableChanges = true;
					val.currentValue = 0;
					val.currentSliderValue = 0f;
				}
			}
		}
	}
	internal static class CampaignModeSystem
	{
		internal const uint MARKER = 3405643787u;

		internal const string EVENT_NAME = "CAMP_STATE";

		private static Harmony _harmony;

		private static Team _lastWinner = (Team)(-1);

		private static int _lastSceneLoadedLevelIndex = int.MinValue;

		public static bool HasBoundCampaign
		{
			get
			{
				if ((Object)(object)CampaignPlayerDataHolder.SelectedCampaign != (Object)null)
				{
					return GameRoomModeState.IsCampaign;
				}
				return false;
			}
		}

		private static HarmonyMethod Hook(string name)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			return new HarmonyMethod(typeof(CampaignModeSystem), name, (Type[])null);
		}

		public static void Initialize()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Expected O, but got Unknown
			_harmony = new Harmony("Multiplayer16.CampaignMode");
			_harmony.Patch((MethodBase)AccessTools.Method(typeof(UIMapSelector), "Start", (Type[])null, (Type[])null), (HarmonyMethod)null, Hook("UiMapSelectorStartPostfix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			_harmony.Patch((MethodBase)AccessTools.Method(typeof(MapSelectionCanvas), "GetGameModeUI", (Type[])null, (Type[])null), Hook("GetGameModeUiPrefix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			_harmony.Patch((MethodBase)AccessTools.Method(typeof(LevelSelection), "SetLevelGridForCurrentGameType", (Type[])null, (Type[])null), Hook("SetLevelGridPrefix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			_harmony.Patch((MethodBase)AccessTools.Method(typeof(LevelSelection), "SpawnCampaignLevelCell", (Type[])null, (Type[])null), Hook("SpawnCampaignLevelCellPrefix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			_harmony.Patch((MethodBase)AccessTools.Method(typeof(CampaignPlayerDataHolder), "StartedPlayingNewCampaign", (Type[])null, (Type[])null), Hook("StartedPlayingNewCampaignPrefix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			_harmony.Patch((MethodBase)AccessTools.Method(typeof(TABSSceneManager), "LoadCampaign", (Type[])null, (Type[])null), Hook("LoadCampaignPrefix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			_harmony.Patch((MethodBase)AccessTools.Method(typeof(CampaignPlayerDataHolder), "LoadCampaignLevelWithIndex", (Type[])null, (Type[])null), Hook("LoadCampaignLevelWithIndexPrefix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			_harmony.Patch((MethodBase)AccessTools.Method(typeof(CampaignPlayerDataHolder), "LoadNextCampaignLevel", (Type[])null, (Type[])null), Hook("LoadNextCampaignLevelPrefix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			_harmony.Patch((MethodBase)AccessTools.Method(typeof(PlacementUI), "EnterPlacementState", (Type[])null, (Type[])null), (HarmonyMethod)null, Hook("EnterPlacementStatePostfix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			_harmony.Patch((MethodBase)AccessTools.Method(typeof(PlacementUI), "ShowUI", (Type[])null, (Type[])null), (HarmonyMethod)null, Hook("ShowUiPostfix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			_harmony.Patch((MethodBase)AccessTools.Method(typeof(PlacementFactionBar), "Spawn", Type.EmptyTypes, (Type[])null), Hook("FactionBarSpawnPrefix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			_harmony.Patch((MethodBase)AccessTools.Method(typeof(PlacementFactionBar), "SpawnFaction", (Type[])null, (Type[])null), (HarmonyMethod)null, Hook("SpawnFactionPostfix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			_harmony.Patch((MethodBase)AccessTools.Method(typeof(PlacementUI), "DrawFactionUnit", new Type[2]
			{
				typeof(UnitBlueprint),
				typeof(bool)
			}, (Type[])null), Hook("DrawFactionUnitPrefix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			_harmony.Patch((MethodBase)AccessTools.Method(typeof(PlacementUI), "AssignInitialUnitToBrush", (Type[])null, (Type[])null), Hook("AssignInitialUnitToBrushPrefix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			_harmony.Patch((MethodBase)AccessTools.Method(typeof(BattleRadialButton), "UpdateData", (Type[])null, (Type[])null), (HarmonyMethod)null, Hook("BattleRadialButtonUpdateDataPostfix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			_harmony.Patch((MethodBase)AccessTools.Method(typeof(BattleRadialMenu), "BuildCaches", (Type[])null, (Type[])null), Hook("BuildCachesPrefix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			_harmony.Patch((MethodBase)AccessTools.Method(typeof(OnlineMultiplayerGameMode), "OnEnterNewScene", (Type[])null, (Type[])null), (HarmonyMethod)null, Hook("OnEnterNewScenePostfix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			CampaignSelectionUI.Ensure();
			Debug.Log((object)"[Multiplayer16] CampaignModeSystem 已初始化");
		}

		public static void Bind(TABSCampaignAsset campaign, int levelIndex)
		{
			if ((Object)(object)campaign == (Object)null)
			{
				return;
			}
			TABSCampaignLevelAsset[] levelsInCampaign = campaign.LevelsInCampaign;
			if (levelsInCampaign != null && levelsInCampaign.Length != 0)
			{
				if (levelIndex < 0)
				{
					levelIndex = 0;
				}
				if (levelIndex >= levelsInCampaign.Length)
				{
					levelIndex = levelsInCampaign.Length - 1;
				}
				CampaignPlayerDataHolder.SelectedCampaign = campaign;
				CampaignPlayerDataHolder._LevelIndex = levelIndex;
				CampaignPlayerDataHolder.AutoLoadNextLevel = true;
				SetLastLoadedLevel(levelsInCampaign[levelIndex]);
			}
		}

		public static void SetLastLoadedLevel(TABSCampaignLevelAsset level)
		{
			CampaignHandler.LastLoadedLevel = level;
		}

		public static void NotifyWinner(Team winningTeam)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			_lastWinner = winningTeam;
		}

		public static bool TryHostContinueAfterWin(OnlineMultiplayerGameMode gameMode)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			if (!GameRoomModeState.IsCampaign || !BoltNetwork.IsServer)
			{
				return false;
			}
			if ((int)_lastWinner != 0)
			{
				return false;
			}
			TABSCampaignAsset selectedCampaign = CampaignPlayerDataHolder.SelectedCampaign;
			if (((selectedCampaign != null) ? selectedCampaign.LevelsInCampaign : null) == null)
			{
				return false;
			}
			int num = GetBoundLevelIndex() + 1;
			if (num >= selectedCampaign.LevelsInCampaign.Length)
			{
				return false;
			}
			try
			{
				CampaignPlayerDataHolder.CompletedCurrentLevel();
			}
			catch
			{
			}
			if (gameMode != null)
			{
				BattleRestartPatches.CleanupBattleEndForReturnToPlacement(gameMode);
			}
			HostLoadLevel(num);
			return true;
		}

		public static void ShowCampaignPicker(Action<TABSCampaignAsset> onSelected, Action onCancel = null)
		{
			CampaignSelectionUI.Ensure();
			CampaignSelectionUI.Instance?.Show(onSelected, onCancel);
		}

		public static void HostStartCampaign(TABSCampaignAsset campaign)
		{
			if (!((Object)(object)campaign == (Object)null) && BoltNetwork.IsServer)
			{
				GameModeSwitchPatches.EnsureOnlineGameModeState();
				Bind(campaign, 0);
				HostLoadCurrentBoundLevel();
			}
		}

		public static void HostLoadLevel(int index)
		{
			if (BoltNetwork.IsServer)
			{
				TABSCampaignAsset selectedCampaign = CampaignPlayerDataHolder.SelectedCampaign;
				if (!((Object)(object)selectedCampaign == (Object)null))
				{
					Bind(selectedCampaign, index);
					HostLoadCurrentBoundLevel();
				}
			}
		}

		public static void HostLoadCurrentBoundLevel()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			if (!BoltNetwork.IsServer)
			{
				return;
			}
			TABSCampaignLevelAsset val = TryGetBoundLevel();
			if (!((Object)(object)val == (Object)null))
			{
				SetLastLoadedLevel(val);
				BroadcastState();
				MapAsset mapAsset = val.MapAsset;
				if (!((Object)(object)mapAsset == (Object)null))
				{
					GameModeSwitchPatches.RequestForceMapReload();
					RoomPasswordSystem.StartGameWithMap(mapAsset.m_MapType, mapAsset.m_mapIndex);
				}
			}
		}

		public static byte[] AppendToMapStart(byte[] data)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			if (!GameRoomModeState.IsCampaign || data == null)
			{
				return data;
			}
			TABSCampaignAsset selectedCampaign = CampaignPlayerDataHolder.SelectedCampaign;
			if (((selectedCampaign != null) ? selectedCampaign.Entity : null) == null)
			{
				return data;
			}
			byte[] array = new byte[12];
			BitConverter.GetBytes(selectedCampaign.Entity.GUID.m_modID).CopyTo(array, 0);
			BitConverter.GetBytes(selectedCampaign.Entity.GUID.m_ID).CopyTo(array, 4);
			BitConverter.GetBytes(GetBoundLevelIndex()).CopyTo(array, 8);
			byte[] array2 = new byte[data.Length + array.Length];
			Buffer.BlockCopy(data, 0, array2, 0, data.Length);
			Buffer.BlockCopy(array, 0, array2, data.Length, array.Length);
			return array2;
		}

		public static void TryApplyFromMapStart(byte[] data, int nameStart, ushort nameLen)
		{
			int num = nameStart + nameLen;
			if (data != null && data.Length >= num + 12)
			{
				int modId = BitConverter.ToInt32(data, num);
				int campaignId = BitConverter.ToInt32(data, num + 4);
				int levelIndex = BitConverter.ToInt32(data, num + 8);
				ApplyRemote(modId, campaignId, levelIndex);
			}
		}

		public static void TryApplyPacket(byte[] data)
		{
			if (data != null && data.Length >= 16)
			{
				int modId = BitConverter.ToInt32(data, 4);
				int campaignId = BitConverter.ToInt32(data, 8);
				int levelIndex = BitConverter.ToInt32(data, 12);
				ApplyRemote(modId, campaignId, levelIndex);
			}
		}

		public static void ApplyRemote(int modId, int campaignId, int levelIndex)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				ContentDatabase obj = ContentDatabase.Instance();
				TABSCampaignAsset val = ((obj != null) ? obj.GetCampaign(new DatabaseID(modId, campaignId)) : null);
				if ((Object)(object)val == (Object)null)
				{
					foreach (TABSCampaignAsset allCampaign in ContentDatabase.Instance().GetAllCampaigns())
					{
						if (((allCampaign != null) ? allCampaign.Entity : null) != null && allCampaign.Entity.GUID.m_ID == campaignId && allCampaign.Entity.GUID.m_modID == modId)
						{
							val = allCampaign;
							break;
						}
					}
				}
				if ((Object)(object)val != (Object)null)
				{
					Bind(val, levelIndex);
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[Multiplayer16] 应用战役状态失败: " + ex.Message));
			}
		}

		public static void SendToConnection(BoltConnection dest)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			if (!BoltNetwork.IsServer || dest == null)
			{
				return;
			}
			TABSCampaignAsset selectedCampaign = CampaignPlayerDataHolder.SelectedCampaign;
			if (!GameRoomModeState.IsCampaign || ((selectedCampaign != null) ? selectedCampaign.Entity : null) == null)
			{
				return;
			}
			try
			{
				byte[] array = new byte[16];
				BitConverter.GetBytes(3405643787u).CopyTo(array, 0);
				BitConverter.GetBytes(selectedCampaign.Entity.GUID.m_modID).CopyTo(array, 4);
				BitConverter.GetBytes(selectedCampaign.Entity.GUID.m_ID).CopyTo(array, 8);
				BitConverter.GetBytes(GetBoundLevelIndex()).CopyTo(array, 12);
				PlayerInfoEvent val = PlayerInfoEvent.Create(dest, (ReliabilityModes)2);
				if (val != null)
				{
					val.PlayerName = "CAMP_STATE";
					((Event)val).BinaryData = array;
					((Event)val).Send();
				}
			}
			catch
			{
			}
		}

		public static void BroadcastState()
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			if (!BoltNetwork.IsServer || !BoltNetwork.IsRunning || BoltNetwork.Connections == null)
			{
				return;
			}
			TABSCampaignAsset selectedCampaign = CampaignPlayerDataHolder.SelectedCampaign;
			if (((selectedCampaign != null) ? selectedCampaign.Entity : null) == null)
			{
				return;
			}
			byte[] array = new byte[16];
			BitConverter.GetBytes(3405643787u).CopyTo(array, 0);
			BitConverter.GetBytes(selectedCampaign.Entity.GUID.m_modID).CopyTo(array, 4);
			BitConverter.GetBytes(selectedCampaign.Entity.GUID.m_ID).CopyTo(array, 8);
			BitConverter.GetBytes(GetBoundLevelIndex()).CopyTo(array, 12);
			foreach (BoltConnection connection in BoltNetwork.Connections)
			{
				if (connection == null)
				{
					continue;
				}
				try
				{
					PlayerInfoEvent val = PlayerInfoEvent.Create(connection, (ReliabilityModes)2);
					if (val != null)
					{
						val.PlayerName = "CAMP_STATE";
						((Event)val).BinaryData = array;
						((Event)val).Send();
					}
				}
				catch
				{
				}
			}
		}

		internal static List<TABSCampaignAsset> GetOfficialCampaigns()
		{
			List<TABSCampaignAsset> list = new List<TABSCampaignAsset>();
			try
			{
				ISaveLoaderService service = ServiceLocator.GetService<ISaveLoaderService>();
				foreach (TABSCampaignAsset allCampaign in ContentDatabase.Instance().GetAllCampaigns())
				{
					if (!((Object)(object)allCampaign == (Object)null) && !allCampaign.IsCustomCampaign && !allCampaign.IsModCampaign)
					{
						string text = ((allCampaign.Entity != null) ? allCampaign.Entity.UnlockKey : null);
						if (string.IsNullOrWhiteSpace(text) || service == null || service.HasUnlockedSecret(text))
						{
							list.Add(allCampaign);
						}
					}
				}
			}
			catch
			{
			}
			return list;
		}

		internal static bool ShouldReloadSceneForBoundLevel()
		{
			if (!GameRoomModeState.IsCampaign)
			{
				return false;
			}
			return GetBoundLevelIndex() != _lastSceneLoadedLevelIndex;
		}

		internal static void MarkSceneLoadedForBoundLevel()
		{
			_lastSceneLoadedLevelIndex = GetBoundLevelIndex();
		}

		private static int GetBoundLevelIndex()
		{
			return CampaignPlayerDataHolder._LevelIndex;
		}

		private static TABSCampaignLevelAsset TryGetBoundLevel()
		{
			try
			{
				return CampaignPlayerDataHolder.GetCurrentLevel();
			}
			catch
			{
				return null;
			}
		}

		private static void UiMapSelectorStartPostfix(UIMapSelector __instance)
		{
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Expected O, but got Unknown
			if (!GameRoomModeState.IsCampaign || (Object)(object)__instance == (Object)null)
			{
				return;
			}
			TABSCampaignAsset selectedCampaign = CampaignPlayerDataHolder.SelectedCampaign;
			TABSCampaignLevelAsset[] array = (((Object)(object)selectedCampaign != (Object)null) ? selectedCampaign.LevelsInCampaign : null);
			if (array == null || array.Length == 0)
			{
				return;
			}
			__instance.ClearMaps();
			__instance.ChangeName("Levels");
			TABSCampaignLevelAsset val = TryGetBoundLevel();
			for (int i = 0; i < array.Length; i++)
			{
				TABSCampaignLevelAsset val2 = array[i];
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				bool flag = (Object)(object)val != (Object)null && val.Entity != null && val2.Entity != null && val.Entity.GUID == val2.Entity.GUID;
				int index = i;
				__instance.AddMapButton((val2.Entity != null) ? val2.Entity.Name : ModL10n.F("level_n", i + 1), (UnityAction)delegate
				{
					if (BoltNetwork.IsServer)
					{
						HostLoadLevel(index);
					}
				}, flag, true, false);
			}
			__instance.SetUpExplicitVerticalNavigation();
		}

		private static bool GetGameModeUiPrefix(MapSelectionCanvas __instance)
		{
			if (!GameRoomModeState.IsCampaign)
			{
				return true;
			}
			try
			{
				if ((Object)(object)__instance.SandboxUI != (Object)null)
				{
					__instance.SandboxUI.SetActive(false);
				}
				if ((Object)(object)__instance.CampaignUI != (Object)null)
				{
					__instance.CampaignUI.SetActive(true);
					Paginator component = __instance.CampaignUI.GetComponent<Paginator>();
					if (component != null)
					{
						component.OpenPage();
					}
				}
			}
			catch
			{
			}
			return false;
		}

		private static bool SetLevelGridPrefix(LevelSelection __instance)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			if (!GameRoomModeState.IsCampaign)
			{
				return true;
			}
			try
			{
				((LevelSelector)__instance).levelType = (LevelType)2;
				__instance.m_SelectedCampaignLevel = CampaignPlayerDataHolder.SelectedCampaign;
				((Paginator)__instance).OpenPage();
			}
			catch
			{
			}
			return false;
		}

		private static void SpawnCampaignLevelCellPrefix(ref bool unlocked, ref bool newLevel)
		{
			if (GameRoomModeState.IsCampaign)
			{
				unlocked = true;
				newLevel = false;
			}
		}

		private static bool StartedPlayingNewCampaignPrefix(TABSCampaignAsset newCampaign, int startIndex)
		{
			if (!GameRoomModeState.IsCampaign || !BoltNetwork.IsRunning)
			{
				return true;
			}
			Bind(newCampaign, startIndex);
			return false;
		}

		private static bool LoadCampaignPrefix()
		{
			if (!GameRoomModeState.IsCampaign || !BoltNetwork.IsRunning)
			{
				return true;
			}
			if (BoltNetwork.IsServer)
			{
				HostLoadCurrentBoundLevel();
			}
			return false;
		}

		private static bool LoadCampaignLevelWithIndexPrefix(int index)
		{
			if (!GameRoomModeState.IsCampaign || !BoltNetwork.IsRunning)
			{
				return true;
			}
			if (BoltNetwork.IsServer)
			{
				HostLoadLevel(index);
			}
			return false;
		}

		private static bool LoadNextCampaignLevelPrefix()
		{
			if (!GameRoomModeState.IsCampaign || !BoltNetwork.IsRunning)
			{
				return true;
			}
			if (BoltNetwork.IsServer)
			{
				int num = GetBoundLevelIndex() + 1;
				TABSCampaignAsset selectedCampaign = CampaignPlayerDataHolder.SelectedCampaign;
				if (((selectedCampaign != null) ? selectedCampaign.LevelsInCampaign : null) != null && num < selectedCampaign.LevelsInCampaign.Length)
				{
					HostLoadLevel(num);
				}
			}
			return false;
		}

		private static void EnterPlacementStatePostfix(PlacementUI __instance)
		{
			if (GameRoomModeState.IsCampaign && !((Object)(object)__instance == (Object)null))
			{
				HideBluePlacementUi(__instance);
			}
		}

		private static void ShowUiPostfix(PlacementUI __instance)
		{
			if (GameRoomModeState.IsCampaign && !((Object)(object)__instance == (Object)null))
			{
				HideBluePlacementUi(__instance);
			}
		}

		private static void HideBluePlacementUi(PlacementUI ui)
		{
			try
			{
				if ((Object)(object)ui.blueMoney != (Object)null)
				{
					((Component)ui.blueMoney).gameObject.SetActive(false);
				}
				if ((Object)(object)ui.m_ClearBlueObject != (Object)null)
				{
					ui.m_ClearBlueObject.SetActive(false);
				}
			}
			catch
			{
			}
		}

		private static bool FactionBarSpawnPrefix(PlacementFactionBar __instance)
		{
			if (!GameRoomModeState.IsCampaign)
			{
				return true;
			}
			TABSCampaignLevelAsset val = TryGetBoundLevel();
			Faction[] array = null;
			if ((Object)(object)val != (Object)null && val.AllowedFactions != null && val.AllowedFactions.Length != 0)
			{
				array = val.AllowedFactions.Where((Faction f) => (Object)(object)f != (Object)null && f.Entity != null && (Object)(object)ContentDatabase.Instance().GetFaction(f.Entity.GUID) != (Object)null).ToArray();
			}
			if (array == null || array.Length == 0)
			{
				try
				{
					array = ServiceLocator.GetService<ISaveLoaderService>().GetFactionBar();
				}
				catch
				{
				}
			}
			if (array == null)
			{
				return true;
			}
			try
			{
				List<FactionButton> list = (__instance.factionButtons = new List<FactionButton>());
				int num = 0;
				Faction[] array2 = array;
				foreach (Faction val2 in array2)
				{
					if (!((Object)(object)val2 == (Object)null))
					{
						FactionButton val3 = __instance.SpawnFaction(val2, num);
						if ((Object)(object)val3 != (Object)null)
						{
							list.Add(val3);
						}
						num++;
					}
				}
				__instance.FixExpandButton(false);
			}
			catch
			{
			}
			return false;
		}

		private static void SpawnFactionPostfix(Faction faction, FactionButton __result)
		{
			if (GameRoomModeState.IsCampaign && !((Object)(object)__result == (Object)null) && !((Object)(object)faction == (Object)null))
			{
				__result.SetUnlocked(IsCampaignFactionUnlocked(faction));
			}
		}

		internal static bool IsUnitAllowedOnBoundLevel(UnitBlueprint unit)
		{
			TABSCampaignLevelAsset val = TryGetBoundLevel();
			if ((Object)(object)val == (Object)null || (Object)(object)unit == (Object)null)
			{
				return true;
			}
			try
			{
				return val.IsAllowed(unit);
			}
			catch
			{
				return true;
			}
		}

		private static bool DrawFactionUnitPrefix(PlacementUI __instance, UnitBlueprint unit, bool secretUnlocked)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			if (!GameRoomModeState.IsCampaign || (Object)(object)__instance == (Object)null)
			{
				return true;
			}
			bool flag = secretUnlocked && IsUnitAllowedOnBoundLevel(unit);
			UILayoutGroup unitLayoutGroup = __instance.unitLayoutGroup;
			if (unitLayoutGroup != null)
			{
				unitLayoutGroup.AddElement(new UnitButtonData(unit, (IPlacementUI)(object)__instance, flag, !secretUnlocked));
			}
			return false;
		}

		private static bool AssignInitialUnitToBrushPrefix(PlacementUI __instance)
		{
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			if (!GameRoomModeState.IsCampaign || (Object)(object)__instance == (Object)null)
			{
				return true;
			}
			try
			{
				object obj = TryGetBoundLevel()?.AllowedUnits?.FirstOrDefault((Func<UnitBlueprint, bool>)((UnitBlueprint u) => (Object)(object)u != (Object)null));
				if (obj == null)
				{
					ContentDatabase unitDatabase = __instance.m_unitDatabase;
					obj = ((unitDatabase != null) ? unitDatabase.GetUserUnitBlueprintByExactName("UNIT_TRIBAL_CLUB") : null);
				}
				UnitBlueprint val = (UnitBlueprint)obj;
				if ((Object)(object)val != (Object)null && __instance.m_unitPlacementBrush != null)
				{
					if (val.Entity != null)
					{
						__instance.m_unitPlacementBrush.SetBrushUnit(val.Entity.GUID);
					}
					BattleRadialMenu radialMenu = __instance.m_RadialMenu;
					if (radialMenu != null)
					{
						radialMenu.SetSelectedUnit(val);
					}
				}
			}
			catch
			{
			}
			return false;
		}

		private static void BattleRadialButtonUpdateDataPostfix(BattleRadialButton __instance)
		{
			if (!GameRoomModeState.IsCampaign || (Object)(object)__instance == (Object)null)
			{
				return;
			}
			IDatabaseEntity currentData = __instance.CurrentData;
			UnitBlueprint val = (UnitBlueprint)(object)((currentData is UnitBlueprint) ? currentData : null);
			if (val != null)
			{
				bool flag = IsUnitAllowedOnBoundLevel(val);
				if (val.IsSecret)
				{
					try
					{
						DatabaseEntity entity = val.Entity;
						string text = ((entity != null) ? entity.UnlockKey : null);
						ISaveLoaderService service = ServiceLocator.GetService<ISaveLoaderService>();
						flag = flag && service != null && !string.IsNullOrEmpty(text) && service.HasUnlockedSecret(text);
					}
					catch
					{
					}
				}
				if (!flag)
				{
					__instance.HideCostUI();
				}
				__instance.SetUnlockedState(flag);
			}
			else
			{
				IDatabaseEntity currentData2 = __instance.CurrentData;
				Faction val2 = (Faction)(object)((currentData2 is Faction) ? currentData2 : null);
				if (val2 != null)
				{
					__instance.SetUnlockedState(IsCampaignFactionUnlocked(val2));
				}
			}
		}

		private static bool BuildCachesPrefix(BattleRadialMenu __instance)
		{
			if (!GameRoomModeState.IsCampaign || (Object)(object)__instance == (Object)null || (Object)(object)TryGetBoundLevel() == (Object)null)
			{
				return true;
			}
			try
			{
				__instance.factionCache?.Clear();
				__instance.addFactionsFactionCache?.Clear();
				__instance.SetUpFactionsForCampaign();
			}
			catch
			{
			}
			return false;
		}

		private static bool IsCampaignFactionUnlocked(Faction faction)
		{
			if ((Object)(object)faction == (Object)null)
			{
				return true;
			}
			try
			{
				GlobalSettingsHandler service = ServiceLocator.GetService<GlobalSettingsHandler>();
				SettingsInstance val = ((service != null) ? service.GetSettingsInstance("GAMEPLAY_RESTRICT_UNITS") : null);
				if (val != null && val.currentValue == 1)
				{
					return true;
				}
			}
			catch
			{
			}
			UnitBlueprint[] units = faction.Units;
			if (units == null || units.Length == 0)
			{
				return true;
			}
			return units.Any((UnitBlueprint u) => (Object)(object)u != (Object)null && IsUnitAllowedOnBoundLevel(u));
		}

		private static void OnEnterNewScenePostfix()
		{
			if (GameRoomModeState.IsCampaign)
			{
				TABSCampaignLevelAsset val = TryGetBoundLevel();
				if ((Object)(object)val != (Object)null)
				{
					SetLastLoadedLevel(val);
				}
				MarkSceneLoadedForBoundLevel();
			}
		}
	}
	internal class CampaignSelectionUI : MonoBehaviour
	{
		private class CampaignRow
		{
			public TABSCampaignAsset Asset;

			public Sprite Icon;
		}

		internal static CampaignSelectionUI Instance;

		private bool visible;

		private Vector2 scroll;

		private GUIStyle windowStyle;

		private GUIStyle labelStyle;

		private GUIStyle buttonStyle;

		private readonly List<CampaignRow> rows = new List<CampaignRow>();

		private Action<TABSCampaignAsset> onSelected;

		private Action onCancelled;

		public static void Ensure()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			if (!((Object)(object)Instance != (Object)null))
			{
				GameObject val = new GameObject("Multiplayer16_CampaignSelectionUI");
				Object.DontDestroyOnLoad((Object)val);
				Instance = val.AddComponent<CampaignSelectionUI>();
			}
		}

		public void Show(Action<TABSCampaignAsset> selected, Action cancelled)
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			onSelected = selected;
			onCancelled = cancelled;
			rows.Clear();
			List<TABSCampaignAsset> officialCampaigns = CampaignModeSystem.GetOfficialCampaigns();
			for (int i = 0; i < officialCampaigns.Count; i++)
			{
				if (!((Object)(object)officialCampaigns[i] == (Object)null))
				{
					rows.Add(new CampaignRow
					{
						Asset = officialCampaigns[i]
					});
				}
			}
			LoadIcons();
			visible = true;
			scroll = Vector2.zero;
		}

		private void LoadIcons()
		{
			for (int i = 0; i < rows.Count; i++)
			{
				int idx = i;
				CampaignRow campaignRow = rows[i];
				TABSCampaignAsset asset = campaignRow.Asset;
				if (((asset != null) ? asset.Entity : null) == null)
				{
					continue;
				}
				try
				{
					Sprite levelCellSpriteIcon = asset.Entity.LevelCellSpriteIcon;
					if ((Object)(object)levelCellSpriteIcon != (Object)null)
					{
						campaignRow.Icon = levelCellSpriteIcon;
					}
				}
				catch
				{
				}
				asset.Entity.GetSpriteIconAsync((Action<Sprite>)delegate(Sprite sprite)
				{
					if ((Object)(object)sprite != (Object)null && idx < rows.Count && (Object)(object)rows[idx].Icon == (Object)null)
					{
						rows[idx].Icon = sprite;
					}
				});
				try
				{
					Sprite campaignSprite = CampaignHandler.GetCampaignSprite(asset);
					if ((Object)(object)campaignSprite != (Object)null && (Object)(object)campaignRow.Icon == (Object)null)
					{
						campaignRow.Icon = campaignSprite;
					}
				}
				catch
				{
				}
				TABSCampaignLevelAsset[] levelsInCampaign = asset.LevelsInCampaign;
				if (!((Object)(object)campaignRow.Icon == (Object)null) || levelsInCampaign == null || levelsInCampaign.Length == 0)
				{
					continue;
				}
				TABSCampaignLevelAsset obj3 = levelsInCampaign[0];
				if (((obj3 != null) ? obj3.Entity : null) == null)
				{
					continue;
				}
				try
				{
					Sprite levelCellSpriteIcon2 = levelsInCampaign[0].Entity.LevelCellSpriteIcon;
					if ((Object)(object)levelCellSpriteIcon2 != (Object)null)
					{
						campaignRow.Icon = levelCellSpriteIcon2;
					}
				}
				catch
				{
				}
				levelsInCampaign[0].Entity.GetSpriteIconAsync((Action<Sprite>)delegate(Sprite sprite)
				{
					if ((Object)(object)sprite != (Object)null && idx < rows.Count && (Object)(object)rows[idx].Icon == (Object)null)
					{
						rows[idx].Icon = sprite;
					}
				});
			}
		}

		private void Update()
		{
			if (visible && Input.GetKeyDown((KeyCode)27))
			{
				visible = false;
				onCancelled?.Invoke();
			}
		}

		private void OnGUI()
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			if (visible)
			{
				EnsureStyles();
				Rect val = default(Rect);
				((Rect)(ref val))..ctor((float)(Screen.width / 2 - 400), (float)(Screen.height / 2 - 300), 800f, 600f);
				val = GUILayout.Window(12351, val, new WindowFunction(DrawWindow), ModL10n.T("select_official_campaign"), windowStyle ?? GUI.skin.window, Array.Empty<GUILayoutOption>());
			}
		}

		private void DrawWindow(int id)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			GUIStyle val = labelStyle ?? GUI.skin.label;
			GUIStyle val2 = buttonStyle ?? GUI.skin.button;
			GUILayout.Label(ModL10n.T("campaign_from_first"), val, Array.Empty<GUILayoutOption>());
			scroll = GUILayout.BeginScrollView(scroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(480f) });
			for (int i = 0; i < rows.Count; i++)
			{
				CampaignRow campaignRow = rows[i];
				TABSCampaignAsset val3 = campaignRow?.Asset;
				if (!((Object)(object)val3 == (Object)null))
				{
					string text = ((val3.Entity != null) ? val3.Entity.Name : ModL10n.T("campaign_fallback"));
					GUILayout.BeginHorizontal(GUIStyle.op_Implicit("box"), Array.Empty<GUILayoutOption>());
					if ((Object)(object)campaignRow.Icon != (Object)null && (Object)(object)campaignRow.Icon.texture != (Object)null)
					{
						GUILayout.Label((Texture)(object)campaignRow.Icon.texture, (GUILayoutOption[])(object)new GUILayoutOption[2]
						{
							GUILayout.Width(64f),
							GUILayout.Height(64f)
						});
					}
					else
					{
						GUILayout.Label("", (GUILayoutOption[])(object)new GUILayoutOption[2]
						{
							GUILayout.Width(64f),
							GUILayout.Height(64f)
						});
					}
					GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
					GUILayout.Label(text, val, Array.Empty<GUILayoutOption>());
					int num = ((val3.LevelsInCampaign != null) ? val3.LevelsInCampaign.Length : 0);
					GUILayout.Label(ModL10n.F("level_count", num), val, Array.Empty<GUILayoutOption>());
					GUILayout.EndVertical();
					GUILayout.FlexibleSpace();
					if (GUILayout.Button(ModL10n.T("select"), val2, (GUILayoutOption[])(object)new GUILayoutOption[2]
					{
						GUILayout.Width(80f),
						GUILayout.Height(64f)
					}))
					{
						visible = false;
						onSelected?.Invoke(val3);
						GUILayout.EndHorizontal();
						GUILayout.EndScrollView();
						return;
					}
					GUILayout.EndHorizontal();
					GUILayout.Space(5f);
				}
			}
			if (rows.Count == 0)
			{
				GUILayout.Label(ModL10n.T("no_campaigns"), val, Array.Empty<GUILayoutOption>());
			}
			GUILayout.EndScrollView();
			if (GUILayout.Button(ModL10n.T("cancel"), val2, Array.Empty<GUILayoutOption>()))
			{
				visible = false;
				onCancelled?.Invoke();
			}
			GUI.DragWindow();
		}

		private void EnsureStyles()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			if (windowStyle == null)
			{
				windowStyle = new GUIStyle(GUI.skin.window)
				{
					fontSize = 16
				};
				labelStyle = new GUIStyle(GUI.skin.label)
				{
					fontSize = 14,
					wordWrap = true
				};
				buttonStyle = new GUIStyle(GUI.skin.button)
				{
					fontSize = 14
				};
			}
		}
	}
	internal static class CavalryPossessionPatches
	{
		internal const int MountLookForceWeapon = 123;

		internal const int MountDismountForceWeapon = 131;

		private const float MountLookSendInterval = 0.05f;

		private static Harmony _harmony;

		private static bool _applyingHostDismount;

		private static readonly HashSet<Mount> TrackedMounts = new HashSet<Mount>();

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

		private static readonly Dictionary<int, Unit> LocalRiderMounts = new Dictionary<int, Unit>();

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

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

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

		private static readonly Dictionary<int, Vector3> RemoteMountLook = new Dictionary<int, Vector3>();

		private static readonly Dictionary<int, Vector3> RemoteMountInput = new Dictionary<int, Vector3>();

		private static readonly Dictionary<int, float> LastMountLookSend = new Dictionary<int, float>();

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

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

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

		private static readonly Dictionary<int, List<Unit>> LocalRiderCluster = new Dictionary<int, List<Unit>>();

		private static readonly List<Unit> ClusterBuf = new List<Unit>(16);

		private static readonly List<Unit> PossessTargetBuf = new List<Unit>(16);

		private static readonly List<Unit> PossessableBuf = new List<Unit>(8);

		private static readonly List<Unit> UnlinkSnapshot = new List<Unit>(16);

		private static readonly Dictionary<int, float> LastDismountSend = new Dictionary<int, float>();

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

		private const float DismountSendInterval = 0.15f;

		private static Unit _exitingRider;

		public static void ApplyPatches()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Expected O, but got Unknown
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Expected O, but got Unknown
			//IL_00d8: Expected O, but got Unknown
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Expected O, but got Unknown
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Expected O, but got Unknown
			//IL_0176: Expected O, but got Unknown
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Expected O, but got Unknown
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Expected O, but got Unknown
			//IL_022c: Expected O, but got Unknown
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Expected O, but got Unknown
			//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02db: Expected O, but got Unknown
			//IL_0334: Unknown result type (might be due to invalid IL or missing references)
			//IL_0342: Expected O, but got Unknown
			//IL_037c: Unknown result type (might be due to invalid IL or missing references)
			//IL_038a: Expected O, but got Unknown
			//IL_03c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d2: Expected O, but got Unknown
			//IL_041f: Unknown result type (might be due to invalid IL or missing references)
			//IL_042c: Expected O, but got Unknown
			_harmony = new Harmony("Multiplayer16.CavalryPossession");
			MethodInfo methodInfo = AccessTools.Method(typeof(Mount), "EnterMount", new Type[3]
			{
				typeof(UnitBlueprint),
				typeof(Unit),
				typeof(int)
			}, (Type[])null);
			if (methodInfo != null)
			{
				_harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(CavalryPossessionPatches), "EnterMountPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo methodInfo2 = AccessTools.Method(typeof(Mount), "Update", (Type[])null, (Type[])null);
			if (methodInfo2 != null)
			{
				_harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(typeof(CavalryPossessionPatches), "MountUpdatePrefix", (Type[])null), new HarmonyMethod(typeof(CavalryPossessionPatches), "MountUpdatePostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo methodInfo3 = AccessTools.Method(typeof(MovementHandler), "BatchedFixedUpdate", (Type[])null, (Type[])null);
			if (methodInfo3 != null)
			{
				_harmony.Patch((MethodBase)methodInfo3, new HarmonyMethod(typeof(CavalryPossessionPatches), "MovementHandlerFixedPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo methodInfo4 = AccessTools.Method(typeof(Mount), "Fall", (Type[])null, (Type[])null);
			if (methodInfo4 != null)
			{
				_harmony.Patch((MethodBase)methodInfo4, new HarmonyMethod(typeof(CavalryPossessionPatches), "FallPrefix", (Type[])null), new HarmonyMethod(typeof(CavalryPossessionPatches), "FallPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo methodInfo5 = AccessTools.Method(typeof(CameraAbilityPossess), "EnterUnit", new Type[1] { typeof(Unit) }, (Type[])null);
			if (methodInfo5 != null)
			{
				_harmony.Patch((MethodBase)methodInfo5, (HarmonyMethod)null, new HarmonyMethod(typeof(CavalryPossessionPatches), "EnterUnitPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo methodInfo6 = AccessTools.Method(typeof(CameraAbilityPossess), "ExitUnit", (Type[])null, (Type[])null);
			if (methodInfo6 != null)
			{
				_harmony.Patch((MethodBase)methodInfo6, new HarmonyMethod(typeof(CavalryPossessionPatches), "ExitUnitPrefix", (Type[])null), new HarmonyMethod(typeof(CavalryPossessionPatches), "ExitUnitPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo methodInfo7 = AccessTools.Method(typeof(NetworkUnit), "OnEnterPossession", (Type[])null, (Type[])null);
			if (methodInfo7 != null)
			{
				_harmony.Patch((MethodBase)methodInfo7, (HarmonyMethod)null, new HarmonyMethod(typeof(CavalryPossessionPatches), "NetworkUnitOnEnterPossessionPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo methodInfo8 = AccessTools.Method(typeof(UnitAPI), "SetLookDirection", new Type[2]
			{
				typeof(Vector3),
				typeof(bool)
			}, (Type[])null);
			if (methodInfo8 != null)
			{
				_harmony.Patch((MethodBase)methodInfo8, new HarmonyMethod(typeof(CavalryPossessionPatches), "SetLookDirectionPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo methodInfo9 = AccessTools.Method(typeof(UnitAPI), "SetMovementSpeed", new Type[2]
			{
				typeof(float),
				typeof(bool)
			}, (Type[])null);
			if (methodInfo9 != null)
			{
				_harmony.Patch((MethodBase)methodInfo9, new HarmonyMethod(typeof(CavalryPossessionPatches), "SetMovementSpeedPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo methodInfo10 = AccessTools.Method(typeof(NetworkUnit), "UpdateLookDirection", (Type[])null, (Type[])null);
			if (methodInfo10 != null)
			{
				_harmony.Patch((MethodBase)methodInfo10, new HarmonyMethod(typeof(CavalryPossessionPatches), "UpdateLookDirectionPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo methodInfo11 = AccessTools.Method(typeof(GeneralInput), "Update", (Type[])null, (Type[])null);
			if (methodInfo11 != null)
			{
				_harmony.Patch((MethodBase)methodInfo11, new HarmonyMethod(typeof(CavalryPossessionPatches), "GeneralInputUpdatePrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo methodInfo12 = AccessTools.Method(typeof(PossessedNetworkUnit), "OnEnterPossession", new Type[1] { typeof(Unit) }, (Type[])null);
			if (methodInfo12 != null)
			{
				_harmony.Patch((MethodBase)methodInfo12, (HarmonyMethod)null, new HarmonyMethod(typeof(CavalryPossessionPatches), "PossessedNetworkUnitEnterPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			Debug.Log((object)"[Multiplayer16] CavalryPossessionPatches: 已 Patch 骑兵坐骑附身朝向");
		}

		private static void PossessedNetworkUnitEnterPostfix(PossessedNetworkUnit __instance, Unit unit)
		{
			if ((Object)(object)__instance == (Object)null || !ShouldSkipPossessorPnuBind(unit))
			{
				return;
			}
			try
			{
				__instance.OnExitPossession(unit);
			}
			catch
			{
			}
		}

		private static void EnterMountPostfix(Mount __instance)
		{
			if ((Object)(object)__instance != (Object)null)
			{
				TrackedMounts.Add(__instance);
			}
			Unit val = (((Object)(object)__instance != (Object)null) ? ((Component)__instance).GetComponent<Unit>() : null);
			if ((Object)(object)val != (Object)null)
			{
				DismountHandledRiders.Remove(val.InstanceId);
				LastDismountSend.Remove(val.InstanceId);
				if ((Object)(object)__instance.OtherData != (Object)null && (Object)(object)__instance.OtherData.unit != (Object)null)
				{
					DismountHandledRiders.Remove(__instance.OtherData.unit.InstanceId);
				}
			}
			if (ShouldSkipPossessorPnuBind(val))
			{
				PossessionSync.UnbindPossessorPnu(val);
			}
		}

		private static void EnterUnitPostfix(Unit unitAPI)
		{
			if ((Object)(object)unitAPI != (Object)null)
			{
				DismountHandledRiders.Remove(unitAPI.InstanceId);
				ReleasedRiders.Remove(unitAPI.InstanceId);
			}
			DisableMountAiForRider(unitAPI);
			if (IsMountedOverrideRider(unitAPI) && IsLocallyPossessed(unitAPI))
			{
				GeneralInput componentInChildren = ((Component)unitAPI).GetComponentInChildren<GeneralInput>();
				if ((Object)(object)componentInChildren != (Object)null)
				{
					componentInChildren.AllowRotationChange = true;
					componentInChildren.hasControl = true;
				}
			}
			if (BoltNetwork.IsClient && !BoltNetwork.IsServer)
			{
				TakeLocalMountControl(unitAPI);
				LinkedPossessionSync.BeginClient(unitAPI);
			}
		}

		private static void ExitUnitPrefix(CameraAbilityPossess __instance)
		{
			_exitingRider = __instance?.currentUnit;
		}

		private static void ExitUnitPostfix()
		{
			LinkedPossessionSync.EndClient();
			ReleaseLocalMountControl(_exitingRider);
			RestoreAfterPossession(_exitingRider);
			_exitingRider = null;
		}

		private static void NetworkUnitOnEnterPossessionPostfix(NetworkUnit __instance)
		{
			Unit val = (((Object)(object)__instance != (Object)null) ? __instance.Unit : null);
			if ((Object)(object)val != (Object)null)
			{
				ReleasedRiders.Remove(val.InstanceId);
			}
			DisableMountAiForRider(val);
		}

		private static bool SetMovementSpeedPrefix(UnitAPI __instance)
		{
			if ((Object)(object)__instance == (Object)null)
			{
				return true;
			}
			Unit component = ((Component)__instance).GetComponent<Unit>();
			if ((Object)(object)component == (Object)null)
			{
				return true;
			}
			if (IsPlayerSteeredMount(component))
			{
				return false;
			}
			if (IsMountedOverrideRider(component) && ShouldDrivePossessedMountLook(component))
			{
				return false;
			}
			if (IsUnpossessedOverrideMount(component))
			{
				return false;
			}
			return true;
		}

		private static void GeneralInputUpdatePrefix(GeneralInput __instance)
		{
			if ((Object)(object)__instance == (Object)null || !BoltNetwork.IsRunning)
			{
				return;
			}
			Unit val = null;
			try
			{
				DataHandler val2 = ((Component)__instance).GetComponent<DataHandler>();
				if ((Object)(object)val2 == (Object)null)
				{
					val2 = ((Component)__instance).GetComponentInParent<DataHandler>();
				}
				val = (((Object)(object)val2 != (Object)null) ? val2.unit : null);
			}
			catch
			{
			}
			if ((Object)(object)val == (Object)null || IsLocallyPossessed(val))
			{
				return;
			}
			Unit riderFromMountUnit = GetRiderFromMountUnit(val);
			if (!((Object)(object)riderFromMountUnit != (Object)null) || !IsLocallyPossessed(riderFromMountUnit))
			{
				if (IsUnpossessedOverrideMount(val))
				{
					__instance.hasControl = false;
				}
				else if (IsPlayerSteeredMount(val) && !LocalControlledMountIds.Contains(val.InstanceId))
				{
					__instance.hasControl = false;
				}
				else if (IsMountedOverrideRider(val) && ShouldDrivePossessedMountLook(val) && !IsLocallyPossessed(val))
				{
					__instance.hasControl = false;
				}
			}
		}

		private static bool SetLookDirectionPrefix(UnitAPI __instance)
		{
			if ((Object)(object)__instance == (Object)null)
			{
				return true;
			}
			Unit component = ((Component)__instance).GetComponent<Unit>();
			if ((Object)(object)component == (Object)null)
			{
				return true;
			}
			if (ReleasedRiders.Contains(component.InstanceId))
			{
				return true;
			}
			if (IsPlayerSteeredMount(component))
			{
				return false;
			}
			if (IsMountedOverrideRider(component) && ShouldDrivePossessedMountLook(component))
			{
				return false;
			}
			if (IsUnpossessedOverrideMount(component))
			{
				return false;
			}
			return true;
		}

		private static bool UpdateLookDirectionPrefix(NetworkUnit __instance)
		{
			Unit val = (((Object)(object)__instance != (Object)null) ? __instance.Unit : null);
			if ((Object)(object)val == (Object)null)
			{
				return true;
			}
			if (!IsMountOfPossessedRider(val))
			{
				return true;
			}
			return !ShouldDrivePossessedMountLook(GetRiderFromMountUnit(val));
		}

		private static bool ShouldDrivePossessedMountLook(Unit rider)
		{
			if ((Object)(object)rider == (Object)null)
			{
				return false;
			}
			if (ReleasedRiders.Contains(rider.InstanceId))
			{
				return false;
			}
			if (DismountHandledRiders.Contains(rider.InstanceId))
			{
				return false;
			}
			if (IsLocallyPossessed(rider))
			{
				Mount component = ((Component)rider).GetComponent<Mount>();
				if ((Object)(object)component != (Object)null && !component.IsMounted)
				{
					return false;
				}
				return true;
			}
			if (HostClientSteeredRiders.Contains(rider.InstanceId))
			{
				return true;
			}
			if (BoltNetwork.IsRunning && BoltNetwork.IsServer)
			{
				return PossessionSync.IsUnitPossessedByAnyone(rider);
			}
			return false;
		}

		private static bool FallPrefix(Mount __instance)
		{
			if ((Object)(object)__instance == (Object)null)
			{
				return true;
			}
			if (BoltNetwork.IsServer && __instance.IsMounted)
			{
				SnapshotUnlinkTargets(__instance);
			}
			if (_applyingHostDismount)
			{
				return true;
			}
			if (SoftLinkBroken(__instance))
			{
				return true;
			}
			if (!BoltNetwork.IsRunning || !BoltNetwork.IsClient || BoltNetwork.IsServer)
			{
				return true;
			}
			if (!__instance.IsMounted || !OverridesMountInput(__instance))
			{
				return true;
			}
			Unit component = ((Component)__instance).GetComponent<Unit>();
			if (!IsLocallyPossessed(component) && !IsObservingRemoteCavalry(component))
			{
				return true;
			}
			return false;
		}

		private static void FallPostfix(Mount __instance)
		{
			if (!((Object)(object)__instance == (Object)null) && !__instance.IsMounted)
			{
				Unit component = ((Component)__instance).GetComponent<Unit>();
				if ((Object)(object)component != (Object)null)
				{
					SoftLinkArmedIds.Remove(component.InstanceId);
				}
				Unit mountUnit = (((Object)(object)__instance.OtherData != (Object)null) ? __instance.OtherData.unit : null);
				HandlePossessedDismount(component, mountUnit);
				if (BoltNetwork.IsServer)
				{
					SendHostDismountToClients(component, mountUnit);
				}
				else if (BoltNetwork.IsClient && !_applyingHostDismount)
				{
					SendDismountToHost(component, mountUnit);
				}
			}
		}

		private static bool IsPlayerControlledCavalry(Unit rider)
		{
			if ((Object)(object)rider == (Object)null)
			{
				return false;
			}
			if (ReleasedRiders.Contains(rider.InstanceId))
			{
				return false;
			}
			if (ShouldDrivePossessedMountLook(rider))
			{
				return true;
			}
			if (IsObservingRemoteCavalry(rider))
			{
				return true;
			}
			if (BoltNetwork.IsRunning)
			{
				return PossessionSync.IsUnitPossessedByAnyone(rider);
			}
			return false;
		}

		private static bool IsUnpossessedOverrideMount(Unit mountUnit)
		{
			if ((Object)(object)mountUnit == (Object)null)
			{
				return false;
			}
			Mount mountForUnit = GetMountForUnit(mountUnit);
			if ((Object)(object)mountForUnit == (Object)null || !mountForUnit.IsMounted || !OverridesMountInput(mountForUnit))
			{
				return false;
			}
			return !IsPlayerControlledCavalry(((Component)mountForUnit).GetComponent<Unit>());
		}

		private static bool IsPlayerPossessedUnit(Unit unit)
		{
			if ((Object)(object)unit == (Object)null)
			{
				return false;
			}
			try
			{
				if ((Object)(object)unit.api != (Object)null && unit.api.IsPossessed)
				{
					return true;
				}
			}
			catch
			{
			}
			if (!PossessionSync.IsUnitPossessedByLocalPlayer(unit))
			{
				return PossessionSync.IsUnitPossessedByAnyone(unit);
			}
			return true;
		}

		private static bool IsOtherPossessedUnit(Unit unit, Unit subject)
		{
			if (!IsPlayerPossessedUnit(unit))
			{
				return false;
			}
			if ((Object)(object)subject == (Object)null)
			{
				return true;
			}
			if (unit.InstanceId == subject.InstanceId)
			{
				return false;
			}
			if (unit.RemoteInstanceId != 0 && unit.RemoteInstanceId == subject.InstanceId)
			{
				return false;
			}
			if (subject.RemoteInstanceId != 0 && subject.RemoteInstanceId == unit.InstanceId)
			{
				return false;
			}
			return true;
		}

		private static void RestoreMountMovementAi(Mount mount)
		{
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)mount == (Object)null || !mount.IsMounted || IsOtherPossessedUnit(((Object)(object)mount.OtherData != (Object)null) ? mount.OtherData.unit : null, null))
			{
				return;
			}
			UnitAPI mountApi = GetMountApi(mount);
			if ((Object)(object)mountApi != (Object)null)
			{
				if (IsOtherPossessedUnit(((Component)mountApi).GetComponent<Unit>(), null))
				{
					return;
				}
				if (!mountApi.IsPossessed)
				{
					mountApi.SetIsRemotelyControlled(false);
					mountApi.SetActive(true, (bool?)false);
				}
			}
			if ((Object)(object)mount.OtherData != (Object)null && (Object)(object)mount.OtherData.input != (Object)null)
			{
				mount.OtherData.input.hasControl = false;
				if (OverridesMountInput(mount))
				{
					mount.OtherData.input.inputDirection = Vector3.forward;
				}
			}
		}

		private static void MountUpdatePrefix(Mount __instance)
		{
			if ((Object)(object)__instance == (Object)null || !__instance.IsMounted)
			{
				return;
			}
			ArmSoftLinkIfNeeded(__instance);
			if (SoftLinkBroken(__instance))
			{
				TryFallFromSoftLink(__instance);
				return;
			}
			Unit component = ((Component)__instance).GetComponent<Unit>();
			if (!IsPlayerControlledCavalry(component))
			{
				Unit val = (((Object)(object)__instance.OtherData != (Object)null) ? __instance.OtherData.unit : null);
				if (!IsPlayerSteeredMount(val) && !IsOtherPossessedUnit(val, component) && OverridesMountInput(__instance))
				{
					RestoreMountMovementAi(__instance);
				}
			}
		}

		private static void MountUpdatePostfix(Mount __instance)
		{
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Invalid comparison between Unknown and I4
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0326: Unknown result type (might be due to invalid IL or missing references)
			//IL_031f: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			//IL_028e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02da: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance == (Object)null)
			{
				return;
			}
			if (!__instance.IsMounted)
			{
				Unit component = ((Component)__instance).GetComponent<Unit>();
				if ((Object)(object)component != (Object)null)
				{
					HandlePossessedDismount(component, ((Object)(object)__instance.OtherData != (Object)null) ? __instance.OtherData.unit : null);
				}
			}
			else
			{
				if (!OverridesMountInput(__instance))
				{
					return;
				}
				Unit component2 = ((Component)__instance).GetComponent<Unit>();
				DataHandler otherData = __instance.OtherData;
				if ((Object)(object)component2 == (Object)null || (Object)(object)otherData == (Object)null || (Object)(object)otherData.input == (Object)null)
				{
					return;
				}
				if (!IsPlayerControlledCavalry(component2))
				{
					Unit unit = otherData.unit;
					if (IsOtherPossessedUnit(unit, component2))
					{
						return;
					}
					if (IsPlayerSteeredMount(unit))
					{
						Unit val = ResolvePossessedRider(unit);
						if ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)component2)
						{
							Vector3 desired = Vector3.zero;
							if (!TryGetRemoteMountLook(val, out desired) && IsLocallyPossessed(val) && TryGetLocalLookRotation(out var look))
							{
								desired = look * Vector3.forward;
							}
							SteerCavalryCluster(val, desired, ((Component)val).GetComponentInChildren<GeneralInput>());
						}
					}
					else
					{
						RestoreMountMovementAi(__instance);
					}
					return;
				}
				if (IsObservingRemoteCavalry(component2))
				{
					ApplyObservedPossessionAiOff(component2);
					return;
				}
				if (!ShouldDrivePossessedMountLook(component2))
				{
					if (BoltNetwork.IsServer && PossessionSync.IsUnitPossessedByAnyone(component2))
					{
						DisableMountAi(__instance);
					}
					return;
				}
				GameStateManager service = ServiceLocator.GetService<GameStateManager>();
				if (service != null && (int)service.GameState != 1)
				{
					return;
				}
				DisableMountAi(__instance);
				if (IsLocallyPossessed(component2))
				{
					LockPossessedMountJoints(__instance);
				}
				if (BoltNetwork.IsServer)
				{
					if ((Object)(object)component2.data?.mainRig != (Object)null)
					{
						component2.data.mainRig.isKinematic = false;
					}
					if ((Object)(object)otherData.mainRig != (Object)null)
					{
						otherData.mainRig.isKinematic = false;
					}
				}
				GeneralInput componentInChildren = ((Component)component2).GetComponentInChildren<GeneralInput>();
				if ((Object)(object)componentInChildren != (Object)null && IsLocallyPossessed(component2))
				{
					componentInChildren.AllowRotationChange = true;
				}
				bool flag = false;
				Vector3 desired2;
				if (IsLocallyPossessed(component2) && TryGetLocalLookRotation(out var look2))
				{
					desired2 = look2 * Vector3.forward;
					SendMountControlToHost(component2, desired2, ((Object)(object)componentInChildren != (Object)null) ? componentInChildren.inputDirection : Vector3.zero);
					flag = true;
				}
				else
				{
					flag = TryGetRemoteMountLook(component2, out desired2);
				}
				if (flag)
				{
					desired2.y = 0f;
					if (((Vector3)(ref desired2)).sqrMagnitude > 0.0001f)
					{
						((Vector3)(ref desired2)).Normalize();
						Quaternion rotation = Quaternion.LookRotation(desired2);
						if ((Object)(object)otherData.input.Direction != (Object)null)
						{
							otherData.input.Direction.rotation = rotation;
						}
						if ((Object)(object)otherData.characterForwardObject != (Object)null)
						{
							otherData.characterForwardObject.rotation = rotation;
						}
						otherData.lookDirectionIntent = desired2;
						if ((Object)(object)componentInChildren != (Object)null && (Object)(object)componentInChildren.Direction != (Object)null)
						{
							componentInChildren.Direction.rotation = rotation;
						}
						if ((Object)(object)component2.data != (Object)null)
						{
							component2.data.lookDirectionIntent = desired2;
							if ((Object)(object)component2.data.characterForwardObject != (Object)null)
							{
								component2.data.characterForwardObject.rotation = rotation;
							}
						}
					}
				}
				KeepMountInput(otherData, component2);
				ApplyPossessedMountMove(otherData, component2, componentInChildren, GetMountPos(__instance));
				SteerCavalryCluster(component2, flag ? desired2 : Vector3.zero, componentInChildren);
			}
		}

		private static bool MovementHandlerFixedPrefix(MovementHandler __instance)
		{
			if (!BoltNetwork.IsRunning || (Object)(object)__instance == (Object)null)
			{
				return true;
			}
			DataHandler val = null;
			try
			{
				val = ((Component)__instance).GetComponent<DataHandler>();
			}
			catch
			{
			}
			if ((Object)(object)val?.unit == (Object)null || (Object)(object)val.input == (Object)null)
			{
				return true;
			}
			if (!IsChargeMountBody(val.unit) && !IsPlayerSteeredMount(val.unit))
			{
				return true;
			}
			if (!IsPossessedChargeMount(val.unit) && !IsPlayerSteeredMount(val.unit))
			{
				return true;
			}
			Unit val2 = GetRiderFromMountUnit(val.unit) ?? ResolvePossessedRider(val.unit);
			if ((Object)(object)val2 != (Object)null && IsObservingRemoteCavalry(val2))
			{
				return true;
			}
			if (!ShouldDrivePossessedMountLook(val2) && !IsLocallyControlledMount(val.unit) && !IsPlayerSteeredMount(val.unit))
			{
				return true;
			}
			KeepMountInput(val, val2);
			return true;
		}

		internal static Unit GetMountUnitFromRider(Unit rider)
		{
			if ((Object)(object)rider == (Object)null)
			{
				return null;
			}
			if (LocalRiderMounts.TryGetValue(rider.InstanceId, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			Mount component = ((Component)rider).GetComponent<Mount>();
			if ((Object)(object)component != (Object)null && (Object)(object)component.OtherData != (Object)null && (Object)(object)component.OtherData.unit != (Object)null)
			{
				return component.OtherData.