Decompiled source of Empress HostSwap v1.0.0

EmpressHostSwap.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Omniscye")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("EmpressHostSwap")]
[assembly: AssemblyTitle("EmpressHostSwap")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Empress.HostSwap
{
	[BepInPlugin("Omniscye.EmpressHostSwap", "EmpressHostSwap", "1.1.1")]
	public class EmpressHostSwap : BaseUnityPlugin
	{
		[CompilerGenerated]
		private sealed class <HostSwapRoutine>d__30 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public Player newMaster;

			public float delay;

			public EmpressHostSwap <>4__this;

			private float <t>5__1;

			private string <activeScene>5__2;

			private Exception <ex>5__3;

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

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

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

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<activeScene>5__2 = null;
				<ex>5__3 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_009c: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<t>5__1 = 0f;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if (<t>5__1 < delay)
				{
					<t>5__1 += Time.unscaledDeltaTime;
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				if (PhotonNetwork.LocalPlayer != null && newMaster != null && PhotonNetwork.LocalPlayer.ActorNumber == newMaster.ActorNumber)
				{
					Scene activeScene = SceneManager.GetActiveScene();
					<activeScene>5__2 = ((Scene)(ref activeScene)).name;
					Logger.LogInfo((object)("I am the new master. Reloading scene '" + <activeScene>5__2 + "' to rebuild authority and physics."));
					<>4__this._autoSyncPrev = PhotonNetwork.AutomaticallySyncScene;
					<>4__this._restoreAutoSync = true;
					PhotonNetwork.AutomaticallySyncScene = true;
					try
					{
						PhotonNetwork.LoadLevel(<activeScene>5__2);
					}
					catch (Exception ex)
					{
						<ex>5__3 = ex;
						Logger.LogError((object)$"Failed to PhotonNetwork.LoadLevel('{<activeScene>5__2}'): {<ex>5__3}");
						if (<>4__this._restoreAutoSync)
						{
							PhotonNetwork.AutomaticallySyncScene = <>4__this._autoSyncPrev;
							<>4__this._restoreAutoSync = false;
						}
					}
					<activeScene>5__2 = null;
				}
				else
				{
					Logger.LogInfo((object)"This client is not the new master; waiting for master-driven level sync.");
				}
				return false;
			}

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

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

		private ConfigEntry<bool> _autoReloadEnabled = null;

		private ConfigEntry<float> _reloadDelaySeconds = null;

		private ConfigEntry<bool> _showUi = null;

		private ConfigEntry<float> _uiYOffset = null;

		private ConfigEntry<float> _phase1FontSize = null;

		private ConfigEntry<float> _phase2FontSize = null;

		private bool swapActive;

		private float swapTimer;

		private string newHostName = string.Empty;

		private bool _restoreAutoSync;

		private bool _autoSyncPrev;

		private bool _basePosCaptured;

		private Vector2 _bigMsgBasePos;

		internal static EmpressHostSwap Instance { get; private set; }

		internal static ManualLogSource Logger => Instance._logger;

		private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger;

		internal Harmony? Harmony { get; set; }

		private void Awake()
		{
			Instance = this;
			_autoReloadEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("HostSwap", "AutoReloadCurrentLevel", true, "Reload current scene after host switch.");
			_reloadDelaySeconds = ((BaseUnityPlugin)this).Config.Bind<float>("HostSwap", "ReloadDelaySeconds", 2.5f, "Delay before reloading current scene.");
			_showUi = ((BaseUnityPlugin)this).Config.Bind<bool>("HostSwap", "ShowUI", true, "Show host swap UI.");
			_uiYOffset = ((BaseUnityPlugin)this).Config.Bind<float>("HostSwap", "UIVerticalOffset", 120f, "Vertical offset applied to BigMessageUI.");
			_phase1FontSize = ((BaseUnityPlugin)this).Config.Bind<float>("HostSwap", "Phase1FontSize", 56f, "Font size for the first banner.");
			_phase2FontSize = ((BaseUnityPlugin)this).Config.Bind<float>("HostSwap", "Phase2FontSize", 50f, "Font size for the second banner.");
			((Component)this).gameObject.transform.parent = null;
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			SceneManager.sceneLoaded += OnSceneLoaded;
			Patch();
			Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} loaded");
		}

		private void OnDestroy()
		{
			SceneManager.sceneLoaded -= OnSceneLoaded;
		}

		internal void Patch()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_0026: Expected O, but got Unknown
			if (Harmony == null)
			{
				Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID);
				Harmony val2 = val;
				Harmony = val;
			}
			Harmony.PatchAll();
		}

		internal void Unpatch()
		{
			Harmony? harmony = Harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		internal void StartHostSwap(Player newMaster)
		{
			newHostName = (string.IsNullOrEmpty((newMaster != null) ? newMaster.NickName : null) ? $"Player {((newMaster != null) ? new int?(newMaster.ActorNumber) : null)}" : newMaster.NickName);
			swapTimer = 0f;
			swapActive = true;
			_basePosCaptured = false;
			Logger.LogInfo((object)$"Master client switched to {newHostName} (Actor {((newMaster != null) ? new int?(newMaster.ActorNumber) : null)}).");
			if (_autoReloadEnabled.Value)
			{
				((MonoBehaviour)this).StartCoroutine(HostSwapRoutine(newMaster, _reloadDelaySeconds.Value));
			}
			else
			{
				Logger.LogInfo((object)"AutoReloadCurrentLevel=false; not reloading scene after host switch.");
			}
		}

		[IteratorStateMachine(typeof(<HostSwapRoutine>d__30))]
		private IEnumerator HostSwapRoutine(Player newMaster, float delay)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <HostSwapRoutine>d__30(0)
			{
				<>4__this = this,
				newMaster = newMaster,
				delay = delay
			};
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			if (_restoreAutoSync)
			{
				PhotonNetwork.AutomaticallySyncScene = _autoSyncPrev;
				_restoreAutoSync = false;
				Logger.LogInfo((object)$"Restored PhotonNetwork.AutomaticallySyncScene={_autoSyncPrev} after reload.");
			}
			swapActive = false;
			_basePosCaptured = false;
		}

		private void Update()
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			if (!_showUi.Value || !swapActive)
			{
				return;
			}
			if ((Object)(object)BigMessageUI.instance != (Object)null)
			{
				if (!_basePosCaptured)
				{
					_bigMsgBasePos = ((SemiUI)BigMessageUI.instance).showPosition;
					_basePosCaptured = true;
				}
				((SemiUI)BigMessageUI.instance).showPosition = _bigMsgBasePos + new Vector2(0f, _uiYOffset.Value);
			}
			swapTimer += Time.unscaledDeltaTime;
			int count = Mathf.Clamp((int)(swapTimer * 3f % 4f), 0, 3);
			string text = new string('.', count);
			if (swapTimer < 1.5f)
			{
				if ((Object)(object)BigMessageUI.instance != (Object)null)
				{
					BigMessageUI.instance.BigMessage("EMPRESS HOST SWAP" + text, "", _phase1FontSize.Value, Color.magenta, Color.white);
				}
			}
			else if (swapTimer < 4.5f)
			{
				if ((Object)(object)BigMessageUI.instance != (Object)null)
				{
					BigMessageUI.instance.BigMessage("NEW HOST: " + newHostName, "", _phase2FontSize.Value, Color.cyan, Color.white);
				}
				else if ((Object)(object)MenuManager.instance != (Object)null)
				{
					MenuManager.instance.PagePopUp("Empress Host Swap", Color.cyan, "New host: " + newHostName, "Ok", true);
				}
			}
			else
			{
				swapActive = false;
			}
		}
	}
	[HarmonyPatch(typeof(NetworkManager), "OnMasterClientSwitched")]
	internal static class HostSwapPatch
	{
		private static bool Prefix(Player _newMasterClient)
		{
			EmpressHostSwap.Instance.StartHostSwap(_newMasterClient);
			return false;
		}
	}
}