Decompiled source of CombinedMeltdownPlaylist v1.4.1

CombinedMeltdownPlaylistSync.dll

Decompiled an hour ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using FacilityMeltdown.API;
using FacilityMeltdown.MeltdownSequence.Behaviours;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using PizzaTowerEscapeMusic;
using PizzaTowerEscapeMusic.Scripting;
using PizzaTowerEscapeMusic.Scripting.ScriptEvents;
using TMPro;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.TextCore;
using UnityEngine.TextCore.LowLevel;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("CombinedMeltdownPlaylistSync")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.4.1.0")]
[assembly: AssemblyInformationalVersion("1.4.1")]
[assembly: AssemblyProduct("CombinedMeltdownPlaylistSync")]
[assembly: AssemblyTitle("CombinedMeltdownPlaylistSync")]
[assembly: AssemblyVersion("1.4.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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]
	[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]
	[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 CombinedMeltdownPlaylistSync
{
	[Serializable]
	internal sealed class SyncedConfigSnapshot
	{
		public float ExtraStaminaPercent;

		public float ExtraStaminaRegenPercent;

		public bool EnableHud;

		public float HudScale;

		public float HudOpacity;

		public string BaseColor = "#FF2020";

		public string FlashColor = "#FFD21A";

		public bool ShowReactorTimer;

		public bool ShowHundredths;

		public bool ShowTimerPanel;

		public float TimerPanelOpacity;

		public bool ShowDistance;

		public bool ShowSelectedTrack;

		public bool ShowTrackAuthor;

		public bool ShowDisc;

		public DistanceUnit DistanceUnits;

		public int DistanceDecimals;

		public float DiscSpinSpeed;

		public bool EnableFlashing;

		public bool UseTrackBpm;

		public HudBeatCadence BeatCadence;

		public float FixedFlashIntervalSeconds;

		public float FlashFadeSeconds;

		public float TimerTransitionSpeed;

		public float OutsideTimerOffsetX;

		public float OutsideTimerOffsetY;

		public float InsideTimerOffsetX;

		public float InsideTimerOffsetY;

		public float SpectatorTimerOffsetX;

		public float SpectatorTimerOffsetY;

		public float DistanceOffsetX;

		public float DistanceOffsetY;

		public float TrackOffsetX;

		public float TrackOffsetY;

		internal static SyncedConfigSnapshot CaptureLocal()
		{
			return new SyncedConfigSnapshot
			{
				ExtraStaminaPercent = Plugin.ExtraStaminaPercent.Value,
				ExtraStaminaRegenPercent = Plugin.ExtraStaminaRegenPercent.Value,
				EnableHud = HudConfig.EnableHud.Value,
				HudScale = HudConfig.HudScale.Value,
				HudOpacity = HudConfig.HudOpacity.Value,
				BaseColor = HudConfig.BaseColor.Value,
				FlashColor = HudConfig.FlashColor.Value,
				ShowReactorTimer = HudConfig.ShowReactorTimer.Value,
				ShowHundredths = HudConfig.ShowHundredths.Value,
				ShowTimerPanel = HudConfig.ShowTimerPanel.Value,
				TimerPanelOpacity = HudConfig.TimerPanelOpacity.Value,
				ShowDistance = HudConfig.ShowDistance.Value,
				ShowSelectedTrack = HudConfig.ShowSelectedTrack.Value,
				ShowTrackAuthor = HudConfig.ShowTrackAuthor.Value,
				ShowDisc = HudConfig.ShowDisc.Value,
				DistanceUnits = HudConfig.DistanceUnits.Value,
				DistanceDecimals = HudConfig.DistanceDecimals.Value,
				DiscSpinSpeed = HudConfig.DiscSpinSpeed.Value,
				EnableFlashing = HudConfig.EnableFlashing.Value,
				UseTrackBpm = HudConfig.UseTrackBpm.Value,
				BeatCadence = HudConfig.BeatCadence.Value,
				FixedFlashIntervalSeconds = HudConfig.FixedFlashIntervalSeconds.Value,
				FlashFadeSeconds = HudConfig.FlashFadeSeconds.Value,
				TimerTransitionSpeed = HudConfig.TimerTransitionSpeed.Value,
				OutsideTimerOffsetX = HudConfig.OutsideTimerOffsetX.Value,
				OutsideTimerOffsetY = HudConfig.OutsideTimerOffsetY.Value,
				InsideTimerOffsetX = HudConfig.InsideTimerOffsetX.Value,
				InsideTimerOffsetY = HudConfig.InsideTimerOffsetY.Value,
				SpectatorTimerOffsetX = HudConfig.SpectatorTimerOffsetX.Value,
				SpectatorTimerOffsetY = HudConfig.SpectatorTimerOffsetY.Value,
				DistanceOffsetX = HudConfig.DistanceOffsetX.Value,
				DistanceOffsetY = HudConfig.DistanceOffsetY.Value,
				TrackOffsetX = HudConfig.TrackOffsetX.Value,
				TrackOffsetY = HudConfig.TrackOffsetY.Value
			};
		}

		internal void Validate()
		{
			ExtraStaminaPercent = Mathf.Clamp(ExtraStaminaPercent, 0f, 1000f);
			ExtraStaminaRegenPercent = Mathf.Clamp(ExtraStaminaRegenPercent, 0f, 1000f);
			HudScale = Mathf.Clamp(HudScale, 0.5f, 2.5f);
			HudOpacity = Mathf.Clamp01(HudOpacity);
			TimerPanelOpacity = Mathf.Clamp01(TimerPanelOpacity);
			DistanceDecimals = Mathf.Clamp(DistanceDecimals, 0, 2);
			DiscSpinSpeed = Mathf.Clamp(DiscSpinSpeed, -720f, 720f);
			FixedFlashIntervalSeconds = Mathf.Clamp(FixedFlashIntervalSeconds, 0.25f, 30f);
			FlashFadeSeconds = Mathf.Clamp(FlashFadeSeconds, 0.05f, 5f);
			TimerTransitionSpeed = Mathf.Clamp(TimerTransitionSpeed, 0.5f, 30f);
			if (!Enum.IsDefined(typeof(DistanceUnit), DistanceUnits))
			{
				DistanceUnits = DistanceUnit.Meters;
			}
			if (!Enum.IsDefined(typeof(HudBeatCadence), BeatCadence))
			{
				BeatCadence = HudBeatCadence.EveryFourBeats;
			}
			if (BaseColor == null)
			{
				BaseColor = "#FF2020";
			}
			if (FlashColor == null)
			{
				FlashColor = "#FFD21A";
			}
		}
	}
	internal static class HostConfigSynchronizer
	{
		private const float RefreshIntervalSeconds = 0.5f;

		private static SyncedConfigSnapshot? _local;

		private static SyncedConfigSnapshot? _host;

		private static string? _lastSentJson;

		private static int _lastClientCount = -1;

		private static float _nextRefreshTime;

		internal static SyncedConfigSnapshot Current
		{
			get
			{
				NetworkManager registeredNetworkManager = Plugin.RegisteredNetworkManager;
				if ((Object)(object)registeredNetworkManager != (Object)null && registeredNetworkManager.IsListening && !registeredNetworkManager.IsServer && _host != null)
				{
					return _host;
				}
				return _local ?? (_local = CaptureValidatedLocal());
			}
		}

		internal static void Tick()
		{
			if (Time.unscaledTime < _nextRefreshTime)
			{
				return;
			}
			_nextRefreshTime = Time.unscaledTime + 0.5f;
			_local = CaptureValidatedLocal();
			NetworkManager registeredNetworkManager = Plugin.RegisteredNetworkManager;
			if (!((Object)(object)registeredNetworkManager == (Object)null) && registeredNetworkManager.IsListening && registeredNetworkManager.IsServer)
			{
				string text = JsonUtility.ToJson((object)_local);
				int count = registeredNetworkManager.ConnectedClientsIds.Count;
				if (!string.Equals(text, _lastSentJson, StringComparison.Ordinal) || count != _lastClientCount)
				{
					Broadcast(text);
					_lastSentJson = text;
					_lastClientCount = count;
				}
			}
		}

		internal static void ForceBroadcast()
		{
			_local = CaptureValidatedLocal();
			NetworkManager registeredNetworkManager = Plugin.RegisteredNetworkManager;
			if (!((Object)(object)registeredNetworkManager == (Object)null) && registeredNetworkManager.IsListening && registeredNetworkManager.IsServer)
			{
				string text = JsonUtility.ToJson((object)_local);
				Broadcast(text);
				_lastSentJson = text;
				_lastClientCount = registeredNetworkManager.ConnectedClientsIds.Count;
			}
		}

		internal static void Receive(ulong senderClientId, FastBufferReader reader)
		{
			NetworkManager registeredNetworkManager = Plugin.RegisteredNetworkManager;
			if ((Object)(object)registeredNetworkManager == (Object)null || registeredNetworkManager.IsServer)
			{
				return;
			}
			if (senderClientId != 0L)
			{
				Plugin.ModLog.LogWarning((object)$"Ignored configuration from non-host client {senderClientId}.");
				return;
			}
			try
			{
				string text = default(string);
				((FastBufferReader)(ref reader)).ReadValueSafe(ref text, true);
				SyncedConfigSnapshot obj = JsonUtility.FromJson<SyncedConfigSnapshot>(text) ?? throw new InvalidOperationException("The host snapshot was empty.");
				obj.Validate();
				_host = obj;
				Plugin.ModLog.LogInfo((object)"Applied the host's meltdown stamina and HUD configuration for this lobby.");
			}
			catch (Exception arg)
			{
				Plugin.ModLog.LogError((object)$"Could not read the host's configuration: {arg}");
			}
		}

		internal static void Reset()
		{
			_local = CaptureValidatedLocal();
			_host = null;
			_lastSentJson = null;
			_lastClientCount = -1;
			_nextRefreshTime = 0f;
		}

		private static SyncedConfigSnapshot CaptureValidatedLocal()
		{
			SyncedConfigSnapshot syncedConfigSnapshot = SyncedConfigSnapshot.CaptureLocal();
			syncedConfigSnapshot.Validate();
			return syncedConfigSnapshot;
		}

		private unsafe static void Broadcast(string json)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager registeredNetworkManager = Plugin.RegisteredNetworkManager;
			if ((Object)(object)registeredNetworkManager == (Object)null)
			{
				return;
			}
			try
			{
				FastBufferWriter val = default(FastBufferWriter);
				((FastBufferWriter)(ref val))..ctor(4096, (Allocator)2, -1);
				try
				{
					((FastBufferWriter)(ref val)).WriteValueSafe(json, true);
					registeredNetworkManager.CustomMessagingManager.SendNamedMessageToAll("CombinedMeltdownPlaylist.Config.v1", val, (NetworkDelivery)3);
				}
				finally
				{
					((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
				}
			}
			catch (Exception arg)
			{
				Plugin.ModLog.LogError((object)$"Could not broadcast the host's configuration: {arg}");
			}
		}
	}
	internal enum DistanceUnit
	{
		Meters,
		Feet,
		GameUnits
	}
	internal enum HudBeatCadence
	{
		EveryBeat,
		EveryFourBeats
	}
	internal static class HudConfig
	{
		internal static ConfigEntry<bool> EnableHud { get; private set; }

		internal static ConfigEntry<float> HudScale { get; private set; }

		internal static ConfigEntry<float> HudOpacity { get; private set; }

		internal static ConfigEntry<string> BaseColor { get; private set; }

		internal static ConfigEntry<string> FlashColor { get; private set; }

		internal static ConfigEntry<bool> ShowReactorTimer { get; private set; }

		internal static ConfigEntry<bool> ShowHundredths { get; private set; }

		internal static ConfigEntry<bool> ShowTimerPanel { get; private set; }

		internal static ConfigEntry<float> TimerPanelOpacity { get; private set; }

		internal static ConfigEntry<bool> ShowDistance { get; private set; }

		internal static ConfigEntry<bool> ShowSelectedTrack { get; private set; }

		internal static ConfigEntry<bool> ShowTrackAuthor { get; private set; }

		internal static ConfigEntry<bool> ShowDisc { get; private set; }

		internal static ConfigEntry<DistanceUnit> DistanceUnits { get; private set; }

		internal static ConfigEntry<int> DistanceDecimals { get; private set; }

		internal static ConfigEntry<float> DiscSpinSpeed { get; private set; }

		internal static ConfigEntry<bool> EnableFlashing { get; private set; }

		internal static ConfigEntry<bool> UseTrackBpm { get; private set; }

		internal static ConfigEntry<HudBeatCadence> BeatCadence { get; private set; }

		internal static ConfigEntry<float> FixedFlashIntervalSeconds { get; private set; }

		internal static ConfigEntry<float> FlashFadeSeconds { get; private set; }

		internal static ConfigEntry<float> TimerTransitionSpeed { get; private set; }

		internal static ConfigEntry<float> OutsideTimerOffsetX { get; private set; }

		internal static ConfigEntry<float> OutsideTimerOffsetY { get; private set; }

		internal static ConfigEntry<float> InsideTimerOffsetX { get; private set; }

		internal static ConfigEntry<float> InsideTimerOffsetY { get; private set; }

		internal static ConfigEntry<float> SpectatorTimerOffsetX { get; private set; }

		internal static ConfigEntry<float> SpectatorTimerOffsetY { get; private set; }

		internal static ConfigEntry<float> DistanceOffsetX { get; private set; }

		internal static ConfigEntry<float> DistanceOffsetY { get; private set; }

		internal static ConfigEntry<float> TrackOffsetX { get; private set; }

		internal static ConfigEntry<float> TrackOffsetY { get; private set; }

		internal static void Bind(ConfigFile config)
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Expected O, but got Unknown
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Expected O, but got Unknown
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Expected O, but got Unknown
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Expected O, but got Unknown
			//IL_0242: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Expected O, but got Unknown
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d5: Expected O, but got Unknown
			//IL_0303: Unknown result type (might be due to invalid IL or missing references)
			//IL_030d: Expected O, but got Unknown
			//IL_033b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0345: Expected O, but got Unknown
			AcceptableValueRange<float> val = new AcceptableValueRange<float>(0.5f, 2.5f);
			AcceptableValueRange<float> val2 = new AcceptableValueRange<float>(0.1f, 1f);
			AcceptableValueRange<float> range = new AcceptableValueRange<float>(-2000f, 2000f);
			EnableHud = config.Bind<bool>("Meltdown HUD - General", "EnableHud", true, "Enable all custom meltdown HUD elements.");
			HudScale = config.Bind<float>("Meltdown HUD - General", "HudScale", 1f, new ConfigDescription("Global scale for every custom HUD element.", (AcceptableValueBase)(object)val, Array.Empty<object>()));
			HudOpacity = config.Bind<float>("Meltdown HUD - General", "HudOpacity", 1f, new ConfigDescription("Global opacity for every custom HUD element.", (AcceptableValueBase)(object)val2, Array.Empty<object>()));
			BaseColor = config.Bind<string>("Meltdown HUD - General", "BaseColor", "#FF2020", "Normal HUD color in HTML hex format.");
			FlashColor = config.Bind<string>("Meltdown HUD - General", "FlashColor", "#FFD21A", "Beat-flash HUD color in HTML hex format.");
			ShowReactorTimer = config.Bind<bool>("Meltdown HUD - Elements", "ShowReactorTimer", true, "Show the CRITICAL FAILURE countdown.");
			ShowHundredths = config.Bind<bool>("Meltdown HUD - Elements", "ShowHundredths", true, "Show small hundredths next to the large total-seconds countdown.");
			ShowTimerPanel = config.Bind<bool>("Meltdown HUD - Elements", "ShowTimerPanel", true, "Show the rounded translucent reactor enclosure and separator line.");
			TimerPanelOpacity = config.Bind<float>("Meltdown HUD - Elements", "TimerPanelOpacity", 0.32f, new ConfigDescription("Opacity of the rounded reactor panel background.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			ShowDistance = config.Bind<bool>("Meltdown HUD - Elements", "ShowDistance", true, "Show distance to the ship outside and main entrance inside.");
			ShowSelectedTrack = config.Bind<bool>("Meltdown HUD - Elements", "ShowSelectedTrack", true, "Show the selected track on the right side.");
			ShowTrackAuthor = config.Bind<bool>("Meltdown HUD - Elements", "ShowTrackAuthor", true, "Show confirmed track authors when available.");
			ShowDisc = config.Bind<bool>("Meltdown HUD - Elements", "ShowDisc", true, "Show the spinning transparent music disc.");
			DistanceUnits = config.Bind<DistanceUnit>("Meltdown HUD - Elements", "DistanceUnits", DistanceUnit.Meters, "Distance units: Meters, Feet, or GameUnits.");
			DistanceDecimals = config.Bind<int>("Meltdown HUD - Elements", "DistanceDecimals", 0, new ConfigDescription("Number of decimal places in distance values.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 2), Array.Empty<object>()));
			DiscSpinSpeed = config.Bind<float>("Meltdown HUD - Elements", "DiscSpinSpeed", 90f, new ConfigDescription("Disc rotation speed in degrees per second. Negative values reverse it.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-720f, 720f), Array.Empty<object>()));
			EnableFlashing = config.Bind<bool>("Meltdown HUD - Flash", "EnableFlashing", true, "Enable red-to-yellow HUD pulses.");
			UseTrackBpm = config.Bind<bool>("Meltdown HUD - Flash", "UseTrackBpm", true, "Use the current track BPM. If disabled, use FixedFlashIntervalSeconds.");
			BeatCadence = config.Bind<HudBeatCadence>("Meltdown HUD - Flash", "BeatCadence", HudBeatCadence.EveryFourBeats, "Pulse on EveryBeat or EveryFourBeats.");
			FixedFlashIntervalSeconds = config.Bind<float>("Meltdown HUD - Flash", "FixedFlashIntervalSeconds", 4f, new ConfigDescription("Pulse interval when BPM sync is disabled or metadata is unavailable.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 30f), Array.Empty<object>()));
			FlashFadeSeconds = config.Bind<float>("Meltdown HUD - Flash", "FlashFadeSeconds", 0.45f, new ConfigDescription("Seconds for yellow to fade back to red. It is shortened automatically when needed so every pulse has red resting time.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 5f), Array.Empty<object>()));
			TimerTransitionSpeed = config.Bind<float>("Meltdown HUD - Layout", "TimerTransitionSpeed", 8f, new ConfigDescription("How quickly the reactor panel glides between its inside, outside, ship, and spectator positions. Higher values move faster.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 30f), Array.Empty<object>()));
			OutsideTimerOffsetX = BindOffset(config, "OutsideTimerOffsetX", "Horizontal adjustment for the timer beside the outside clock.", range);
			OutsideTimerOffsetY = BindOffset(config, "OutsideTimerOffsetY", "Vertical adjustment for the timer beside the outside clock.", range);
			InsideTimerOffsetX = BindOffset(config, "InsideTimerOffsetX", "Horizontal adjustment for the inside top-center timer.", range);
			InsideTimerOffsetY = BindOffset(config, "InsideTimerOffsetY", "Vertical adjustment for the inside top-center timer.", range);
			SpectatorTimerOffsetX = BindOffset(config, "SpectatorTimerOffsetX", "Horizontal adjustment for the spectator bottom-left timer.", range);
			SpectatorTimerOffsetY = BindOffset(config, "SpectatorTimerOffsetY", "Vertical adjustment for the spectator bottom-left timer.", range);
			DistanceOffsetX = BindOffset(config, "DistanceOffsetX", "Horizontal adjustment for the bottom-left distance.", range);
			DistanceOffsetY = BindOffset(config, "DistanceOffsetY", "Vertical adjustment for the lowered bottom-left distance.", range);
			TrackOffsetX = BindOffset(config, "TrackOffsetX", "Horizontal adjustment for the right-center track panel.", range);
			TrackOffsetY = BindOffset(config, "TrackOffsetY", "Vertical adjustment for the right-center track panel.", range);
		}

		private static ConfigEntry<float> BindOffset(ConfigFile config, string key, string description, AcceptableValueRange<float> range)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			return config.Bind<float>("Meltdown HUD - Layout", key, 0f, new ConfigDescription(description, (AcceptableValueBase)(object)range, Array.Empty<object>()));
		}
	}
	internal static class StaminaBoostController
	{
		private static bool _wasActive;

		internal static bool IsActive
		{
			get
			{
				StartOfRound instance = StartOfRound.Instance;
				if ((Object)(object)instance != (Object)null && instance.shipHasLanded && !instance.inShipPhase)
				{
					return MeltdownAPI.MeltdownStarted;
				}
				return false;
			}
		}

		internal static void Tick()
		{
			bool isActive = IsActive;
			if (isActive != _wasActive)
			{
				_wasActive = isActive;
				if (isActive)
				{
					SyncedConfigSnapshot current = HostConfigSynchronizer.Current;
					Plugin.ModLog.LogInfo((object)("Meltdown stamina boosts enabled: " + $"+{current.ExtraStaminaPercent:0.##}% effective stamina, " + $"+{current.ExtraStaminaRegenPercent:0.##}% regeneration."));
				}
				else
				{
					Plugin.ModLog.LogInfo((object)"Meltdown stamina boosts disabled.");
				}
			}
		}

		internal static void ForceDeactivate(string reason)
		{
			if (_wasActive)
			{
				Plugin.ModLog.LogInfo((object)("Meltdown stamina boosts disabled (" + reason + ")."));
			}
			_wasActive = false;
		}

		internal static StaminaSnapshot Capture(PlayerControllerB player)
		{
			if (!IsLocalPlayer(player) || !IsActive)
			{
				return default(StaminaSnapshot);
			}
			return new StaminaSnapshot(tracked: true, player.sprintMeter);
		}

		internal static void ApplyFrameDelta(PlayerControllerB player, StaminaSnapshot snapshot, bool includeRegeneration)
		{
			if (!snapshot.Tracked || !IsLocalPlayer(player) || !IsActive)
			{
				return;
			}
			float sprintMeter = player.sprintMeter;
			float num = sprintMeter - snapshot.Before;
			if (num < 0f)
			{
				SyncedConfigSnapshot current = HostConfigSynchronizer.Current;
				float num2 = 1f + current.ExtraStaminaPercent / 100f;
				float num3 = 0f - num;
				player.sprintMeter = snapshot.Before - num3 / num2;
			}
			else if (includeRegeneration && num > 0f)
			{
				SyncedConfigSnapshot current2 = HostConfigSynchronizer.Current;
				float num4 = num * current2.ExtraStaminaRegenPercent / 100f;
				float num5 = sprintMeter + num4;
				if (snapshot.Before > 1f || sprintMeter > 1f)
				{
					player.sprintMeter = num5;
				}
				else
				{
					player.sprintMeter = Mathf.Min(1f, num5);
				}
			}
			if ((Object)(object)player.sprintMeterUI != (Object)null)
			{
				player.sprintMeterUI.fillAmount = player.sprintMeter;
			}
		}

		private static bool IsLocalPlayer(PlayerControllerB player)
		{
			if ((Object)(object)GameNetworkManager.Instance != (Object)null)
			{
				return player == GameNetworkManager.Instance.localPlayerController;
			}
			return false;
		}
	}
	internal readonly struct StaminaSnapshot
	{
		internal bool Tracked { get; }

		internal float Before { get; }

		internal StaminaSnapshot(bool tracked, float before)
		{
			Tracked = tracked;
			Before = before;
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")]
	internal static class PlayerStaminaLateUpdatePatch
	{
		[HarmonyPrefix]
		[HarmonyPriority(800)]
		private static void Prefix(PlayerControllerB __instance, out StaminaSnapshot __state)
		{
			__state = StaminaBoostController.Capture(__instance);
		}

		[HarmonyPostfix]
		[HarmonyPriority(0)]
		private static void Postfix(PlayerControllerB __instance, StaminaSnapshot __state)
		{
			StaminaBoostController.ApplyFrameDelta(__instance, __state, includeRegeneration: true);
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB), "Jump_performed")]
	internal static class PlayerJumpStaminaPatch
	{
		[HarmonyPrefix]
		[HarmonyPriority(800)]
		private static void Prefix(PlayerControllerB __instance, out StaminaSnapshot __state)
		{
			__state = StaminaBoostController.Capture(__instance);
		}

		[HarmonyPostfix]
		[HarmonyPriority(0)]
		private static void Postfix(PlayerControllerB __instance, StaminaSnapshot __state)
		{
			StaminaBoostController.ApplyFrameDelta(__instance, __state, includeRegeneration: false);
		}
	}
	[HarmonyPatch(typeof(MeltdownHandler), "HandleEnemies")]
	internal static class FacilityMeltdownEnemyCompatibilityPatch
	{
		[HarmonyFinalizer]
		private static Exception? Finalizer(Exception? __exception)
		{
			if (__exception == null)
			{
				return null;
			}
			Plugin.ModLog.LogError((object)("FacilityMeltdown's optional enemy handling failed. The exception was contained so host-side meltdown initialization and forced takeoff can continue. " + $"Original error: {__exception}"));
			return null;
		}
	}
	[HarmonyPatch(typeof(MeltdownHandler), "Update")]
	internal static class FacilityMeltdownUpdatePatch
	{
		[HarmonyPostfix]
		private static void Postfix(MeltdownHandler __instance)
		{
			ForcedTakeoffFailsafe.Observe(__instance);
			MeltdownHudController.Observe(__instance);
		}
	}
	[HarmonyPatch(typeof(MeltdownHandler), "OnDisable")]
	internal static class FacilityMeltdownCleanupPatch
	{
		[HarmonyPrefix]
		private static void Prefix()
		{
			StaminaBoostController.ForceDeactivate("meltdown handler cleanup");
			ForcedTakeoffFailsafe.Reset();
			LazyMusicPlayer.Stop();
			MeltdownHudController.ResetSession();
		}
	}
	[HarmonyPatch(typeof(StartOfRound), "ShipLeave")]
	internal static class ShipLeaveCleanupPatch
	{
		[HarmonyPrefix]
		private static void Prefix()
		{
			StaminaBoostController.ForceDeactivate("ship departure");
			LazyMusicPlayer.Stop();
			MeltdownHudController.ResetSession();
		}
	}
	[HarmonyPatch(typeof(StartOfRound), "EndOfGame")]
	internal static class EndOfGameCleanupPatch
	{
		[HarmonyPrefix]
		private static void Prefix()
		{
			StaminaBoostController.ForceDeactivate("end of round");
			LazyMusicPlayer.Stop();
			MeltdownHudController.ResetSession();
		}
	}
	internal static class ForcedTakeoffFailsafe
	{
		private const float GraceSecondsAfterOriginalTakeoff = 7f;

		private const float RetryDelaySeconds = 2f;

		private const int MaximumAttempts = 3;

		private static readonly MethodInfo? ShipLeaveMethod = AccessTools.Method(typeof(StartOfRound), "ShipLeave", (Type[])null, (Type[])null);

		private static bool _armed;

		private static float _nextAttemptTime;

		private static int _attempts;

		internal static void Observe(MeltdownHandler handler)
		{
			if (!_armed && IsHost() && !(handler.TimeLeftUntilMeltdown > 3f))
			{
				_armed = true;
				_attempts = 0;
				_nextAttemptTime = Time.realtimeSinceStartup + 7f;
				Plugin.ModLog.LogDebug((object)"Armed the host forced-takeoff failsafe.");
			}
		}

		internal static void Tick()
		{
			if (!_armed)
			{
				return;
			}
			StartOfRound instance = StartOfRound.Instance;
			if ((Object)(object)instance == (Object)null || instance.inShipPhase || !MeltdownAPI.MeltdownStarted)
			{
				Reset();
			}
			else
			{
				if (!IsHost() || !instance.shipHasLanded || Time.realtimeSinceStartup < _nextAttemptTime || _attempts >= 3)
				{
					return;
				}
				_attempts++;
				_nextAttemptTime = Time.realtimeSinceStartup + 2f;
				if (!(ShipLeaveMethod == null))
				{
					try
					{
						Plugin.ModLog.LogWarning((object)("FacilityMeltdown's host departure did not complete; running takeoff " + $"failsafe attempt {_attempts}/{3}."));
						instance.shipLeftAutomatically = true;
						instance.shipIsLeaving = true;
						ShipLeaveMethod.Invoke(instance, Array.Empty<object>());
						return;
					}
					catch (Exception arg)
					{
						Plugin.ModLog.LogError((object)$"Forced-takeoff failsafe attempt {_attempts} failed: {arg}");
						return;
					}
				}
				Plugin.ModLog.LogError((object)"Could not locate StartOfRound.ShipLeave for the forced-takeoff failsafe.");
				_attempts = 3;
			}
		}

		internal static void Reset()
		{
			_armed = false;
			_nextAttemptTime = 0f;
			_attempts = 0;
		}

		private static bool IsHost()
		{
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton != (Object)null && singleton.IsListening)
			{
				return singleton.IsHost;
			}
			return false;
		}
	}
	internal static class MeltdownHudController
	{
		private const float DistanceUpdateInterval = 0.1f;

		private static MeltdownHandler? _handler;

		private static HUDManager? _hudManager;

		private static GameObject? _root;

		private static RectTransform? _rootRect;

		private static CanvasGroup? _canvasGroup;

		private static Canvas? _hudCanvas;

		private static RectTransform? _timerRoot;

		private static Image? _timerPanel;

		private static Image? _timerHighlight;

		private static TextMeshProUGUI? _timerHeader;

		private static TextMeshProUGUI? _timerSeconds;

		private static TextMeshProUGUI? _timerHundredths;

		private static RectTransform? _distanceRoot;

		private static TextMeshProUGUI? _distanceText;

		private static RectTransform? _trackRoot;

		private static TextMeshProUGUI? _trackHeader;

		private static TextMeshProUGUI? _trackTitle;

		private static TextMeshProUGUI? _trackAuthor;

		private static RectTransform? _discRect;

		private static Image? _discImage;

		private static Image? _tonearmImage;

		private static Texture2D? _discTexture;

		private static Sprite? _discSprite;

		private static Texture2D? _tonearmTexture;

		private static Sprite? _tonearmSprite;

		private static Texture2D? _timerPanelTexture;

		private static Sprite? _timerPanelSprite;

		private static Texture2D? _timerHighlightTexture;

		private static Sprite? _timerHighlightSprite;

		private static TrackInfo? _currentTrack;

		private static double _trackStartDsp;

		private static double _sessionStartDsp;

		private static double _lastPulseDsp = double.NegativeInfinity;

		private static long _lastPulseIndex = long.MinValue;

		private static float _lastPulseInterval = -1f;

		private static float _lastPulseOffset = -1f;

		private static bool _wasActive;

		private static float _nextDistanceUpdate;

		private static bool _hasEntrancePosition;

		private static Vector3 _entrancePosition;

		private static float _discAngle;

		private static bool _timerPositionInitialized;

		private static string? _cachedBaseColorText;

		private static string? _cachedFlashColorText;

		private static Color _cachedBaseColor = new Color(1f, 0.125f, 0.125f, 1f);

		private static Color _cachedFlashColor = new Color(1f, 0.824f, 0.102f, 1f);

		internal static void Observe(MeltdownHandler handler)
		{
			_handler = handler;
		}

		internal static void OnTrackStarted(string filename)
		{
			_currentTrack = TrackMetadata.Resolve(filename);
			_trackStartDsp = AudioSettings.dspTime;
			_lastPulseDsp = double.NegativeInfinity;
			_lastPulseIndex = long.MinValue;
			_lastPulseInterval = -1f;
			_lastPulseOffset = -1f;
			UpdateTrackText();
			Plugin.ModLog.LogInfo((object)("HUD track metadata: '" + _currentTrack.Title + "', " + (_currentTrack.HasBpm ? $"{_currentTrack.Bpm:0.###} BPM." : "fixed-interval pulse fallback.")));
		}

		internal static void Tick()
		{
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			SyncedConfigSnapshot current = HostConfigSynchronizer.Current;
			if (!current.EnableHud || !IsMeltdownActive())
			{
				if (_wasActive)
				{
					Hide();
				}
				_wasActive = false;
				return;
			}
			if (!_wasActive)
			{
				_sessionStartDsp = AudioSettings.dspTime;
				_lastPulseIndex = long.MinValue;
				_lastPulseDsp = double.NegativeInfinity;
			}
			_wasActive = true;
			HUDManager instance = HUDManager.Instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance.HUDContainer == (Object)null)
			{
				return;
			}
			EnsureCreated(instance);
			if (!((Object)(object)_root == (Object)null))
			{
				if (!instance.HUDContainer.activeInHierarchy)
				{
					Hide();
					return;
				}
				_root.SetActive(true);
				UpdateVisibilityAndLayout(current);
				UpdateTimer();
				UpdateDistance(current);
				UpdateDisc(current);
				ApplySharedColor(CalculatePulseColor(current), current);
			}
		}

		internal static void ResetSession()
		{
			_handler = null;
			_currentTrack = null;
			_trackStartDsp = 0.0;
			_sessionStartDsp = 0.0;
			_lastPulseDsp = double.NegativeInfinity;
			_lastPulseIndex = long.MinValue;
			_lastPulseInterval = -1f;
			_lastPulseOffset = -1f;
			_nextDistanceUpdate = 0f;
			_hasEntrancePosition = false;
			_timerPositionInitialized = false;
			_wasActive = false;
			Hide();
			UpdateTrackText();
		}

		internal static void Destroy()
		{
			ResetSession();
			if ((Object)(object)_root != (Object)null)
			{
				Object.Destroy((Object)(object)_root);
			}
			if ((Object)(object)_discSprite != (Object)null)
			{
				Object.Destroy((Object)(object)_discSprite);
			}
			if ((Object)(object)_discTexture != (Object)null)
			{
				Object.Destroy((Object)(object)_discTexture);
			}
			if ((Object)(object)_tonearmSprite != (Object)null)
			{
				Object.Destroy((Object)(object)_tonearmSprite);
			}
			if ((Object)(object)_tonearmTexture != (Object)null)
			{
				Object.Destroy((Object)(object)_tonearmTexture);
			}
			if ((Object)(object)_timerPanelSprite != (Object)null)
			{
				Object.Destroy((Object)(object)_timerPanelSprite);
			}
			if ((Object)(object)_timerPanelTexture != (Object)null)
			{
				Object.Destroy((Object)(object)_timerPanelTexture);
			}
			if ((Object)(object)_timerHighlightSprite != (Object)null)
			{
				Object.Destroy((Object)(object)_timerHighlightSprite);
			}
			if ((Object)(object)_timerHighlightTexture != (Object)null)
			{
				Object.Destroy((Object)(object)_timerHighlightTexture);
			}
			_root = null;
			_rootRect = null;
			_canvasGroup = null;
			_hudCanvas = null;
			_timerRoot = null;
			_timerPanel = null;
			_timerHighlight = null;
			_timerHeader = null;
			_timerSeconds = null;
			_timerHundredths = null;
			_distanceRoot = null;
			_distanceText = null;
			_trackRoot = null;
			_trackHeader = null;
			_trackTitle = null;
			_trackAuthor = null;
			_discRect = null;
			_discImage = null;
			_tonearmImage = null;
			_discTexture = null;
			_discSprite = null;
			_tonearmTexture = null;
			_tonearmSprite = null;
			_timerPanelTexture = null;
			_timerPanelSprite = null;
			_timerHighlightTexture = null;
			_timerHighlightSprite = null;
			_hudManager = null;
			VcrFontFactory.Destroy();
		}

		private static bool IsMeltdownActive()
		{
			StartOfRound instance = StartOfRound.Instance;
			if ((Object)(object)instance != (Object)null && instance.shipHasLanded && !instance.inShipPhase)
			{
				return MeltdownAPI.MeltdownStarted;
			}
			return false;
		}

		private static void EnsureCreated(HUDManager hudManager)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Expected O, but got Unknown
			if (!((Object)(object)_root != (Object)null) || _hudManager != hudManager)
			{
				if ((Object)(object)_root != (Object)null)
				{
					Object.Destroy((Object)(object)_root);
				}
				_hudManager = hudManager;
				TMP_FontAsset orCreate = VcrFontFactory.GetOrCreate();
				_root = new GameObject("CombinedMeltdownPlaylist HUD", new Type[2]
				{
					typeof(RectTransform),
					typeof(CanvasGroup)
				});
				Canvas componentInParent = hudManager.HUDContainer.GetComponentInParent<Canvas>();
				Canvas val = (_hudCanvas = ((componentInParent != null) ? componentInParent.rootCanvas : null));
				Transform val2 = (((Object)(object)val != (Object)null) ? ((Component)val).transform : hudManager.HUDContainer.transform);
				_root.transform.SetParent(val2, false);
				_root.transform.SetAsLastSibling();
				_rootRect = (RectTransform)_root.transform;
				StretchToParent(_rootRect);
				_canvasGroup = _root.GetComponent<CanvasGroup>();
				_canvasGroup.interactable = false;
				_canvasGroup.blocksRaycasts = false;
				BuildTimer(orCreate);
				BuildDistance(orCreate);
				BuildTrackPanel(orCreate);
				UpdateTrackText();
				Plugin.ModLog.LogInfo((object)"Created the meltdown HUD.");
			}
		}

		private static void BuildTimer(TMP_FontAsset font)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: 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)
			//IL_0041: 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)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//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_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			_timerRoot = CreateRect(_rootRect, "Reactor Timer", new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(202f, 94f), Vector2.zero);
			_timerPanel = ((Component)CreateRect(_timerRoot, "Rounded Reactor Enclosure", Vector2.zero, Vector2.zero, Vector2.zero, new Vector2(202f, 94f), Vector2.zero)).gameObject.AddComponent<Image>();
			((Graphic)_timerPanel).raycastTarget = false;
			_timerPanelSprite = CreateTimerPanelSprite();
			_timerPanel.sprite = _timerPanelSprite;
			_timerHighlight = ((Component)CreateRect(_timerRoot, "Reactor Border And Separator", Vector2.zero, Vector2.zero, Vector2.zero, new Vector2(202f, 94f), Vector2.zero)).gameObject.AddComponent<Image>();
			((Graphic)_timerHighlight).raycastTarget = false;
			_timerHighlightSprite = CreateTimerHighlightSprite();
			_timerHighlight.sprite = _timerHighlightSprite;
			_timerHeader = CreateText(_timerRoot, "Critical Failure Label", font, 17f, (TextAlignmentOptions)514, new Vector2(9f, 66f), new Vector2(184f, 23f));
			((TMP_Text)_timerHeader).text = "CRITICAL FAILURE";
			_timerSeconds = CreateText(_timerRoot, "Reactor Seconds", font, 56f, (TextAlignmentOptions)4100, new Vector2(8f, 5f), new Vector2(132f, 58f));
			((TMP_Text)_timerSeconds).text = "150";
			_timerHundredths = CreateText(_timerRoot, "Reactor Hundredths", font, 23f, (TextAlignmentOptions)1025, new Vector2(143f, 10f), new Vector2(50f, 34f));
			((TMP_Text)_timerHundredths).text = "00";
		}

		private static void BuildDistance(TMP_FontAsset font)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: 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)
			//IL_0041: 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)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			_distanceRoot = CreateRect(_rootRect, "Distance", new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 0f), new Vector2(380f, 44f), Vector2.zero);
			_distanceText = CreateText(_distanceRoot, "Distance Text", font, 25f, (TextAlignmentOptions)1025, Vector2.zero, new Vector2(380f, 44f));
		}

		private static void BuildTrackPanel(TMP_FontAsset font)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: 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)
			//IL_0041: 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)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			_trackRoot = CreateRect(_rootRect, "Now Playing", new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(1f, 0.5f), new Vector2(382f, 94f), Vector2.zero);
			_discRect = CreateRect(_trackRoot, "Spinning Disc", new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(61f, 61f), new Vector2(32f, 0f));
			_discImage = ((Component)_discRect).gameObject.AddComponent<Image>();
			((Graphic)_discImage).raycastTarget = false;
			_discImage.preserveAspect = true;
			_discSprite = CreateDiscSprite();
			_discImage.sprite = _discSprite;
			_tonearmImage = ((Component)CreateRect(_trackRoot, "Record Player Tonearm", new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(61f, 61f), new Vector2(35f, 5f))).gameObject.AddComponent<Image>();
			((Graphic)_tonearmImage).raycastTarget = false;
			_tonearmImage.preserveAspect = true;
			_tonearmSprite = CreateTonearmSprite();
			_tonearmImage.sprite = _tonearmSprite;
			_trackHeader = CreateText(_trackRoot, "Now Playing Label", font, 15f, (TextAlignmentOptions)1025, new Vector2(70f, 62f), new Vector2(305f, 23f));
			((TMP_Text)_trackHeader).text = "NOW PLAYING";
			_trackTitle = CreateText(_trackRoot, "Track Title", font, 23f, (TextAlignmentOptions)4097, new Vector2(70f, 31f), new Vector2(305f, 35f));
			_trackAuthor = CreateText(_trackRoot, "Track Author", font, 15f, (TextAlignmentOptions)257, new Vector2(70f, 5f), new Vector2(305f, 26f));
		}

		private static void UpdateVisibilityAndLayout(SyncedConfigSnapshot config)
		{
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: 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_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_0281: Unknown result type (might be due to invalid IL or missing references)
			//IL_029b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0334: Unknown result type (might be due to invalid IL or missing references)
			//IL_0339: Unknown result type (might be due to invalid IL or missing references)
			//IL_033d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0351: Unknown result type (might be due to invalid IL or missing references)
			//IL_0356: Unknown result type (might be due to invalid IL or missing references)
			//IL_0367: Unknown result type (might be due to invalid IL or missing references)
			//IL_036c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0371: Unknown result type (might be due to invalid IL or missing references)
			//IL_0382: Unknown result type (might be due to invalid IL or missing references)
			//IL_0387: Unknown result type (might be due to invalid IL or missing references)
			//IL_038c: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_03eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0303: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_rootRect == (Object)null) && !((Object)(object)_timerRoot == (Object)null) && !((Object)(object)_distanceRoot == (Object)null) && !((Object)(object)_trackRoot == (Object)null) && !((Object)(object)_timerHundredths == (Object)null) && !((Object)(object)_canvasGroup == (Object)null))
			{
				PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
				bool flag = (Object)(object)val == (Object)null || val.isPlayerDead;
				bool flag2 = (Object)(object)val != (Object)null && val.isInsideFactory;
				bool flag3 = (Object)(object)val != (Object)null && val.isInHangarShipRoom;
				float hudScale = config.HudScale;
				Vector3 localScale = Vector3.one * hudScale;
				((Transform)_timerRoot).localScale = localScale;
				((Transform)_distanceRoot).localScale = localScale;
				((Transform)_trackRoot).localScale = localScale;
				_canvasGroup.alpha = config.HudOpacity;
				((Component)_timerRoot).gameObject.SetActive(config.ShowReactorTimer);
				((Component)_timerHundredths).gameObject.SetActive(config.ShowHundredths);
				if ((Object)(object)_timerPanel != (Object)null)
				{
					((Component)_timerPanel).gameObject.SetActive(config.ShowTimerPanel);
				}
				if ((Object)(object)_timerHighlight != (Object)null)
				{
					((Component)_timerHighlight).gameObject.SetActive(config.ShowTimerPanel);
				}
				bool active = config.ShowDistance && (Object)(object)val != (Object)null && !flag && !flag3;
				((Component)_distanceRoot).gameObject.SetActive(active);
				bool flag4 = config.ShowSelectedTrack && _currentTrack != null;
				((Component)_trackRoot).gameObject.SetActive(flag4);
				if ((Object)(object)_trackAuthor != (Object)null)
				{
					((Component)_trackAuthor).gameObject.SetActive(flag4 && config.ShowTrackAuthor && !string.IsNullOrWhiteSpace(_currentTrack?.Author));
				}
				if ((Object)(object)_discRect != (Object)null)
				{
					((Component)_discRect).gameObject.SetActive(flag4 && config.ShowDisc);
				}
				if ((Object)(object)_tonearmImage != (Object)null)
				{
					((Component)_tonearmImage).gameObject.SetActive(flag4 && config.ShowDisc);
				}
				Vector2 topCenterTimerTarget = GetTopCenterTimerTarget(config, hudScale);
				Vector2 val2 = (flag ? (ScreenToRootLocal(new Vector2(35f, 110f)) + new Vector2(_timerRoot.sizeDelta.x * hudScale * 0.5f + config.SpectatorTimerOffsetX, _timerRoot.sizeDelta.y * hudScale * 0.5f + config.SpectatorTimerOffsetY)) : ((!(flag2 || flag3) && IsOutsideClockVisible()) ? GetOutsideTimerTarget(config, hudScale) : topCenterTimerTarget));
				SetAnchoredLayout(_timerRoot, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), _timerRoot.anchoredPosition);
				if (!_timerPositionInitialized)
				{
					_timerRoot.anchoredPosition = topCenterTimerTarget;
					_timerPositionInitialized = true;
				}
				float num = 1f - Mathf.Exp((0f - config.TimerTransitionSpeed) * Time.unscaledDeltaTime);
				_timerRoot.anchoredPosition = Vector2.Lerp(_timerRoot.anchoredPosition, val2, num);
				Vector2 anchoredPosition = ScreenToRootLocal(new Vector2(35f, 22f)) + new Vector2(config.DistanceOffsetX, config.DistanceOffsetY);
				SetAnchoredLayout(_distanceRoot, new Vector2(0.5f, 0.5f), Vector2.zero, anchoredPosition);
				Vector2 anchoredPosition2 = ScreenToRootLocal(new Vector2((float)Screen.width - 22f, (float)Screen.height * 0.5f)) + new Vector2(config.TrackOffsetX, config.TrackOffsetY);
				SetAnchoredLayout(_trackRoot, new Vector2(0.5f, 0.5f), new Vector2(1f, 0.5f), anchoredPosition2);
			}
		}

		private static Vector2 GetTopCenterTimerTarget(SyncedConfigSnapshot config, float scale)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_timerRoot == (Object)null)
			{
				return Vector2.zero;
			}
			return ScreenToRootLocal(new Vector2((float)Screen.width * 0.5f, (float)Screen.height - 24f)) + new Vector2(config.InsideTimerOffsetX, (0f - _timerRoot.sizeDelta.y) * scale * 0.5f + config.InsideTimerOffsetY);
		}

		private static Vector2 GetOutsideTimerTarget(SyncedConfigSnapshot config, float scale)
		{
			//IL_000f: 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)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//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_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//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)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_timerRoot == (Object)null)
			{
				return GetTopCenterTimerTarget(config, scale);
			}
			HUDManager? hudManager = _hudManager;
			object obj;
			if (hudManager == null)
			{
				obj = null;
			}
			else
			{
				TextMeshProUGUI clockNumber = hudManager.clockNumber;
				obj = ((clockNumber != null) ? ((TMP_Text)clockNumber).rectTransform : null);
			}
			RectTransform val = (RectTransform)obj;
			if ((Object)(object)val == (Object)null)
			{
				return GetTopCenterTimerTarget(config, scale);
			}
			Rect rect = val.rect;
			float xMax = ((Rect)(ref rect)).xMax;
			rect = val.rect;
			Vector3 val2 = ((Transform)val).TransformPoint(new Vector3(xMax, ((Rect)(ref rect)).center.y, 0f));
			return ScreenToRootLocal(RectTransformUtility.WorldToScreenPoint(GetHudCamera(), val2)) + new Vector2(50f + _timerRoot.sizeDelta.x * scale * 0.5f + config.OutsideTimerOffsetX, config.OutsideTimerOffsetY);
		}

		private static bool IsOutsideClockVisible()
		{
			TextMeshProUGUI val = _hudManager?.clockNumber;
			if ((Object)(object)val != (Object)null && ((Behaviour)val).enabled)
			{
				return ((Component)val).gameObject.activeInHierarchy;
			}
			return false;
		}

		private static Vector2 ScreenToRootLocal(Vector2 screenPosition)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			Vector2 result = default(Vector2);
			if ((Object)(object)_rootRect != (Object)null && RectTransformUtility.ScreenPointToLocalPointInRectangle(_rootRect, screenPosition, GetHudCamera(), ref result))
			{
				return result;
			}
			return Vector2.zero;
		}

		private static Camera? GetHudCamera()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_hudCanvas == (Object)null || (int)_hudCanvas.renderMode == 0)
			{
				return null;
			}
			return _hudCanvas.worldCamera;
		}

		private static void UpdateTimer()
		{
			if (!((Object)(object)_timerSeconds == (Object)null) && !((Object)(object)_timerHundredths == (Object)null))
			{
				int num = Mathf.FloorToInt((((Object)(object)_handler == (Object)null) ? 0f : Mathf.Max(0f, _handler.TimeLeftUntilMeltdown)) * 100f + 0.001f);
				int num2 = num / 100;
				int num3 = num % 100;
				((TMP_Text)_timerSeconds).text = num2.ToString(CultureInfo.InvariantCulture);
				((TMP_Text)_timerHundredths).text = num3.ToString("00", CultureInfo.InvariantCulture);
			}
		}

		private static void UpdateDistance(SyncedConfigSnapshot config)
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: 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_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_distanceRoot == (Object)null || !((Component)_distanceRoot).gameObject.activeSelf || (Object)(object)_distanceText == (Object)null || Time.unscaledTime < _nextDistanceUpdate)
			{
				return;
			}
			_nextDistanceUpdate = Time.unscaledTime + 0.1f;
			PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Vector3 val2;
			string text;
			if (val.isInsideFactory)
			{
				if (!_hasEntrancePosition)
				{
					_entrancePosition = RoundManager.FindMainEntrancePosition(true, false);
					_hasEntrancePosition = _entrancePosition != Vector3.zero;
				}
				if (!_hasEntrancePosition)
				{
					((TMP_Text)_distanceText).text = "ENTRANCE --";
					return;
				}
				val2 = _entrancePosition;
				text = "ENTRANCE";
			}
			else
			{
				Transform val3 = StartOfRound.Instance?.shipDoorNode;
				if ((Object)(object)val3 == (Object)null)
				{
					((TMP_Text)_distanceText).text = "SHIP --";
					return;
				}
				val2 = val3.position;
				text = "SHIP";
			}
			float num = Vector3.Distance(((Component)val).transform.position, val2);
			string text2;
			switch (config.DistanceUnits)
			{
			case DistanceUnit.Feet:
				num *= 3.28084f;
				text2 = "FT";
				break;
			case DistanceUnit.GameUnits:
				text2 = "U";
				break;
			default:
				text2 = "M";
				break;
			}
			int distanceDecimals = config.DistanceDecimals;
			string text3 = "F" + distanceDecimals.ToString(CultureInfo.InvariantCulture);
			((TMP_Text)_distanceText).text = text + " " + num.ToString(text3, CultureInfo.InvariantCulture) + " " + text2;
		}

		private static void UpdateDisc(SyncedConfigSnapshot config)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_discRect == (Object)null) && ((Component)_discRect).gameObject.activeSelf)
			{
				_discAngle = Mathf.Repeat(_discAngle - config.DiscSpinSpeed * Time.unscaledDeltaTime, 360f);
				((Transform)_discRect).localRotation = Quaternion.Euler(0f, 0f, _discAngle);
			}
		}

		private static Color CalculatePulseColor(SyncedConfigSnapshot config)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: 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)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			Color val = ResolveConfiguredColor(config.BaseColor, ref _cachedBaseColorText, ref _cachedBaseColor, new Color(1f, 0.125f, 0.125f, 1f), "BaseColor");
			Color val2 = ResolveConfiguredColor(config.FlashColor, ref _cachedFlashColorText, ref _cachedFlashColor, new Color(1f, 0.824f, 0.102f, 1f), "FlashColor");
			if (!config.EnableFlashing)
			{
				return val;
			}
			float num2;
			float num3;
			double num4;
			if (config.UseTrackBpm && _currentTrack != null && _currentTrack.HasBpm)
			{
				int num = ((config.BeatCadence != HudBeatCadence.EveryFourBeats) ? 1 : 4);
				num2 = 60f / _currentTrack.Bpm * (float)num;
				num3 = Mathf.Max(0f, _currentTrack.BeatOffsetSeconds);
				num4 = _trackStartDsp;
			}
			else
			{
				num2 = Mathf.Clamp(config.FixedFlashIntervalSeconds, 0.25f, 30f);
				num3 = 0f;
				num4 = ((_trackStartDsp > 0.0) ? _trackStartDsp : _sessionStartDsp);
			}
			if (!Mathf.Approximately(num2, _lastPulseInterval) || !Mathf.Approximately(num3, _lastPulseOffset))
			{
				_lastPulseInterval = num2;
				_lastPulseOffset = num3;
				_lastPulseIndex = long.MinValue;
				_lastPulseDsp = double.NegativeInfinity;
			}
			double dspTime = AudioSettings.dspTime;
			double num5 = dspTime - num4 - (double)num3;
			if (num5 >= 0.0)
			{
				long num6 = (long)Math.Floor(num5 / (double)num2);
				if (num6 != _lastPulseIndex)
				{
					_lastPulseIndex = num6;
					_lastPulseDsp = num4 + (double)num3 + (double)((float)num6 * num2);
				}
			}
			float num7 = Mathf.Min(config.FlashFadeSeconds, num2 * 0.75f);
			float num8 = (float)(dspTime - _lastPulseDsp);
			if (num8 < 0f || num8 >= num7)
			{
				return val;
			}
			return Color.Lerp(val2, val, Mathf.Clamp01(num8 / num7));
		}

		private static Color ResolveConfiguredColor(string configuredValue, ref string? cachedText, ref Color cachedColor, Color fallback, string settingName)
		{
			//IL_000c: 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_0045: 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_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			if (string.Equals(cachedText, configuredValue, StringComparison.Ordinal))
			{
				return cachedColor;
			}
			cachedText = configuredValue;
			Color val = default(Color);
			if (ColorUtility.TryParseHtmlString(configuredValue.StartsWith("#", StringComparison.Ordinal) ? configuredValue : ("#" + configuredValue), ref val))
			{
				cachedColor = val;
				return val;
			}
			cachedColor = fallback;
			Plugin.ModLog.LogWarning((object)("Invalid HUD " + settingName + " '" + configuredValue + "'; using the default."));
			return fallback;
		}

		private static void ApplySharedColor(Color color, SyncedConfigSnapshot config)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: 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_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			ApplyTextColor(_timerHeader, color);
			ApplyTextColor(_timerSeconds, color);
			ApplyTextColor(_timerHundredths, color);
			ApplyTextColor(_distanceText, color);
			ApplyTextColor(_trackHeader, color);
			ApplyTextColor(_trackTitle, color);
			ApplyTextColor(_trackAuthor, color);
			if ((Object)(object)_discImage != (Object)null)
			{
				((Graphic)_discImage).color = new Color(color.r, color.g, color.b, color.a * 0.78f);
			}
			if ((Object)(object)_tonearmImage != (Object)null)
			{
				((Graphic)_tonearmImage).color = new Color(color.r, color.g, color.b, color.a * 0.88f);
			}
			if ((Object)(object)_timerPanel != (Object)null)
			{
				((Graphic)_timerPanel).color = new Color(0f, 0f, 0f, config.TimerPanelOpacity);
			}
			if ((Object)(object)_timerHighlight != (Object)null)
			{
				((Graphic)_timerHighlight).color = new Color(color.r, color.g, color.b, color.a * 0.9f);
			}
		}

		private static void ApplyTextColor(TextMeshProUGUI? text, Color color)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)text != (Object)null)
			{
				((Graphic)text).color = color;
			}
		}

		private static void UpdateTrackText()
		{
			if (!((Object)(object)_trackTitle == (Object)null) && !((Object)(object)_trackAuthor == (Object)null))
			{
				if (_currentTrack == null)
				{
					((TMP_Text)_trackTitle).text = string.Empty;
					((TMP_Text)_trackAuthor).text = string.Empty;
				}
				else
				{
					((TMP_Text)_trackTitle).text = _currentTrack.Title;
					((TMP_Text)_trackAuthor).text = (string.IsNullOrWhiteSpace(_currentTrack.Author) ? string.Empty : ("BY " + _currentTrack.Author));
				}
			}
		}

		private static TextMeshProUGUI CreateText(RectTransform parent, string name, TMP_FontAsset font, float fontSize, TextAlignmentOptions alignment, Vector2 anchoredPosition, Vector2 size)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: 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)
			TextMeshProUGUI obj = ((Component)CreateRect(parent, name, Vector2.zero, Vector2.zero, Vector2.zero, size, anchoredPosition)).gameObject.AddComponent<TextMeshProUGUI>();
			((TMP_Text)obj).font = font;
			((TMP_Text)obj).fontSize = fontSize;
			((TMP_Text)obj).fontStyle = (FontStyles)0;
			((TMP_Text)obj).alignment = alignment;
			((TMP_Text)obj).enableWordWrapping = false;
			((TMP_Text)obj).overflowMode = (TextOverflowModes)1;
			((Graphic)obj).raycastTarget = false;
			((TMP_Text)obj).outlineWidth = 0.12f;
			((TMP_Text)obj).outlineColor = new Color32((byte)20, (byte)0, (byte)0, (byte)210);
			((TMP_Text)obj).margin = Vector4.zero;
			return obj;
		}

		private static RectTransform CreateRect(RectTransform parent, string name, Vector2 anchorMin, Vector2 anchorMax, Vector2 pivot, Vector2 size, Vector2 anchoredPosition)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//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)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: 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_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			RectTransform val = (RectTransform)new GameObject(name, new Type[1] { typeof(RectTransform) }).transform;
			((Transform)val).SetParent((Transform)(object)parent, false);
			val.anchorMin = anchorMin;
			val.anchorMax = anchorMax;
			val.pivot = pivot;
			val.sizeDelta = size;
			val.anchoredPosition = anchoredPosition;
			return val;
		}

		private static void StretchToParent(RectTransform rect)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: 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)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			rect.anchorMin = Vector2.zero;
			rect.anchorMax = Vector2.one;
			rect.pivot = new Vector2(0.5f, 0.5f);
			rect.offsetMin = Vector2.zero;
			rect.offsetMax = Vector2.zero;
		}

		private static void SetAnchoredLayout(RectTransform rect, Vector2 anchor, Vector2 pivot, Vector2 anchoredPosition)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			rect.anchorMin = anchor;
			rect.anchorMax = anchor;
			rect.pivot = pivot;
			rect.anchoredPosition = anchoredPosition;
		}

		private static Sprite CreateDiscSprite()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: 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)
			//IL_0074: 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)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			_discTexture = new Texture2D(64, 64, (TextureFormat)4, false)
			{
				name = "Combined Meltdown Music Disc",
				filterMode = (FilterMode)1,
				wrapMode = (TextureWrapMode)1,
				hideFlags = (HideFlags)61
			};
			Color[] array = (Color[])(object)new Color[4096];
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(31.5f, 31.5f);
			float num = 30.08f;
			float num2 = 7.68f;
			for (int i = 0; i < 64; i++)
			{
				for (int j = 0; j < 64; j++)
				{
					Vector2 val2 = new Vector2((float)j, (float)i) - val;
					float magnitude = ((Vector2)(ref val2)).magnitude;
					Color clear = Color.clear;
					if (magnitude <= num && magnitude >= num2)
					{
						float num3 = Mathf.SmoothStep(0f, 1f, (num - magnitude) / 1.5f);
						float num4 = 0.48f + 0.18f * Mathf.Sin(magnitude * 1.35f);
						float num5 = Mathf.Clamp01((val2.x - val2.y + 8f) / 18f) * 0.18f;
						((Color)(ref clear))..ctor(1f, 1f, 1f, Mathf.Clamp01((num4 + num5) * num3));
					}
					array[i * 64 + j] = clear;
				}
			}
			_discTexture.SetPixels(array);
			_discTexture.Apply(false, true);
			Sprite obj = Sprite.Create(_discTexture, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 64f);
			((Object)obj).name = "Combined Meltdown Music Disc";
			((Object)obj).hideFlags = (HideFlags)61;
			return obj;
		}

		private static Sprite CreateTonearmSprite()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: 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_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			_tonearmTexture = new Texture2D(64, 64, (TextureFormat)4, false)
			{
				name = "Combined Meltdown Record Player Tonearm",
				filterMode = (FilterMode)1,
				wrapMode = (TextureWrapMode)1,
				hideFlags = (HideFlags)61
			};
			Color[] array = (Color[])(object)new Color[4096];
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(54f, 55f);
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(45f, 43f);
			Vector2 end = default(Vector2);
			((Vector2)(ref end))..ctor(39f, 37f);
			for (int i = 0; i < 64; i++)
			{
				for (int j = 0; j < 64; j++)
				{
					Vector2 val3 = new Vector2((float)j, (float)i);
					float num = Vector2.Distance(val3, val);
					float num2 = DistanceToSegment(val3, val, val2);
					float num3 = DistanceToSegment(val3, val2, end);
					float num4 = 0f;
					if (num <= 5.5f)
					{
						num4 = ((num >= 2.4f) ? 0.95f : 0.32f);
					}
					if (num2 <= 1.8f)
					{
						num4 = Mathf.Max(num4, 0.92f);
					}
					if (num3 <= 3.1f)
					{
						num4 = Mathf.Max(num4, 1f);
					}
					array[i * 64 + j] = new Color(1f, 1f, 1f, num4);
				}
			}
			_tonearmTexture.SetPixels(array);
			_tonearmTexture.Apply(false, true);
			Sprite obj = Sprite.Create(_tonearmTexture, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 64f);
			((Object)obj).name = "Combined Meltdown Record Player Tonearm";
			((Object)obj).hideFlags = (HideFlags)61;
			return obj;
		}

		private static Sprite CreateTimerPanelSprite()
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: 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)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			_timerPanelTexture = new Texture2D(202, 94, (TextureFormat)4, false)
			{
				name = "Combined Meltdown Rounded Reactor Panel",
				filterMode = (FilterMode)1,
				wrapMode = (TextureWrapMode)1,
				hideFlags = (HideFlags)61
			};
			Color[] array = (Color[])(object)new Color[18988];
			Vector2 center = default(Vector2);
			((Vector2)(ref center))..ctor(100.5f, 46.5f);
			Vector2 halfSize = default(Vector2);
			((Vector2)(ref halfSize))..ctor(100.5f, 46.5f);
			for (int i = 0; i < 94; i++)
			{
				for (int j = 0; j < 202; j++)
				{
					float num = ((RoundedRectangleDistance(j, i, center, halfSize, 11f) <= -1f) ? 0.95f : 0f);
					array[i * 202 + j] = new Color(1f, 1f, 1f, num);
				}
			}
			_timerPanelTexture.SetPixels(array);
			_timerPanelTexture.Apply(false, true);
			Sprite obj = Sprite.Create(_timerPanelTexture, new Rect(0f, 0f, 202f, 94f), new Vector2(0.5f, 0.5f), 100f);
			((Object)obj).name = "Combined Meltdown Rounded Reactor Panel";
			((Object)obj).hideFlags = (HideFlags)61;
			return obj;
		}

		private static Sprite CreateTimerHighlightSprite()
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: 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)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			_timerHighlightTexture = new Texture2D(202, 94, (TextureFormat)4, false)
			{
				name = "Combined Meltdown Reactor Highlight",
				filterMode = (FilterMode)1,
				wrapMode = (TextureWrapMode)1,
				hideFlags = (HideFlags)61
			};
			Color[] array = (Color[])(object)new Color[18988];
			Vector2 center = default(Vector2);
			((Vector2)(ref center))..ctor(100.5f, 46.5f);
			Vector2 halfSize = default(Vector2);
			((Vector2)(ref halfSize))..ctor(100.5f, 46.5f);
			for (int i = 0; i < 94; i++)
			{
				for (int j = 0; j < 202; j++)
				{
					float num = RoundedRectangleDistance(j, i, center, halfSize, 11f);
					bool num2 = num <= 0f && num >= -2f;
					bool flag = Mathf.Abs((float)i - 63f) <= 1f && j >= 9 && j < 193;
					float num3 = ((num2 || flag) ? 0.96f : 0f);
					array[i * 202 + j] = new Color(1f, 1f, 1f, num3);
				}
			}
			_timerHighlightTexture.SetPixels(array);
			_timerHighlightTexture.Apply(false, true);
			Sprite obj = Sprite.Create(_timerHighlightTexture, new Rect(0f, 0f, 202f, 94f), new Vector2(0.5f, 0.5f), 100f);
			((Object)obj).name = "Combined Meltdown Reactor Highlight";
			((Object)obj).hideFlags = (HideFlags)61;
			return obj;
		}

		private static float RoundedRectangleDistance(float x, float y, Vector2 center, Vector2 halfSize, float cornerRadius)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//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_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: 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)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: 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_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = new Vector2(Mathf.Abs(x - center.x), Mathf.Abs(y - center.y)) - (halfSize - Vector2.one * cornerRadius);
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(Mathf.Max(val.x, 0f), Mathf.Max(val.y, 0f));
			return Mathf.Min(Mathf.Max(val.x, val.y), 0f) + ((Vector2)(ref val2)).magnitude - cornerRadius;
		}

		private static float DistanceToSegment(Vector2 point, Vector2 start, Vector2 end)
		{
			//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)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: 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_0019: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = end - start;
			float sqrMagnitude = ((Vector2)(ref val)).sqrMagnitude;
			if (sqrMagnitude <= Mathf.Epsilon)
			{
				return Vector2.Distance(point, start);
			}
			float num = Mathf.Clamp01(Vector2.Dot(point - start, val) / sqrMagnitude);
			return Vector2.Distance(point, start + val * num);
		}

		private static void Hide()
		{
			if ((Object)(object)_root != (Object)null)
			{
				_root.SetActive(false);
			}
		}
	}
	[BepInPlugin("combinedmeltdownplaylist.sync", "Combined Meltdown Playlist Sync", "1.4.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInProcess("Lethal Company.exe")]
	public sealed class Plugin : BaseUnityPlugin
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static HandleNamedMessageDelegate <0>__HandleSelectionMessage;

			public static HandleNamedMessageDelegate <1>__Receive;
		}

		public const string PluginGuid = "combinedmeltdownplaylist.sync";

		public const string PluginName = "Combined Meltdown Playlist Sync";

		public const string PluginVersion = "1.4.1";

		internal const string PlaylistTag = "CombinedMeltdownPlaylist";

		internal const string SelectionMessageName = "CombinedMeltdownPlaylist.Selection.v1";

		internal const string ConfigMessageName = "CombinedMeltdownPlaylist.Config.v1";

		private Harmony? _harmony;

		internal static Plugin Instance { get; private set; }

		internal static ManualLogSource ModLog { get; private set; }

		internal static NetworkManager? RegisteredNetworkManager { get; private set; }

		internal static ConfigEntry<float> ExtraStaminaPercent { get; private set; }

		internal static ConfigEntry<float> ExtraStaminaRegenPercent { get; private set; }

		private void Awake()
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Expected O, but got Unknown
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Expected O, but got Unknown
			Instance = this;
			ModLog = ((BaseUnityPlugin)this).Logger;
			AcceptableValueRange<float> val = new AcceptableValueRange<float>(0f, 1000f);
			ExtraStaminaPercent = ((BaseUnityPlugin)this).Config.Bind<float>("Meltdown Stamina", "ExtraStaminaPercent", 20f, new ConfigDescription("Percentage of extra effective stamina capacity during a meltdown. For example, 20 means 20% more stamina. Applied to the final stamina drain so upgrades from other mods remain included.", (AcceptableValueBase)(object)val, Array.Empty<object>()));
			ExtraStaminaRegenPercent = ((BaseUnityPlugin)this).Config.Bind<float>("Meltdown Stamina", "ExtraStaminaRegenPercent", 50f, new ConfigDescription("Percentage of extra stamina regeneration during a meltdown. For example, 50 means regeneration is 50% faster. Applied to the final regeneration produced by the game and other mods.", (AcceptableValueBase)(object)val, Array.Empty<object>()));
			HudConfig.Bind(((BaseUnityPlugin)this).Config);
			HostConfigSynchronizer.Reset();
			_harmony = new Harmony("combinedmeltdownplaylist.sync");
			_harmony.PatchAll();
			ModLog.LogInfo((object)"Combined Meltdown Playlist Sync 1.4.1 loaded.");
		}

		private void Update()
		{
			EnsureNetworkRegistration();
			HostConfigSynchronizer.Tick();
			LazyMusicPlayer.Tick();
			StaminaBoostController.Tick();
			ForcedTakeoffFailsafe.Tick();
			MeltdownHudController.Tick();
		}

		private void OnDestroy()
		{
			StaminaBoostController.ForceDeactivate("plugin shutdown");
			ForcedTakeoffFailsafe.Reset();
			LazyMusicPlayer.Stop();
			UnregisterMessageHandlers();
			SelectionCoordinator.Reset();
			HostConfigSynchronizer.Reset();
			MeltdownHudController.Destroy();
			Harmony? harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		private static void EnsureNetworkRegistration()
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Expected O, but got Unknown
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Expected O, but got Unknown
			NetworkManager singleton = NetworkManager.Singleton;
			if (singleton == RegisteredNetworkManager && ((Object)(object)singleton == (Object)null || singleton.IsListening))
			{
				return;
			}
			UnregisterMessageHandlers();
			SelectionCoordinator.Reset();
			HostConfigSynchronizer.Reset();
			MeltdownHudController.ResetSession();
			if ((Object)(object)singleton == (Object)null || !singleton.IsListening)
			{
				return;
			}
			try
			{
				CustomMessagingManager customMessagingManager = singleton.CustomMessagingManager;
				object obj = <>O.<0>__HandleSelectionMessage;
				if (obj == null)
				{
					HandleNamedMessageDelegate val = HandleSelectionMessage;
					<>O.<0>__HandleSelectionMessage = val;
					obj = (object)val;
				}
				customMessagingManager.RegisterNamedMessageHandler("CombinedMeltdownPlaylist.Selection.v1", (HandleNamedMessageDelegate)obj);
				CustomMessagingManager customMessagingManager2 = singleton.CustomMessagingManager;
				object obj2 = <>O.<1>__Receive;
				if (obj2 == null)
				{
					HandleNamedMessageDelegate val2 = HostConfigSynchronizer.Receive;
					<>O.<1>__Receive = val2;
					obj2 = (object)val2;
				}
				customMessagingManager2.RegisterNamedMessageHandler("CombinedMeltdownPlaylist.Config.v1", (HandleNamedMessageDelegate)obj2);
				RegisteredNetworkManager = singleton;
				HostConfigSynchronizer.ForceBroadcast();
				ModLog.LogDebug((object)"Registered the synchronized playlist and host-config message handlers.");
			}
			catch (Exception arg)
			{
				ModLog.LogError((object)$"Could not register the synchronization message handlers: {arg}");
			}
		}

		private static void UnregisterMessageHandlers()
		{
			if ((Object)(object)RegisteredNetworkManager == (Object)null)
			{
				return;
			}
			try
			{
				RegisteredNetworkManager.CustomMessagingManager.UnregisterNamedMessageHandler("CombinedMeltdownPlaylist.Selection.v1");
				RegisteredNetworkManager.CustomMessagingManager.UnregisterNamedMessageHandler("CombinedMeltdownPlaylist.Config.v1");
			}
			catch (Exception ex)
			{
				ModLog.LogDebug((object)("Message handlers were already unavailable: " + ex.Message));
			}
			finally
			{
				RegisteredNetworkManager = null;
			}
		}

		private static void HandleSelectionMessage(ulong senderClientId, FastBufferReader reader)
		{
			NetworkManager registeredNetworkManager = RegisteredNetworkManager;
			if ((Object)(object)registeredNetworkManager == (Object)null || registeredNetworkManager.IsServer)
			{
				return;
			}
			if (senderClientId != 0L)
			{
				ModLog.LogWarning((object)$"Ignored a playlist selection from non-host client {senderClientId}.");
				return;
			}
			try
			{
				string selectedTrack = default(string);
				((FastBufferReader)(ref reader)).ReadValueSafe(ref selectedTrack, true);
				SelectionCoordinator.ReceiveHostSelection(selectedTrack);
			}
			catch (Exception arg)
			{
				ModLog.LogError((object)$"Could not read the host's playlist selection: {arg}");
			}
		}

		internal unsafe static bool BroadcastSelection(string selectedTrack)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager registeredNetworkManager = RegisteredNetworkManager;
			if ((Object)(object)registeredNetworkManager == (Object)null || !registeredNetworkManager.IsListening || !registeredNetworkManager.IsServer)
			{
				return false;
			}
			try
			{
				HostConfigSynchronizer.ForceBroadcast();
				FastBufferWriter val = default(FastBufferWriter);
				((FastBufferWriter)(ref val))..ctor(512, (Allocator)2, -1);
				try
				{
					((FastBufferWriter)(ref val)).WriteValueSafe(selectedTrack, true);
					registeredNetworkManager.CustomMessagingManager.SendNamedMessageToAll("CombinedMeltdownPlaylist.Selection.v1", val, (NetworkDelivery)3);
					return true;
				}
				finally
				{
					((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
				}
			}
			catch (Exception arg)
			{
				ModLog.LogError((object)$"Could not broadcast the playlist selection: {arg}");
				return false;
			}
		}
	}
	[HarmonyPatch(typeof(MusicManager), "LoadMusicClip")]
	internal static class MusicManagerLoadMusicClipPatch
	{
		private static bool Prefix(string musicFileName, ref Task<AudioClip?> __result)
		{
			if (!TrackMetadata.Contains(musicFileName))
			{
				return true;
			}
			__result = Task.FromResult<AudioClip>(null);
			return false;
		}
	}
	[HarmonyPatch(typeof(MusicManager), "PlayMusic")]
	internal static class MusicManagerPlayMusicPatch
	{
		private static bool Prefix(MusicManager __instance, Script script, ScriptEvent_PlayMusic musicEvent)
		{
			if (!string.Equals(musicEvent.tag, "CombinedMeltdownPlaylist", StringComparison.Ordinal))
			{
				return true;
			}
			SelectionCoordinator.Intercept(__instance, script, musicEvent);
			return false;
		}
	}
	[HarmonyPatch(typeof(MusicManager), "StopMusic")]
	internal static class MusicManagerStopMusicPatch
	{
		private static void Postfix(string? targetTag = null)
		{
			if (targetTag == null || string.Equals(targetTag, "CombinedMeltdownPlaylist", StringComparison.Ordinal))
			{
				LazyMusicPlayer.Stop();
			}
		}
	}
	[HarmonyPatch(typeof(MusicManager), "FadeStopMusic")]
	internal static class MusicManagerFadeStopMusicPatch
	{
		private static void Postfix(string? targetTag = null)
		{
			if (targetTag == null || string.Equals(targetTag, "CombinedMeltdownPlaylist", StringComparison.Ordinal))
			{
				LazyMusicPlayer.Stop();
			}
		}
	}
	internal static class SelectionCoordinator
	{
		private static MusicManager? _waitingManager;

		private static Script? _waitingScript;

		private static ScriptEvent_PlayMusic? _waitingEvent;

		private static string? _pendingSelection;

		internal static void Intercept(MusicManager manager, Script script, ScriptEvent_PlayMusic musicEvent)
		{
			string[] musicNames = musicEvent.musicNames;
			if (musicNames == null || musicNames.Length == 0)
			{
				Plugin.ModLog.LogError((object)"The combined meltdown playlist has no tracks.");
				return;
			}
			_waitingManager = manager;
			_waitingScript = script;
			_waitingEvent = musicEvent;
			NetworkManager registeredNetworkManager = Plugin.RegisteredNetworkManager;
			if ((Object)(object)registeredNetworkManager == (Object)null || !registeredNetworkManager.IsListening)
			{
				string selectedTrack = musicNames[Random.Range(0, musicNames.Length)];
				Plugin.ModLog.LogWarning((object)"Networking was not ready; selecting the meltdown track locally.");
				StartSelectedTrack(manager, script, musicEvent, selectedTrack);
				Reset();
			}
			else if (registeredNetworkManager.IsServer)
			{
				string text = musicNames[Random.Range(0, musicNames.Length)];
				if (!Plugin.BroadcastSelection(text))
				{
					Plugin.ModLog.LogWarning((object)"The host selection could not be broadcast; playing it locally.");
				}
				Plugin.ModLog.LogInfo((object)("Host selected meltdown track: " + text));
				StartSelectedTrack(manager, script, musicEvent, text);
				Reset();
			}
			else if (!registeredNetworkManager.IsClient)
			{
				Reset();
			}
			else if (_pendingSelection == null)
			{
				Plugin.ModLog.LogDebug((object)"Waiting for the host's meltdown track selection.");
			}
			else
			{
				string pendingSelection = _pendingSelection;
				_pendingSelection = null;
				PlayReceivedSelection(manager, script, musicEvent, pendingSelection);
			}
		}

		internal static void ReceiveHostSelection(string selectedTrack)
		{
			if (string.IsNullOrWhiteSpace(selectedTrack))
			{
				Plugin.ModLog.LogWarning((object)"Ignored an empty playlist selection from the host.");
			}
			else if ((Object)(object)_waitingManager == (Object)null || _waitingScript == null || _waitingEvent == null)
			{
				_pendingSelection = selectedTrack;
				Plugin.ModLog.LogDebug((object)("Stored the host's early playlist selection: " + selectedTrack));
			}
			else
			{
				PlayReceivedSelection(_waitingManager, _waitingScript, _waitingEvent, selectedTrack);
			}
		}

		internal static void Reset()
		{
			_waitingManager = null;
			_waitingScript = null;
			_waitingEvent = null;
			_pendingSelection = null;
		}

		private static void PlayReceivedSelection(MusicManager manager, Script script, ScriptEvent_PlayMusic musicEvent, string selectedTrack)
		{
			if (!ContainsChoice(musicEvent.musicNames, selectedTrack))
			{
				Plugin.ModLog.LogError((object)("The host selected '" + selectedTrack + "', but it is not in this client's playlist. All players must install the same package version."));
				Reset();
			}
			else
			{
				Plugin.ModLog.LogInfo((object)("Streaming host-selected meltdown track: " + selectedTrack));
				StartSelectedTrack(manager, script, musicEvent, selectedTrack);
				Reset();
			}
		}

		private static void StartSelectedTrack(MusicManager manager, Script script, ScriptEvent_PlayMusic musicEvent, string selectedTrack)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected I4, but got Unknown
			OverlapHandling overlapHandling = musicEvent.overlapHandling;
			switch (overlapHandling - 2)
			{
			case 0:
				manager.StopMusic((string)null);
				break;
			case 1:
				manager.StopMusic(musicEvent.tag);
				break;
			case 2:
				manager.FadeStopMusic((string)null);
				break;
			case 3:
				manager.FadeStopMusic(musicEvent.tag);
				break;
			}
			LazyMusicPlayer.Play(script, musicEvent, selectedTrack);
		}

		private static bool ContainsChoice(string[] choices, string selectedTrack)
		{
			for (int i = 0; i < choices.Length; i++)
			{
				if (string.Equals(choices[i], selectedTrack, StringComparison.Ordinal))
				{
					return true;
				}
			}
			return false;
		}
	}
	internal static class LazyMusicPlayer
	{
		private static readonly FieldInfo? MasterVolumeField = AccessTools.Field(typeof(Configuration), "volumeMaster");

		private static Coroutine? _loadCoroutine;

		private static AudioSource? _audioSource;

		private static AudioClip? _audioClip;

		private static float _scriptVolume = 1f;

		private static bool _silenceGameMusic;

		private static int _playGeneration;

		internal static void Play(Script script, ScriptEvent_PlayMusic musicEvent, string filename)
		{
			Stop();
			_playGeneration++;
			int playGeneration = _playGeneration;
			_scriptVolume = script.TryGetVolumeGroupOrDefault(musicEvent.tag).GetVolume(script);
			_silenceGameMusic = musicEvent.silenceGameMusic;
			_loadCoroutine = ((MonoBehaviour)Plugin.Instance).StartCoroutine(LoadAndPlay(filename, musicEvent, playGeneration));
		}

		internal static void Tick()
		{
			if ((Object)(object)_audioSource == (Object)null || !_audioSource.isPlaying)
			{
				return;
			}
			_audioSource.volume = _scriptVolume * GetMasterVolume();
			if (_silenceGameMusic)
			{
				if ((Object)(object)SoundManager.Instance != (Object)null && SoundManager.Instance.playingOutsideMusic)
				{
					SoundManager.Instance.playingOutsideMusic = false;
				}
				if ((Object)(object)TimeOfDay.Instance != (Object)null && (Object)(object)TimeOfDay.Instance.TimeOfDayMusic != (Object)null && TimeOfDay.Instance.TimeOfDayMusic.isPlaying)
				{
					TimeOfDay.Instance.TimeOfDayMusic.Stop();
				}
			}
		}

		internal static void Stop()
		{
			_playGeneration++;
			if (_loadCoroutine != null && (Object)(object)Plugin.Instance != (Object)null)
			{
				((MonoBehaviour)Plugin.Instance).StopCoroutine(_loadCoroutine);
				_loadCoroutine = null;
			}
			if ((Object)(object)_audioSource != (Object)null)
			{
				_audioSource.Stop();
				Object.Destroy((Object)(object)_audioSource);
				_audioSource = null;
			}
			if ((Object)(object)_audioClip != (Object)null)
			{
				_audioClip.UnloadAudioData();
				Object.Destroy((Object)(object)_audioClip);
				_audioClip = null;
			}
			_silenceGameMusic = false;
		}

		private static IEnumerator LoadAndPlay(string filename, ScriptEvent_PlayMusic musicEvent, int generation)
		{
			string text = Path.Combine(Path.GetDirectoryName(typeof(Plugin).Assembly.Location) ?? Paths.PluginPath, "BGN-PizzaTowerEscapeMusic", "Music", filename);
			if (!File.Exists(text))
			{
				Plugin.ModLog.LogError((object)("Cannot stream meltdown music because the file is missing: " + text));
				yield break;
			}
			string absoluteUri = new Uri(text).AbsoluteUri;
			UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(absoluteUri, (AudioType)14);
			try
			{
				DownloadHandler downloadHandler = request.downloadHandler;
				DownloadHandlerAudioClip val = (DownloadHandlerAudioClip)(object)((downloadHandler is DownloadHandlerAudioClip) ? downloadHandler : null);
				if (val != null)
				{
					val.streamAudio = true;
				}
				request.SendWebRequest();