Decompiled source of PeakRadio v1.0.0

peakradiomod.peakradiomod.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using PEAKLib.Core;
using PEAKLib.Items;
using PEAKLib.UI;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using UnityEngine.SceneManagement;

[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("peakradiomod.peakradiomod")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+ea939fdc914272f1a2a4c62ea2f6e113343029dd")]
[assembly: AssemblyProduct("peakradiomod.peakradiomod")]
[assembly: AssemblyTitle("PeakRadioMod")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace MonoDetour.HookGen
{
	internal static class DefaultMonoDetourManager
	{
		internal static MonoDetourManager Instance { get; } = New();


		internal static MonoDetourManager New()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			return new MonoDetourManager(typeof(DefaultMonoDetourManager).Assembly.GetName().Name);
		}
	}
	[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
	internal class MonoDetourTargetsAttribute : Attribute, IMonoDetourTargets
	{
		public Type? TargetType { get; }

		public bool IncludeNestedTypes { get; set; }

		public bool DistinguishOverloadsByName { get; set; }

		public string[]? Members { get; set; }

		public string[]? MemberNamePrefixes { get; set; }

		public string[]? MemberNameSuffixes { get; set; }

		public bool GenerateControlFlowVariants { get; set; }

		public MonoDetourTargetsAttribute(Type? targetType = null)
		{
			TargetType = targetType;
			IncludeNestedTypes = true;
			base..ctor();
		}
	}
}
namespace BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace PeakRadio
{
	internal static class AssetPaths
	{
		internal const string RADIO_PREFAB_PATH = "assets/peakradio/radio.prefab";

		internal const string RADIO_ICON_PATH = "assets/peakradio/icon/icon.png";

		internal const string RADIO_AUDIO_PATH = "assets/peakradio/audio/music/alltracks.ogg";

		internal const string TUNING_NOISE_PREFIX = "assets/peakradio/audio/noise/tune";

		internal const string TUNING_NOISE_SUFFIX = ".ogg";

		internal const string CLICK_NOISE_PATH = "assets/peakradio/audio/click/radio_click.ogg";

		internal const string MANAGER_PREFAB_PATH = "assets/peakradio/radiomanager.prefab";
	}
	[HarmonyPatch(typeof(Item), "DenyPickupRPC")]
	public static class Item_DenyPickupRPC_Patch
	{
		[HarmonyPostfix]
		public static void Postfix(Item __instance)
		{
			GameObject gameObject = ((Component)__instance).gameObject;
			if (Object.op_Implicit((Object)(object)gameObject))
			{
				(gameObject.GetComponent<RadioBehavior>() ?? gameObject.GetComponentInChildren<RadioBehavior>(true) ?? gameObject.GetComponentInParent<RadioBehavior>())?.GetAudioSourceFromManager();
			}
		}
	}
	[HarmonyPatch(typeof(PhotonNetwork))]
	internal static class PhotonNetwork_LoggingPatches
	{
		[HarmonyPrefix]
		[HarmonyPatch("Destroy", new Type[] { typeof(GameObject) })]
		private static void Pre_Destroy_GO(GameObject targetGo)
		{
			bool flag = false;
			if (Object.op_Implicit((Object)(object)targetGo))
			{
				flag = (Object)(object)targetGo.GetComponent<RadioBehavior>() != (Object)null || (Object)(object)targetGo.GetComponentInChildren<RadioBehavior>(true) != (Object)null || (Object)(object)targetGo.GetComponentInParent<RadioBehavior>() != (Object)null;
			}
			if (flag)
			{
				Item val = (Object.op_Implicit((Object)(object)targetGo) ? targetGo.GetComponent<Item>() : null);
				string text = ((val?.data != null) ? ((object)val.data).ToString() : "null");
				Plugin.LogInfoTS("[PN.Destroy:PRE GameObject] go=" + (((targetGo != null) ? ((Object)targetGo).name : null) ?? "null") + " item=" + (Object.op_Implicit((Object)(object)val) ? ((Object)val).name : "—") + " iid=" + text);
				if (Object.op_Implicit((Object)(object)targetGo))
				{
					(targetGo.GetComponent<RadioBehavior>() ?? targetGo.GetComponentInChildren<RadioBehavior>(true) ?? targetGo.GetComponentInParent<RadioBehavior>())?.ReturnAudioSourceToManager();
				}
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch("Destroy", new Type[] { typeof(PhotonView) })]
		private static void Pre_Destroy_PV(PhotonView targetView)
		{
			GameObject val = (Object.op_Implicit((Object)(object)targetView) ? ((Component)targetView).gameObject : null);
			bool flag = false;
			if (Object.op_Implicit((Object)(object)val))
			{
				flag = (Object)(object)val.GetComponent<RadioBehavior>() != (Object)null || (Object)(object)val.GetComponentInChildren<RadioBehavior>(true) != (Object)null || (Object)(object)val.GetComponentInParent<RadioBehavior>() != (Object)null;
			}
			if (flag)
			{
				Item val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<Item>() : null);
				string text = ((val2?.data != null) ? ((object)val2.data).ToString() : "null");
				Plugin.LogInfoTS(string.Format("[PN.Destroy:PRE PhotonView] pv={0} go={1} item={2} iid={3}", (targetView != null) ? new int?(targetView.ViewID) : null, ((val != null) ? ((Object)val).name : null) ?? "null", Object.op_Implicit((Object)(object)val2) ? ((Object)val2).name : "—", text));
				if (Object.op_Implicit((Object)(object)val))
				{
					(val.GetComponent<RadioBehavior>() ?? val.GetComponentInChildren<RadioBehavior>(true) ?? val.GetComponentInParent<RadioBehavior>())?.ReturnAudioSourceToManager();
				}
			}
		}
	}
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("peakradiomod.peakradiomod", "PeakRadioMod", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		[CompilerGenerated]
		private sealed class <LoadSharedRadioClip>d__33 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

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

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

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

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

			private bool MoveNext()
			{
				if (<>1__state != 0)
				{
					return false;
				}
				<>1__state = -1;
				SharedRadioClip = Bundle.LoadAsset<AudioClip>("assets/peakradio/audio/music/alltracks.ogg");
				SharedRadioClipLoaded = (Object)(object)SharedRadioClip != (Object)null;
				if (SharedRadioClipLoaded)
				{
					LogInfoTS("Shared radio audio loaded successfully from bundle!");
				}
				else
				{
					LogInfoTS("Failed to load shared AudioClip from bundle at assets/peakradio/audio/music/alltracks.ogg");
				}
				int num = 0;
				while (true)
				{
					string text = string.Format("{0}{1}{2}", "assets/peakradio/audio/noise/tune", num, ".ogg");
					AudioClip val = Bundle.LoadAsset<AudioClip>(text);
					if ((Object)(object)val == (Object)null)
					{
						break;
					}
					TuningNoiseClips.Add(val);
					LogInfoTS("Tuning noise audio loaded from bundle: " + text);
					num++;
				}
				if (TuningNoiseClips.Count == 0)
				{
					LogInfoTS("No tuning noise clips found in bundle!");
				}
				ClickNoiseClip = Bundle.LoadAsset<AudioClip>("assets/peakradio/audio/click/radio_click.ogg");
				if ((Object)(object)ClickNoiseClip != (Object)null)
				{
					LogInfoTS("Click noise audio loaded successfully from bundle!");
				}
				else
				{
					LogInfoTS("Click noise audio not found in bundle!");
				}
				return false;
			}

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

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

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

			private object <>2__current;

			private int <attempt>5__2;

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

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

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

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

			private bool MoveNext()
			{
				//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ac: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<attempt>5__2 = 0;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				while (!RadioLocalization.Initialized && <attempt>5__2 < 30)
				{
					<attempt>5__2++;
					try
					{
						RadioLocalization.Init();
					}
					catch (Exception ex)
					{
						if (<attempt>5__2 == 1)
						{
							LogInfoTS($"Localization init not ready (attempt {<attempt>5__2}): {ex.Message}");
						}
						else if (<attempt>5__2 % 5 == 0)
						{
							LogInfoTS($"Localization still not ready after {<attempt>5__2} attempts: {ex.Message}");
						}
					}
					if (!RadioLocalization.Initialized)
					{
						<>2__current = (object)new WaitForSeconds(0.5f);
						<>1__state = 1;
						return true;
					}
				}
				if (!RadioLocalization.Initialized)
				{
					LogInfoTS("Radio localization did not initialize after retries; using fallback English prompt strings.");
				}
				return false;
			}

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

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

		internal static string bundleName = "peakradio.bundle";

		internal static AudioClip? SharedRadioClip = null;

		internal static bool SharedRadioClipLoaded = false;

		internal static AudioClip? TuningNoiseClip = null;

		internal static AudioClip? ClickNoiseClip = null;

		internal static List<AudioClip> TuningNoiseClips = new List<AudioClip>();

		internal static GameObject? RadioPrefabRef;

		internal static bool isDebugMode = false;

		public const string Id = "peakradiomod.peakradiomod";

		public static Plugin Instance { get; private set; } = null;


		internal static ManualLogSource Log { get; private set; } = null;


		internal static Harmony? Harmony { get; set; }

		internal static AssetBundle Bundle { get; set; } = null;


		internal static ModDefinition Definition { get; set; } = null;


		public static string Name => "PeakRadioMod";

		public static string Version => "1.0.0";

		private void Awake()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			Definition = ModDefinition.GetOrCreate(((BaseUnityPlugin)this).Info.Metadata);
			Harmony val = new Harmony("com.yourname.item-audio-logger");
			val.PatchAll();
			string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), bundleName);
			LogInfoTS("AssetBundlePath resolved to: " + text);
			LogInfoTS($"AssetBundle file exists: {File.Exists(text)}");
			Bundle = AssetBundle.LoadFromFile(text);
			if ((Object)(object)Bundle == (Object)null)
			{
				LogInfoTS("Failed to load AssetBundle from " + text);
				return;
			}
			string[] allAssetNames = Bundle.GetAllAssetNames();
			LogInfoTS("Assets in bundle: " + string.Join(", ", allAssetNames));
			GameObject val2 = Bundle.LoadAsset<GameObject>("assets/peakradio/radiomanager.prefab");
			if ((Object)(object)val2 == (Object)null)
			{
				LogInfoTS("RadioManager prefab not found in bundle at assets/peakradio/radiomanager.prefab!");
				return;
			}
			val2.AddComponent<RadioManager>();
			NetworkPrefabManager.RegisterNetworkPrefab(Definition, "", val2);
			GameObject val3 = Bundle.LoadAsset<GameObject>("assets/peakradio/radio.prefab");
			if ((Object)(object)val3 == (Object)null)
			{
				LogInfoTS("Radio prefab not found in bundle at assets/peakradio/radio.prefab!");
				return;
			}
			if ((Object)(object)val3.GetComponent<RadioBehavior>() == (Object)null)
			{
				LogInfoTS("Adding RadioBehavior component to radio prefab");
				val3.AddComponent<RadioBehavior>();
			}
			RadioPrefabRef = val3;
			Transform val4 = val3.transform.Find("radio/lamp/light");
			Light val5 = (((Object)(object)val4 != (Object)null) ? ((Component)val4).GetComponent<Light>() : null);
			if ((Object)(object)val5 != (Object)null)
			{
				val5.intensity = 0f;
				val5.range = 0f;
				LogInfoTS("Lamp light intensity and range set successfully.");
			}
			else
			{
				LogInfoTS("Lamp light component not found in radio prefab.");
			}
			LogInfoTS("Radio prefab loaded from bundle");
			SceneManager.sceneLoaded -= OnSceneLoaded;
			SceneManager.sceneLoaded += OnSceneLoaded;
			RadioItemSetup.ConfigureItem(val3, "Radio", 2.5f, 0, "A radio.");
			((MonoBehaviour)this).StartCoroutine(LoadSharedRadioClip());
			LogInfoTS("Plugin " + Name + " is loaded!");
		}

		private void Start()
		{
			((MonoBehaviour)this).StartCoroutine(TryInitLocalizationDelayed());
		}

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

		[IteratorStateMachine(typeof(<TryInitLocalizationDelayed>d__31))]
		private IEnumerator TryInitLocalizationDelayed()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <TryInitLocalizationDelayed>d__31(0);
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			if (PhotonNetwork.IsConnected && PhotonNetwork.IsMasterClient && ((Scene)(ref scene)).name.StartsWith("Level_", StringComparison.OrdinalIgnoreCase))
			{
				if (RadioSpawner.FindExistingRadio())
				{
					LogInfoTS("Radio already present in scene; skipping auto-spawn.");
				}
				else
				{
					((MonoBehaviour)this).StartCoroutine(RadioSpawner.DelayedSpawnRadio(this));
				}
			}
		}

		[IteratorStateMachine(typeof(<LoadSharedRadioClip>d__33))]
		private IEnumerator LoadSharedRadioClip()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <LoadSharedRadioClip>d__33(0);
		}

		public static int GetRandomTuningNoiseClip()
		{
			if (TuningNoiseClips.Count <= 0)
			{
				return -1;
			}
			return Random.Range(0, TuningNoiseClips.Count);
		}

		public static float GetWrappedAudioTime(float time, AudioSource audioSource)
		{
			if ((Object)(object)audioSource.clip == (Object)null || audioSource.clip.length <= 0f)
			{
				return 0f;
			}
			float length = audioSource.clip.length;
			return (time % length + length) % length;
		}

		public static float GetRandomAudioTime()
		{
			if ((Object)(object)SharedRadioClip == (Object)null || SharedRadioClip.length <= 0f)
			{
				return 0f;
			}
			return Random.Range(0f, SharedRadioClip.length);
		}

		internal static void LogInfoTS(string message)
		{
			if (isDebugMode)
			{
				Log.LogInfo((object)$"[{DateTime.Now:HH:mm:ss.fff}] {message}");
			}
		}
	}
	public class RadioBehavior : MonoBehaviourPun
	{
		[CompilerGenerated]
		private sealed class <InitAfterRadioManagerStart>d__15 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public RadioBehavior <>4__this;

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

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

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

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

			private bool MoveNext()
			{
				int num = <>1__state;
				RadioBehavior radioBehavior = <>4__this;
				switch (num)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					if (!RadioManager.Instance.timeInitialized)
					{
						<>2__current = null;
						<>1__state = 1;
						return true;
					}
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				radioBehavior.GetAudioSourceFromManager();
				GameObject gameObjectAudioSource = radioBehavior.gameObjectAudioSource;
				AudioSource val = ((gameObjectAudioSource != null) ? gameObjectAudioSource.GetComponent<AudioSource>() : null);
				radioBehavior.radioTuner = new RadioTuner(val, radioBehavior);
				radioBehavior.radioToggleController = new RadioToggleController(val, (MonoBehaviour)(object)radioBehavior, ((MonoBehaviourPun)radioBehavior).photonView, radioBehavior.LogId, 0.25f);
				Plugin.LogInfoTS($"{radioBehavior.LogId} RadioBehavior initialized with AudioSource: {(Object)(object)val != (Object)null} after RadioManager.Start()");
				return false;
			}

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

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

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

			private object <>2__current;

			public RadioBehavior <>4__this;

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

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

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

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

			private bool MoveNext()
			{
				int num = <>1__state;
				RadioBehavior radioBehavior = <>4__this;
				switch (num)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					radioBehavior.isToggleRadioRunning = true;
					Plugin.LogInfoTS(radioBehavior.LogId + " ToggleRadioRoutine started");
					radioBehavior.playClick();
					if (radioBehavior.lamp != null)
					{
						<>2__current = ((MonoBehaviour)radioBehavior).StartCoroutine(radioBehavior.lamp.ClickPulse());
						<>1__state = 1;
						return true;
					}
					goto IL_0084;
				case 1:
					<>1__state = -1;
					goto IL_0084;
				case 2:
					{
						<>1__state = -1;
						break;
					}
					IL_0084:
					Plugin.LogInfoTS(radioBehavior.LogId + " Lamp animation done, toggling radio");
					Plugin.LogInfoTS("RadioPlaybackInfo.IsPlaying: " + RadioManager.Instance.radioPlaybackInfo.IsPlaying + " playbackinfo volume: " + RadioManager.Instance.radioPlaybackInfo.Volume);
					radioBehavior.radioToggleController?.ToggleRadio();
					break;
				}
				if (radioBehavior.radioToggleController != null && radioBehavior.radioToggleController.IsFading)
				{
					<>2__current = null;
					<>1__state = 2;
					return true;
				}
				radioBehavior.isToggleRadioRunning = false;
				return false;
			}

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

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

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

			private object <>2__current;

			public RadioBehavior <>4__this;

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

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

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

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

			private bool MoveNext()
			{
				int num = <>1__state;
				RadioBehavior radioBehavior = <>4__this;
				switch (num)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					radioBehavior.radioTuner?.TuneRadio();
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if (radioBehavior.radioTuner != null && radioBehavior.radioTuner.IsTuning)
				{
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				return false;
			}

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

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

		private AudioSource? clickAudioSource;

		private AudioClip? clickNoiseClip;

		private bool isFading;

		private const float fadeTime = 0.25f;

		private RadioTuner radioTuner;

		private RadioToggleController radioToggleController;

		private bool isToggleRadioRunning;

		private RadioLamp? lamp;

		private GameObject gameObjectAudioSource;

		private Item item;

		private string LogId
		{
			get
			{
				object arg = ((Object)this).GetInstanceID();
				PhotonView photonView = ((MonoBehaviourPun)this).photonView;
				return $"[Radio:{arg}|PV:{((photonView != null) ? new int?(photonView.ViewID) : null)}]";
			}
		}

		private void OnEnable()
		{
			GlobalEvents.OnItemRequested = (Action<Item, Character>)Delegate.Combine(GlobalEvents.OnItemRequested, new Action<Item, Character>(OnItemRequested));
		}

		private void OnItemRequested(Item item, Character interactor)
		{
			string[] obj = new string[5]
			{
				LogId,
				" OnItemRequested called for item ",
				((Object)item).name,
				" by ",
				null
			};
			object obj2;
			if (interactor == null)
			{
				obj2 = null;
			}
			else
			{
				Player player = interactor.player;
				obj2 = ((player != null) ? ((Object)player).name : null);
			}
			if (obj2 == null)
			{
				obj2 = "null";
			}
			obj[4] = (string)obj2;
			Plugin.LogInfoTS(string.Concat(obj));
			if (!((Object)(object)item != (Object)(object)this.item))
			{
				string[] obj3 = new string[5]
				{
					LogId,
					" OnItemRequested called for item ",
					((Object)item).name,
					" by ",
					null
				};
				object obj4;
				if (interactor == null)
				{
					obj4 = null;
				}
				else
				{
					Player player2 = interactor.player;
					obj4 = ((player2 != null) ? ((Object)player2).name : null);
				}
				if (obj4 == null)
				{
					obj4 = "null";
				}
				obj3[4] = (string)obj4;
				Plugin.LogInfoTS(string.Concat(obj3));
				ReturnAudioSourceToManager();
			}
		}

		private void Start()
		{
			if (PhotonNetwork.InRoom)
			{
				LogStartup();
				item = ((Component)this).GetComponent<Item>();
				SetupClickAudioSource();
				RegisterItemEvents();
				EnsureRadioManager();
				((MonoBehaviour)this).StartCoroutine(InitAfterRadioManagerStart());
			}
		}

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

		private void LogStartup()
		{
			Plugin.LogInfoTS(LogId + " _____________________________________________________________");
			Plugin.LogInfoTS(LogId + " RadioBehavior starting up");
			if ((Object)(object)((MonoBehaviourPun)this).photonView == (Object)null)
			{
				Plugin.LogInfoTS(LogId + " PhotonView component missing from Radio GameObject!");
			}
		}

		public void GetAudioSourceFromManager()
		{
			RadioManager.Instance.RequestAudioSourceOwnership(((Component)this).transform);
			gameObjectAudioSource = RadioManager.Instance.gameObjectAudioSource;
		}

		private void SetupClickAudioSource()
		{
			clickAudioSource = ((Component)this).gameObject.AddComponent<AudioSource>();
			clickAudioSource.playOnAwake = false;
			clickAudioSource.spatialBlend = 1f;
			clickAudioSource.loop = false;
			clickAudioSource.volume = 0.4f;
			clickNoiseClip = Plugin.ClickNoiseClip;
		}

		private void EnsureRadioManager()
		{
			//IL_0036: 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)
			if ((Object)(object)RadioManager.Instance == (Object)null)
			{
				Plugin.LogInfoTS(LogId + " RadioManager instance is null, creating new instance.");
				GameObject val = NetworkPrefabManager.SpawnNetworkPrefab(Plugin.Definition.Id + ":RadioManager", Vector3.zero, Quaternion.identity, (byte)0, (object[])null);
				RadioManager.Instance = val.GetComponent<RadioManager>();
			}
			else
			{
				Plugin.LogInfoTS($"{LogId} Found existing RadioManager instance: {((Object)RadioManager.Instance).GetInstanceID()}");
			}
		}

		private void RegisterItemEvents()
		{
			Item component = ((Component)this).GetComponent<Item>();
			if ((Object)(object)component != (Object)null)
			{
				component.onStashAction = (Action)Delegate.Combine(component.onStashAction, new Action(OnRadioStashed));
				component.OnPrimaryStarted = (Action)Delegate.Combine(component.OnPrimaryStarted, new Action(ToggleRadio));
				component.OnSecondaryStarted = (Action)Delegate.Combine(component.OnSecondaryStarted, new Action(TuneRadio));
				component.OnScrolled = (Action<float>)Delegate.Combine(component.OnScrolled, new Action<float>(OnItemScrolled));
			}
		}

		private void OnRadioStashed()
		{
			if (PhotonNetwork.InRoom)
			{
				RadioManager.Instance.TransferAudioSourceToPlayer(item.holderCharacter);
			}
		}

		private void OnItemScrolled(float value)
		{
			if (PhotonNetwork.InRoom)
			{
				playClick();
				((MonoBehaviourPun)this).photonView.RPC("RPC_ScrollVolume", (RpcTarget)3, new object[1] { value });
			}
		}

		[PunRPC]
		public void RPC_ScrollVolume(float value)
		{
			GameObject obj = gameObjectAudioSource;
			AudioSource val = ((obj != null) ? obj.GetComponent<AudioSource>() : null);
			if (!((Object)(object)val == (Object)null) && RadioManager.Instance.radioPlaybackInfo.IsPlaying)
			{
				if (value < 0.1f)
				{
					val.volume = Mathf.Max(0.1f, val.volume - 0.1f);
				}
				else if (value > 0f)
				{
					val.volume = Mathf.Min(1f, val.volume + 0.1f);
				}
				RadioManager.Instance.radioPlaybackInfo.Volume = val.volume;
			}
		}

		public void TuneRadio()
		{
			if (radioTuner == null || !radioTuner.IsTuning)
			{
				playClick();
				((MonoBehaviour)this).StartCoroutine(TuneRadioRoutine());
			}
		}

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

		public void ToggleRadio()
		{
			Plugin.LogInfoTS(LogId + " ToggleRadio called");
			if (!isToggleRadioRunning)
			{
				Plugin.LogInfoTS(LogId + " Starting ToggleRadio coroutine");
				((MonoBehaviour)this).StartCoroutine(ToggleRadioRoutine());
			}
		}

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

		[PunRPC]
		public void RPC_SetRadioState(bool state)
		{
			radioToggleController?.SetRadioState(state);
		}

		[PunRPC]
		public void RPC_SyncTune(int noiseIdx, float syncedTuneTime)
		{
			radioTuner?.SyncTune(noiseIdx, syncedTuneTime);
		}

		[PunRPC]
		public void RPC_SyncIsPlaying(bool isPlaying)
		{
			RadioManager.Instance.radioPlaybackInfo.IsPlaying = isPlaying;
		}

		private void playClick()
		{
			if ((Object)(object)clickAudioSource != (Object)null && (Object)(object)clickNoiseClip != (Object)null)
			{
				clickAudioSource.PlayOneShot(clickNoiseClip);
			}
		}

		public void ReturnAudioSourceToManager(bool movePosition = false)
		{
			Plugin.LogInfoTS($"{LogId} ReturnTestAudioSourceToManager called (movePosition={movePosition})");
			if ((Object)(object)gameObjectAudioSource != (Object)null && (Object)(object)RadioManager.Instance != (Object)null)
			{
				RadioManager.Instance.ReturnAudioSourceToManager(((Component)this).transform, movePosition);
				return;
			}
			if ((Object)(object)gameObjectAudioSource == (Object)null)
			{
				Plugin.LogInfoTS(LogId + " ReturnTestAudioSourceToManager: testAudioSourceGO is null");
			}
			if ((Object)(object)RadioManager.Instance == (Object)null)
			{
				Plugin.LogInfoTS(LogId + " ReturnTestAudioSourceToManager: RadioManager.Instance is null");
			}
		}

		private void OnDisable()
		{
			Plugin.LogInfoTS(LogId + " RadioBehavior OnDisable called");
			GlobalEvents.OnItemRequested = (Action<Item, Character>)Delegate.Remove(GlobalEvents.OnItemRequested, new Action<Item, Character>(OnItemRequested));
		}
	}
	internal static class RadioItemSetup
	{
		public static void ConfigureItem(GameObject radio, string rawName, float mass, int carryWeight, string description)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: 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_006f: 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_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: 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_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Expected O, but got Unknown
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Expected O, but got Unknown
			Plugin.LogInfoTS("Configuring " + rawName + "...");
			EnsureRadioNetworkingComponents(radio, mass);
			Item component = radio.GetComponent<Item>();
			if ((Object)(object)component == (Object)null)
			{
				Plugin.LogInfoTS("Item component not found on radio prefab");
				return;
			}
			component.itemTags = (ItemTags)0;
			component.UIData = new ItemUIData
			{
				itemName = rawName,
				hasMainInteract = true,
				mainInteractPrompt = "PEAKRADIO_POWER",
				hasSecondInteract = true,
				secondaryInteractPrompt = "PEAKRADIO_TUNE",
				hasScrollingInteract = true,
				scrollInteractPrompt = "PEAKRADIO_VOLUME",
				canDrop = true,
				canPocket = true,
				canThrow = true,
				isShootable = false,
				iconPositionOffset = Vector3.zero,
				iconRotationOffset = Vector3.zero,
				iconScaleOffset = 1f
			};
			AssignRadioIcon(radio);
			component.AddNameToCSV();
			ItemContent val = new ItemContent(component);
			val.Register(Plugin.Definition);
		}

		private static void EnsureRadioNetworkingComponents(GameObject radio, float mass)
		{
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			PhotonView val = radio.GetComponent<PhotonView>();
			if ((Object)(object)val == (Object)null)
			{
				val = radio.AddComponent<PhotonView>();
				Plugin.LogInfoTS("Added PhotonView to radio prefab");
			}
			Rigidbody val2 = radio.GetComponent<Rigidbody>();
			if ((Object)(object)val2 == (Object)null)
			{
				val2 = radio.AddComponent<Rigidbody>();
				val2.mass = mass;
				Plugin.LogInfoTS("Added Rigidbody to radio prefab");
			}
			val2.interpolation = (RigidbodyInterpolation)1;
			val2.collisionDetectionMode = (CollisionDetectionMode)3;
			PhotonRigidbodyView val3 = radio.GetComponent<PhotonRigidbodyView>();
			if ((Object)(object)val3 == (Object)null)
			{
				val3 = radio.AddComponent<PhotonRigidbodyView>();
				Plugin.LogInfoTS("Added PhotonRigidbodyView to radio prefab");
			}
			try
			{
				Type type = ((object)val3).GetType();
				type.GetField("m_SynchronizeVelocity", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(val3, true);
				type.GetField("m_SynchronizeAngularVelocity", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(val3, true);
			}
			catch (Exception ex)
			{
				Plugin.LogInfoTS("PhotonRigidbodyView reflection config skipped: " + ex.Message);
			}
			if (val.ObservedComponents == null)
			{
				val.ObservedComponents = new List<Component>();
			}
			if (!val.ObservedComponents.Contains((Component)(object)val3))
			{
				val.ObservedComponents.Add((Component)(object)val3);
				Plugin.LogInfoTS("Registered PhotonRigidbodyView in PhotonView.ObservedComponents");
			}
			val.Synchronization = (ViewSynchronization)3;
		}

		private static void AssignRadioIcon(GameObject radio)
		{
			Texture2D val = Plugin.Bundle.LoadAsset<Texture2D>("assets/peakradio/icon/icon.png");
			if ((Object)(object)val != (Object)null)
			{
				Item component = radio.GetComponent<Item>();
				if ((Object)(object)component != (Object)null && component.UIData != null)
				{
					component.UIData.icon = val;
					Plugin.LogInfoTS("Radio icon assigned from bundle!");
				}
				else
				{
					Plugin.LogInfoTS("Item or ItemUIData not found on radio prefab.");
				}
			}
			else
			{
				Plugin.LogInfoTS("Failed to load icon from bundle at assets/peakradio/icon/icon.png");
			}
		}
	}
	internal sealed class RadioLamp
	{
		[CompilerGenerated]
		private sealed class <ClickPulse>d__5 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public RadioLamp <>4__this;

			public float downDistance;

			public float halfDuration;

			private Vector3 <startPos>5__2;

			private Vector3 <endPos>5__3;

			private float <t>5__4;

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

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

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

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

			private bool MoveNext()
			{
				//IL_0030: Unknown result type (might be due to invalid IL or missing references)
				//IL_0035: Unknown result type (might be due to invalid IL or missing references)
				//IL_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)
				//IL_004c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0051: Unknown result type (might be due to invalid IL or missing references)
				//IL_0056: 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_0075: 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_00cf: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
				//IL_0105: 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)
				int num = <>1__state;
				RadioLamp radioLamp = <>4__this;
				switch (num)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<startPos>5__2 = radioLamp._lampRoot.localPosition;
					<endPos>5__3 = <startPos>5__2 + Vector3.down * downDistance;
					<t>5__4 = 0f;
					goto IL_00ba;
				case 1:
					<>1__state = -1;
					goto IL_00ba;
				case 2:
					{
						<>1__state = -1;
						break;
					}
					IL_00ba:
					if (<t>5__4 < halfDuration)
					{
						radioLamp._lampRoot.localPosition = Vector3.Lerp(<startPos>5__2, <endPos>5__3, <t>5__4 / halfDuration);
						<t>5__4 += Time.deltaTime;
						<>2__current = null;
						<>1__state = 1;
						return true;
					}
					radioLamp._lampRoot.localPosition = <endPos>5__3;
					<t>5__4 = 0f;
					break;
				}
				if (<t>5__4 < halfDuration)
				{
					radioLamp._lampRoot.localPosition = Vector3.Lerp(<endPos>5__3, <startPos>5__2, <t>5__4 / halfDuration);
					<t>5__4 += Time.deltaTime;
					<>2__current = null;
					<>1__state = 2;
					return true;
				}
				radioLamp._lampRoot.localPosition = <startPos>5__2;
				return false;
			}

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

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

		private readonly Transform _lampRoot;

		private readonly Light? _lampLight;

		private RadioLamp(Transform lampRoot, Light? lampLight)
		{
			_lampRoot = lampRoot;
			_lampLight = lampLight;
		}

		internal static RadioLamp? TryCreate(Transform radioRoot)
		{
			Transform val = radioRoot.Find("radio/lamp");
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Transform obj = val.Find("light");
			Light lampLight = ((obj != null) ? ((Component)obj).GetComponent<Light>() : null) ?? ((Component)val).GetComponentInChildren<Light>();
			return new RadioLamp(val, lampLight);
		}

		internal void SetIntensity(float intensity)
		{
			if ((Object)(object)_lampLight != (Object)null)
			{
				_lampLight.intensity = intensity;
			}
		}

		[IteratorStateMachine(typeof(<ClickPulse>d__5))]
		internal IEnumerator ClickPulse(float downDistance = 0.02f, float halfDuration = 0.1f)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <ClickPulse>d__5(0)
			{
				<>4__this = this,
				downDistance = downDistance,
				halfDuration = halfDuration
			};
		}
	}
	internal static class RadioLocalization
	{
		internal const string POWER_INDEX = "PEAKRADIO_POWER";

		internal const string TUNE_INDEX = "PEAKRADIO_TUNE";

		internal const string VOLUME_INDEX = "PEAKRADIO_VOLUME";

		internal const string NAME_KEY = "NAME_RADIO";

		internal static TranslationKey? PowerKey;

		internal static TranslationKey? TuneKey;

		internal static TranslationKey? VolumeKey;

		internal static TranslationKey? NameKey;

		internal static bool Initialized
		{
			get
			{
				if (PowerKey != (TranslationKey)null && TuneKey != (TranslationKey)null && VolumeKey != (TranslationKey)null)
				{
					return NameKey != (TranslationKey)null;
				}
				return false;
			}
		}

		internal static void Init()
		{
			//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_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: 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_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			if (Initialized)
			{
				return;
			}
			if (PowerKey == null)
			{
				PowerKey = MenuAPI.CreateLocalization("PEAKRADIO_POWER").AddLocalization("Power", (Language)0);
			}
			if (TuneKey == null)
			{
				TuneKey = MenuAPI.CreateLocalization("PEAKRADIO_TUNE").AddLocalization("Tune", (Language)0);
			}
			if (VolumeKey == null)
			{
				VolumeKey = MenuAPI.CreateLocalization("PEAKRADIO_VOLUME").AddLocalization("Volume", (Language)0);
			}
			if (NameKey == null)
			{
				NameKey = MenuAPI.CreateLocalization("NAME_RADIO").AddLocalization("Radio", (Language)0);
			}
			foreach (Language value in Enum.GetValues(typeof(Language)))
			{
				if ((int)value != 0)
				{
					PowerKey.AddLocalization("Power", value);
					TuneKey.AddLocalization("Tune", value);
					VolumeKey.AddLocalization("Volume", value);
					NameKey.AddLocalization("Radio", value);
				}
			}
			Plugin.LogInfoTS("Radio localization keys initialized.");
		}
	}
	public class RadioManager : MonoBehaviourPun
	{
		[CompilerGenerated]
		private sealed class <ReparentWithDoppler>d__32 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public AudioSource audio;

			public Transform newParent;

			public bool movePosition;

			public RadioManager <>4__this;

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

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

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

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

			private bool MoveNext()
			{
				//IL_0066: 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_009a: 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_00ab: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
				//IL_0117: Unknown result type (might be due to invalid IL or missing references)
				//IL_012c: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
				int num = <>1__state;
				RadioManager radioManager = <>4__this;
				switch (num)
				{
				default:
					return false;
				case 0:
				{
					<>1__state = -1;
					audio.dopplerLevel = 0f;
					Plugin.LogInfoTS($"[RadioManager] Reparenting audio source to {((Object)newParent).name}, movePosition={movePosition}");
					Plugin.LogInfoTS($"[RadioManager] BEFORE position: {radioManager.gameObjectAudioSource.transform.position}, localPosition: {radioManager.gameObjectAudioSource.transform.localPosition}");
					Vector3 position = radioManager.gameObjectAudioSource.transform.position;
					Quaternion rotation = radioManager.gameObjectAudioSource.transform.rotation;
					radioManager.gameObjectAudioSource.transform.SetParent(newParent, !movePosition);
					if (!movePosition)
					{
						radioManager.gameObjectAudioSource.transform.SetPositionAndRotation(position, rotation);
					}
					if (movePosition)
					{
						radioManager.gameObjectAudioSource.transform.localPosition = Vector3.zero;
					}
					Plugin.LogInfoTS($"[RadioManager] AFTER position: {radioManager.gameObjectAudioSource.transform.position}, localPosition: {radioManager.gameObjectAudioSource.transform.localPosition}");
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				case 1:
					<>1__state = -1;
					audio.dopplerLevel = 1f;
					return false;
				}
			}

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

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

		private const float radioRange = 50f;

		private const bool initialPlayingState = false;

		private const float initialVolume = 0.7f;

		private const float initialTime = 0f;

		public bool timeInitialized;

		private const float AutoDisposeWhenParkedSeconds = 10f;

		private float _parkedUnderManagerTimer;

		public RadioPlaybackInfo radioPlaybackInfo = new RadioPlaybackInfo(isPlaying: false, 0.7f);

		public GameObject gameObjectAudioSource;

		private Transform holdingPen;

		public static RadioManager Instance { get; set; }

		public Transform HoldingPen => holdingPen;

		private void Awake()
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			Plugin.LogInfoTS("[RadioManager] Awake called");
			if ((Object)(object)Instance != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
				return;
			}
			Instance = this;
			Plugin.LogInfoTS("[RadioManager] Instance set, photonView Id: " + ((MonoBehaviourPun)this).photonView.ViewID);
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			((Component)this).transform.SetParent((Transform)null, true);
			((Component)this).transform.localScale = Vector3.one;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			holdingPen = ((Component)this).transform.Find("HoldingPen") ?? new GameObject("HoldingPen").transform;
			holdingPen.SetParent(((Component)this).transform, false);
		}

		private void OnEnable()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)((Component)this).transform.parent != (Object)null)
			{
				((Component)this).transform.SetParent((Transform)null, true);
			}
			((Component)this).transform.localScale = Vector3.one;
		}

		private void Start()
		{
			Plugin.LogInfoTS("[RadioManager] Start called");
			gameObjectAudioSource = SetUpGameObjectAudioSource();
			Sanitize();
		}

		private void OnDestroy()
		{
			Plugin.LogInfoTS("[RadioManager] OnDestroy called");
		}

		private void Update()
		{
			if ((Object)(object)gameObjectAudioSource != (Object)null)
			{
				Transform transform = gameObjectAudioSource.transform;
				if ((Object)(object)transform.parent != (Object)null && transform.IsChildOf(((Component)this).transform))
				{
					_parkedUnderManagerTimer += Time.unscaledDeltaTime;
					if (_parkedUnderManagerTimer >= 10f)
					{
						Plugin.LogInfoTS($"[RadioManager] AudioSource has been parked under manager for >= {10f}s. Destroying and clearing reference.");
						Object.Destroy((Object)(object)gameObjectAudioSource);
						gameObjectAudioSource = null;
						_parkedUnderManagerTimer = 0f;
					}
				}
				else
				{
					_parkedUnderManagerTimer = 0f;
				}
			}
			else
			{
				_parkedUnderManagerTimer = 0f;
			}
		}

		private void Sanitize()
		{
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			Rigidbody[] componentsInChildren = ((Component)this).GetComponentsInChildren<Rigidbody>(true);
			foreach (Rigidbody val in componentsInChildren)
			{
				Object.Destroy((Object)(object)val);
			}
			Collider[] componentsInChildren2 = ((Component)this).GetComponentsInChildren<Collider>(true);
			foreach (Collider val2 in componentsInChildren2)
			{
				Object.Destroy((Object)(object)val2);
			}
			Component[] components = ((Component)this).GetComponents<Component>();
			foreach (Component val3 in components)
			{
				if (Object.op_Implicit((Object)(object)val3) && ((object)val3).GetType().Name == "Item")
				{
					Object.Destroy((Object)(object)val3);
				}
			}
			((Component)this).transform.SetParent((Transform)null, true);
			((Component)this).transform.localScale = Vector3.one;
		}

		private GameObject SetUpGameObjectAudioSource()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			GameObject val = new GameObject("TestAudioSource");
			AudioSource val2 = val.AddComponent<AudioSource>();
			val2.loop = true;
			val2.spatialBlend = 1f;
			val2.maxDistance = 50f;
			val2.rolloffMode = (AudioRolloffMode)1;
			val2.playOnAwake = false;
			if ((Object)(object)Plugin.SharedRadioClip == (Object)null)
			{
				Plugin.LogInfoTS("SharedRadioClip is null, cannot set up audio source.");
				return val;
			}
			AudioClip sharedRadioClip = Plugin.SharedRadioClip;
			ApplyPlaybackState(val2, sharedRadioClip);
			Plugin.LogInfoTS($"[RadioManager] TestAudioSource set up with clip '{((Object)sharedRadioClip).name}', volume={val2.volume}, time={val2.time}, isPlaying={val2.isPlaying}");
			return val;
		}

		public void initRandomTrackTime()
		{
			if (!timeInitialized)
			{
				float randomAudioTime = Plugin.GetRandomAudioTime();
				((MonoBehaviourPun)this).photonView.RPC("RPC_SyncTrackTime", (RpcTarget)3, new object[1] { randomAudioTime });
				((MonoBehaviourPun)this).photonView.RPC("RPC_SetTimeInitialized", (RpcTarget)3, Array.Empty<object>());
			}
		}

		public void RequestAudioSourceOwnership(Transform requesterTransform)
		{
			if ((Object)(object)gameObjectAudioSource == (Object)null || (Object)(object)gameObjectAudioSource.GetComponent<AudioSource>() == (Object)null)
			{
				Plugin.LogInfoTS("[RadioManager] GameObjectAudioSource is null, reinitializing.");
				gameObjectAudioSource = SetUpGameObjectAudioSource();
				timeInitialized = false;
				Sanitize();
			}
			PhotonView componentInParent = ((Component)requesterTransform).GetComponentInParent<PhotonView>();
			if ((Object)(object)componentInParent == (Object)null)
			{
				Debug.LogWarning((object)"[RadioManager] Requester has no PhotonView in its parents.");
			}
			else
			{
				RequestAudioSource(componentInParent.ViewID);
			}
		}

		private void RequestAudioSource(int requesterViewId)
		{
			PhotonView val = PhotonView.Find(requesterViewId);
			if ((Object)(object)val == (Object)null)
			{
				Debug.LogWarning((object)$"[RadioManager] Could not find requester PV for ViewID {requesterViewId}.");
				return;
			}
			Transform transform = ((Component)val).transform;
			updateAudioSource(transform);
		}

		public void ReturnAudioSourceToManager(Transform sourceTransform, bool movePosition = false)
		{
			Plugin.LogInfoTS(" testAudioSourceGO found, preparing to return to RadioManager");
			if ((Object)(object)gameObjectAudioSource.transform.parent != (Object)(object)sourceTransform)
			{
				string[] obj = new string[5] { "Skipping return: testAudioSourceGO parent is '", null, null, null, null };
				Transform parent = gameObjectAudioSource.transform.parent;
				obj[1] = ((parent != null) ? ((Object)parent).name : null) ?? "null";
				obj[2] = "', expected '";
				obj[3] = ((Object)((Component)this).transform).name;
				obj[4] = "'";
				Plugin.LogInfoTS(string.Concat(obj));
			}
			else
			{
				((MonoBehaviourPun)this).photonView.RPC("RPC_ReturnAudioSourceToManager", (RpcTarget)3, new object[1] { movePosition });
				Plugin.LogInfoTS("Returned testAudioSource to RadioManager (via helper)");
			}
		}

		[PunRPC]
		public void RPC_ReturnAudioSourceToManager(bool movePosition = false)
		{
			Plugin.LogInfoTS("RPC_ReturnAudioSourceToManager called");
			updateAudioSource(Instance.HoldingPen, movePosition);
		}

		public void ApplyPlaybackState(AudioSource target, AudioClip clip)
		{
			if ((Object)(object)target == (Object)null)
			{
				Plugin.LogInfoTS(" ApplyPlaybackState called with null target AudioSource");
				return;
			}
			if ((Object)(object)clip == (Object)null)
			{
				Plugin.LogInfoTS("ApplyPlaybackState called with null AudioClip");
				return;
			}
			RadioPlaybackInfo radioPlaybackInfo = Instance.radioPlaybackInfo;
			target.clip = clip;
			target.volume = (radioPlaybackInfo.IsPlaying ? radioPlaybackInfo.Volume : 0f);
			target.Play();
			Plugin.LogInfoTS($"ApplyPlaybackState -> time={target.time}, vol={target.volume}, isPlaying={radioPlaybackInfo.IsPlaying}");
		}

		public void TransferAudioSourceToPlayer(Character holderCharacter)
		{
			if ((Object)(object)holderCharacter == (Object)null || (Object)(object)((MonoBehaviourPun)holderCharacter).photonView == (Object)null)
			{
				Plugin.LogInfoTS("TransferAudioSourceToPlayer called with null holderCharacter or photonView");
				return;
			}
			Plugin.LogInfoTS($"[RadioManager] Transferring audio source to player {((MonoBehaviourPun)holderCharacter).photonView.ViewID}");
			((MonoBehaviourPun)this).photonView.RPC("RPC_TransferAudioSourceToPlayer", (RpcTarget)3, new object[1] { ((MonoBehaviourPun)holderCharacter).photonView.ViewID });
		}

		[PunRPC]
		public void RPC_TransferAudioSourceToPlayer(int characterViewId)
		{
			Plugin.LogInfoTS($"[RadioManager] RPC_TransferAudioSourceToPlayer called for viewId {characterViewId}");
			Character val = null;
			PhotonView val2 = PhotonView.Find(characterViewId);
			if ((Object)(object)val2 != (Object)null)
			{
				val = ((Component)val2).GetComponent<Character>() ?? ((Component)val2).GetComponentInParent<Character>();
			}
			if ((Object)(object)val == (Object)null)
			{
				Character[] source = Object.FindObjectsByType<Character>((FindObjectsSortMode)0);
				val = ((IEnumerable<Character>)source).FirstOrDefault((Func<Character, bool>)((Character c) => (Object)(object)((MonoBehaviourPun)c).photonView != (Object)null && ((MonoBehaviourPun)c).photonView.ViewID == characterViewId));
			}
			if ((Object)(object)val == (Object)null)
			{
				Plugin.LogInfoTS($"Character with PhotonView ID {characterViewId} not found for audio source transfer.");
			}
			else
			{
				updateAudioSource(((Component)val.refs.hip).transform);
			}
		}

		public void updateAudioSource(Transform transform, bool movePosition = true)
		{
			AudioSource component = gameObjectAudioSource.GetComponent<AudioSource>();
			((MonoBehaviour)this).StartCoroutine(ReparentWithDoppler(component, transform, movePosition));
		}

		[IteratorStateMachine(typeof(<ReparentWithDoppler>d__32))]
		private IEnumerator ReparentWithDoppler(AudioSource audio, Transform newParent, bool movePosition = true)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <ReparentWithDoppler>d__32(0)
			{
				<>4__this = this,
				audio = audio,
				newParent = newParent,
				movePosition = movePosition
			};
		}

		[PunRPC]
		public void RPC_SyncTrackTime(float trackTime)
		{
			Plugin.LogInfoTS($"[RadioManager] RPC_SyncTrackTime called. TrackTime: {trackTime}");
			gameObjectAudioSource.GetComponent<AudioSource>().time = trackTime;
		}

		[PunRPC]
		public void RPC_SetTimeInitialized()
		{
			Plugin.LogInfoTS("[RadioManager] RPC_SetTimeInitialized called");
			timeInitialized = true;
		}

		public void SyncIsPlaying(bool isPlaying)
		{
			((MonoBehaviourPun)this).photonView.RPC("RPC_SyncIsPlaying", (RpcTarget)3, new object[1] { isPlaying });
		}

		[PunRPC]
		public void RPC_SyncIsPlaying(bool isPlaying)
		{
			radioPlaybackInfo.IsPlaying = isPlaying;
			Plugin.LogInfoTS($"[RadioManager] SyncIsPlaying called. IsPlaying: {isPlaying}");
		}

		public void SyncHolderCharacterId(int characterId)
		{
			((MonoBehaviourPun)this).photonView.RPC("RPC_SyncHolderCharacterId", (RpcTarget)3, new object[1] { characterId });
		}

		[PunRPC]
		public void RPC_SyncHolderCharacterId(int characterId)
		{
			Plugin.LogInfoTS($"[RadioManager] SyncHolderCharacterId called. CharacterId: {characterId}");
			radioPlaybackInfo.HolderCharacterId = characterId;
		}
	}
	public struct RadioPlaybackInfo
	{
		public bool IsPlaying;

		public float Volume;

		public int? HolderCharacterId;

		public RadioPlaybackInfo(bool isPlaying, float volume)
		{
			HolderCharacterId = null;
			IsPlaying = isPlaying;
			Volume = volume;
		}
	}
	internal static class RadioSpawner
	{
		[CompilerGenerated]
		private sealed class <DelayedSpawnRadio>d__1 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public Plugin plugin;

			private float <waited>5__2;

			private Player <targetOwner>5__3;

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

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

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

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

			private bool MoveNext()
			{
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				//IL_0032: Expected O, but got Unknown
				//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
				//IL_0101: 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_0114: Unknown result type (might be due to invalid IL or missing references)
				//IL_0119: Unknown result type (might be due to invalid IL or missing references)
				//IL_011e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0120: Unknown result type (might be due to invalid IL or missing references)
				//IL_012a: Unknown result type (might be due to invalid IL or missing references)
				//IL_012f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0145: 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_0157: Unknown result type (might be due to invalid IL or missing references)
				//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(2f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					if ((Object)(object)Plugin.RadioPrefabRef == (Object)null)
					{
						Plugin.LogInfoTS("DelayedSpawnRadio: RadioPrefabRef is null; aborting spawn.");
						return false;
					}
					<waited>5__2 = 0f;
					<targetOwner>5__3 = PhotonNetwork.MasterClient;
					break;
				case 2:
					<>1__state = -1;
					<waited>5__2 += Time.unscaledDeltaTime;
					if (<waited>5__2 - Mathf.Floor(<waited>5__2) < Time.unscaledDeltaTime)
					{
						Plugin.LogInfoTS($"Waiting for master character... {<waited>5__2:F1}s");
					}
					break;
				}
				if (<waited>5__2 < 10f)
				{
					if (!PhotonNetwork.IsConnected || !PhotonNetwork.IsMasterClient)
					{
						return false;
					}
					if (FindExistingRadio())
					{
						Plugin.LogInfoTS("Radio appeared during wait; aborting auto-spawn.");
						return false;
					}
					List<Character> allCharacters = Character.AllCharacters;
					foreach (Character item in allCharacters)
					{
						try
						{
							if ((Object)(object)item == (Object)null || (Object)(object)((MonoBehaviourPun)item).photonView == (Object)null || ((MonoBehaviourPun)item).photonView.Owner != <targetOwner>5__3)
							{
								continue;
							}
							Vector2 val = Random.insideUnitCircle * 1.5f;
							Vector3 approx = item.Center + new Vector3(val.x, 0.25f, val.y);
							Quaternion rot;
							Vector3 val2 = <DelayedSpawnRadio>g__TryFindGroundedSpawn|1_0(approx, out rot);
							try
							{
								GameObject val3 = PhotonNetwork.Instantiate("0_Items/" + ((Object)Plugin.RadioPrefabRef).name, val2, rot, (byte)0, (object[])null);
								Plugin.LogInfoTS($"Spawned radio at {val2} (wait {<waited>5__2:F2}s) for master {<targetOwner>5__3.ActorNumber}");
								Item component = val3.GetComponent<Item>();
								if ((Object)(object)component != (Object)null)
								{
									try
									{
										component.SetKinematicNetworked(true, val3.transform.position, val3.transform.rotation);
										((MonoBehaviour)plugin).StartCoroutine(ReleaseKinematicNextFrame(component));
									}
									catch (Exception ex)
									{
										Plugin.LogInfoTS("SetKinematicNetworked not applied: " + ex.Message);
									}
								}
							}
							catch (Exception ex2)
							{
								Plugin.LogInfoTS("Radio spawn failed: " + ex2.Message);
							}
							return false;
						}
						catch (Exception ex3)
						{
							Plugin.LogInfoTS("Character iteration exception: " + ex3.Message);
						}
					}
					<>2__current = null;
					<>1__state = 2;
					return true;
				}
				Plugin.LogInfoTS("DelayedSpawnRadio: Timed out waiting for master character; no radio spawned.");
				return false;
			}

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

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

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

			private object <>2__current;

			public Item item;

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

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

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

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

			private bool MoveNext()
			{
				//IL_0040: Unknown result type (might be due to invalid IL or missing references)
				//IL_0050: Unknown result type (might be due to invalid IL or missing references)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = null;
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					try
					{
						item.SetKinematicNetworked(false, ((Component)item).transform.position, ((Component)item).transform.rotation);
					}
					catch
					{
					}
					return false;
				}
			}

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

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

		public static bool FindExistingRadio()
		{
			return (Object)(object)Object.FindFirstObjectByType<RadioBehavior>() != (Object)null;
		}

		[IteratorStateMachine(typeof(<DelayedSpawnRadio>d__1))]
		public static IEnumerator DelayedSpawnRadio(Plugin plugin)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <DelayedSpawnRadio>d__1(0)
			{
				plugin = plugin
			};
		}

		[IteratorStateMachine(typeof(<ReleaseKinematicNextFrame>d__2))]
		private static IEnumerator ReleaseKinematicNextFrame(Item item)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <ReleaseKinematicNextFrame>d__2(0)
			{
				item = item
			};
		}

		[CompilerGenerated]
		internal static Vector3 <DelayedSpawnRadio>g__TryFindGroundedSpawn|1_0(Vector3 approx, out Quaternion rot, int radialAttempts = 8, float radius = 3f)
		{
			//IL_000a: 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_0015: 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_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: 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_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: 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_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: 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_0098: 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_00a4: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			int num = -5;
			RaycastHit val2 = default(RaycastHit);
			for (int i = 0; i < radialAttempts; i++)
			{
				Vector3 val = approx + Vector3.up * 5f + Random.insideUnitSphere * radius;
				if (Physics.Raycast(val, Vector3.down, ref val2, 15f, num, (QueryTriggerInteraction)1))
				{
					Vector3 normal = ((RaycastHit)(ref val2)).normal;
					Vector3 val3 = Vector3.ProjectOnPlane(Random.onUnitSphere, normal);
					if (((Vector3)(ref val3)).sqrMagnitude < 0.01f)
					{
						Vector3 val4 = Vector3.Cross(normal, Vector3.right);
						val3 = ((Vector3)(ref val4)).normalized;
					}
					rot = Quaternion.LookRotation(val3, normal);
					return ((RaycastHit)(ref val2)).point + normal * 0.05f;
				}
			}
			rot = Quaternion.identity;
			return approx;
		}
	}
	public class RadioToggleController
	{
		[CompilerGenerated]
		private sealed class <FadeRadio>d__9 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public RadioToggleController <>4__this;

			public bool fadeIn;

			private float <startVolume>5__2;

			private float <targetVolume>5__3;

			private float <elapsedTime>5__4;

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

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

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

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

			private bool MoveNext()
			{
				int num = <>1__state;
				RadioToggleController radioToggleController = <>4__this;
				switch (num)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					Plugin.LogInfoTS($"{radioToggleController.logId} FadeRadio called. FadeIn: {fadeIn}, Current Volume: {radioToggleController.audioSource.volume}, Target Volume: {(fadeIn ? RadioManager.Instance.radioPlaybackInfo.Volume : 0f)}");
					radioToggleController.isFading = true;
					<startVolume>5__2 = radioToggleController.audioSource.volume;
					<targetVolume>5__3 = (fadeIn ? RadioManager.Instance.radioPlaybackInfo.Volume : 0f);
					<elapsedTime>5__4 = 0f;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if (<elapsedTime>5__4 < radioToggleController.fadeTime)
				{
					<elapsedTime>5__4 += Time.deltaTime;
					radioToggleController.audioSource.volume = Mathf.Lerp(<startVolume>5__2, <targetVolume>5__3, <elapsedTime>5__4 / radioToggleController.fadeTime);
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				radioToggleController.audioSource.volume = <targetVolume>5__3;
				radioToggleController.isFading = false;
				Plugin.LogInfoTS(radioToggleController.logId + " Radio fade " + (fadeIn ? "in" : "out") + " complete");
				return false;
			}

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

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

		private readonly AudioSource audioSource;

		private readonly MonoBehaviour radioBehavior;

		private readonly PhotonView photonView;

		private readonly string logId;

		private readonly float fadeTime;

		private bool isFading;

		public bool IsFading => isFading;

		public RadioToggleController(AudioSource audioSource, MonoBehaviour radioBehavior, PhotonView photonView, string logId, float fadeTime)
		{
			this.audioSource = audioSource;
			this.radioBehavior = radioBehavior;
			this.photonView = photonView;
			this.logId = logId;
			this.fadeTime = fadeTime;
		}

		public void ToggleRadio()
		{
			if (!PhotonNetwork.InRoom)
			{
				Plugin.LogInfoTS(logId + " ToggleRadio called but not in room, skipping RPC.");
				return;
			}
			Plugin.LogInfoTS(logId + " ToggleRadio called");
			bool flag = !RadioManager.Instance.radioPlaybackInfo.IsPlaying;
			RadioManager.Instance.initRandomTrackTime();
			RadioManager.Instance.SyncIsPlaying(flag);
			Plugin.LogInfoTS(logId + " Radio turning " + (RadioManager.Instance.radioPlaybackInfo.IsPlaying ? "ON" : "OFF"));
			Plugin.LogInfoTS($"{logId} Radio volume set to {RadioManager.Instance.radioPlaybackInfo.Volume}");
			photonView.RPC("RPC_SetRadioState", (RpcTarget)0, new object[1] { flag });
			Plugin.LogInfoTS(logId + " ToggleRadio completed");
		}

		public void SetRadioState(bool state)
		{
			Plugin.LogInfoTS($"{logId} SetRadioState called. State: {state}");
			radioBehavior.StartCoroutine(FadeRadio(state));
		}

		[IteratorStateMachine(typeof(<FadeRadio>d__9))]
		private IEnumerator FadeRadio(bool fadeIn)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <FadeRadio>d__9(0)
			{
				<>4__this = this,
				fadeIn = fadeIn
			};
		}
	}
	public class RadioTuner
	{
		[CompilerGenerated]
		private sealed class <TuneRadioCoroutine>d__9 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public RadioTuner <>4__this;

			public int noiseIdx;

			public float syncedTuneTime;

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

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

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

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

			private bool MoveNext()
			{
				//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e0: Expected O, but got Unknown
				int num = <>1__state;
				RadioTuner radioTuner = <>4__this;
				switch (num)
				{
				default:
					return false;
				case 0:
				{
					<>1__state = -1;
					radioTuner.isTuning = true;
					Plugin.LogInfoTS($"[RadioTuner] TuneRadioCoroutine started. noiseIdx={noiseIdx}, syncedTuneTime={syncedTuneTime}");
					AudioClip val = ((noiseIdx >= 0 && noiseIdx < Plugin.TuningNoiseClips.Count) ? Plugin.TuningNoiseClips[noiseIdx] : null);
					if ((Object)(object)val != (Object)null && (Object)(object)radioTuner.audioSource != (Object)null)
					{
						Plugin.LogInfoTS("[RadioTuner] Playing tuning noise clip: " + ((Object)val).name);
						radioTuner.audioSource.clip = val;
						radioTuner.audioSource.time = 0f;
						radioTuner.audioSource.Play();
						<>2__current = (object)new WaitForSeconds(val.length);
						<>1__state = 1;
						return true;
					}
					Plugin.LogInfoTS("[RadioTuner] No valid tuning noise clip found or audioSource is null.");
					break;
				}
				case 1:
					<>1__state = -1;
					break;
				}
				if ((Object)(object)Plugin.SharedRadioClip != (Object)null && (Object)(object)radioTuner.audioSource != (Object)null)
				{
					Plugin.LogInfoTS($"[RadioTuner] Switching to music clip: {((Object)Plugin.SharedRadioClip).name} at time {syncedTuneTime}");
					radioTuner.audioSource.clip = Plugin.SharedRadioClip;
					radioTuner.audioSource.time = syncedTuneTime;
					radioTuner.audioSource.Play();
				}
				else
				{
					Plugin.LogInfoTS("[RadioTuner] SharedRadioClip is null or audioSource is null.");
				}
				radioTuner.isTuning = false;
				return false;
			}

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

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

		private readonly AudioSource audioSource;

		private readonly RadioBehavior radioBehavior;

		private bool isTuning;

		public bool IsTuning => isTuning;

		public RadioTuner(AudioSource audioSource, RadioBehavior radioBehavior)
		{
			this.audioSource = audioSource;
			this.radioBehavior = radioBehavior;
			PhotonView component = ((Component)radioBehavior).GetComponent<PhotonView>();
			Plugin.LogInfoTS($"[RadioTuner] Constructed for RadioBehavior PV:{((component != null) ? new int?(component.ViewID) : null)}");
		}

		public void TuneRadio()
		{
			if (isTuning || !PhotonNetwork.InRoom)
			{
				return;
			}
			Plugin.LogInfoTS($"[RadioTuner] TuneRadio called. AudioSource null? {(Object)(object)audioSource == (Object)null}");
			if (!((Object)(object)audioSource == (Object)null))
			{
				PhotonView photonView = ((MonoBehaviourPun)radioBehavior).photonView;
				Plugin.LogInfoTS($"[RadioTuner] TuneRadio: PV.IsMine={photonView.IsMine}, PV.ViewID={photonView.ViewID}");
				if (photonView.IsMine)
				{
					BroadcastRandomTune(photonView, "Owner");
					return;
				}
				Plugin.LogInfoTS($"[RadioTuner] Non-owner: Requesting tune from owner PV:{photonView.Owner}");
				photonView.RPC("RPC_RequestTune", photonView.Owner, new object[1] { photonView.ViewID });
			}
		}

		public void RequestTune(int viewID)
		{
			if (PhotonNetwork.InRoom)
			{
				Plugin.LogInfoTS($"[RadioTuner] RPC_RequestTune called. viewID={viewID}");
				PhotonView component = ((Component)radioBehavior).GetComponent<PhotonView>();
				if (!component.IsMine)
				{
					Plugin.LogInfoTS("[RadioTuner] RPC_RequestTune: Not owner, ignoring.");
				}
				else
				{
					BroadcastRandomTune(component, "Owner responding");
				}
			}
		}

		public void SyncTune(int noiseIdx, float syncedTuneTime)
		{
			Plugin.LogInfoTS($"[RadioTuner] RPC_SyncTune called. noiseIdx={noiseIdx}, syncedTuneTime={syncedTuneTime}");
			((MonoBehaviour)radioBehavior).StartCoroutine(TuneRadioCoroutine(noiseIdx, syncedTuneTime));
		}

		[IteratorStateMachine(typeof(<TuneRadioCoroutine>d__9))]
		private IEnumerator TuneRadioCoroutine(int noiseIdx, float syncedTuneTime)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <TuneRadioCoroutine>d__9(0)
			{
				<>4__this = this,
				noiseIdx = noiseIdx,
				syncedTuneTime = syncedTuneTime
			};
		}

		private void BroadcastRandomTune(PhotonView pv, string context)
		{
			int randomTuningNoiseClip = Plugin.GetRandomTuningNoiseClip();
			float randomAudioTime = Plugin.GetRandomAudioTime();
			Plugin.LogInfoTS($"[RadioTuner] {context}: Broadcasting noiseIdx={randomTuningNoiseClip}, randomTime={randomAudioTime}");
			pv.RPC("RPC_SyncTune", (RpcTarget)0, new object[2] { randomTuningNoiseClip, randomAudioTime });
		}
	}
}
namespace System.Diagnostics.CodeAnalysis
{
	[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ConstantExpectedAttribute : Attribute
	{
		public object? Min { get; set; }

		public object? Max { get; set; }
	}
	[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ExperimentalAttribute : Attribute
	{
		public string DiagnosticId { get; }

		public string? UrlFormat { get; set; }

		public ExperimentalAttribute(string diagnosticId)
		{
			DiagnosticId = diagnosticId;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
	[ExcludeFromCodeCoverage]
	internal sealed class MemberNotNullAttribute : Attribute
	{
		public string[] Members { get; }

		public MemberNotNullAttribute(string member)
		{
			Members = new string[1] { member };
		}

		public MemberNotNullAttribute(params string[] members)
		{
			Members = members;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
	[ExcludeFromCodeCoverage]
	internal sealed class MemberNotNullWhenAttribute : Attribute
	{
		public bool ReturnValue { get; }

		public string[] Members { get; }

		public MemberNotNullWhenAttribute(bool returnValue, string member)
		{
			ReturnValue = returnValue;
			Members = new string[1] { member };
		}

		public MemberNotNullWhenAttribute(bool returnValue, params string[] members)
		{
			ReturnValue = returnValue;
			Members = members;
		}
	}
	[AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class SetsRequiredMembersAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class StringSyntaxAttribute : Attribute
	{
		public const string CompositeFormat = "CompositeFormat";

		public const string DateOnlyFormat = "DateOnlyFormat";

		public const string DateTimeFormat = "DateTimeFormat";

		public const string EnumFormat = "EnumFormat";

		public const string GuidFormat = "GuidFormat";

		public const string Json = "Json";

		public const string NumericFormat = "NumericFormat";

		public const string Regex = "Regex";

		public const string TimeOnlyFormat = "TimeOnlyFormat";

		public const string TimeSpanFormat = "TimeSpanFormat";

		public const string Uri = "Uri";

		public const string Xml = "Xml";

		public string Syntax { get; }

		public object?[] Arguments { get; }

		public StringSyntaxAttribute(string syntax)
		{
			Syntax = syntax;
			Arguments = new object[0];
		}

		public StringSyntaxAttribute(string syntax, params object?[] arguments)
		{
			Syntax = syntax;
			Arguments = arguments;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class UnscopedRefAttribute : Attribute
	{
	}
}
namespace System.Runtime.Versioning
{
	[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class RequiresPreviewFeaturesAttribute : Attribute
	{
		public string? Message { get; }

		public string? Url { get; set; }

		public RequiresPreviewFeaturesAttribute()
		{
		}

		public RequiresPreviewFeaturesAttribute(string? message)
		{
			Message = message;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
	[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class CallerArgumentExpressionAttribute : Attribute
	{
		public string ParameterName { get; }

		public CallerArgumentExpressionAttribute(string parameterName)
		{
			ParameterName = parameterName;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class CollectionBuilderAttribute : Attribute
	{
		public Type BuilderType { get; }

		public string MethodName { get; }

		public CollectionBuilderAttribute(Type builderType, string methodName)
		{
			BuilderType = builderType;
			MethodName = methodName;
		}
	}
	[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class CompilerFeatureRequiredAttribute : Attribute
	{
		public const string RefStructs = "RefStructs";

		public const string RequiredMembers = "RequiredMembers";

		public string FeatureName { get; }

		public bool IsOptional { get; set; }

		public CompilerFeatureRequiredAttribute(string featureName)
		{
			FeatureName = featureName;
		}
	}
	[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class InterpolatedStringHandlerArgumentAttribute : Attribute
	{
		public string[] Arguments { get; }

		public InterpolatedStringHandlerArgumentAttribute(string argument)
		{
			Arguments = new string[1] { argument };
		}

		public InterpolatedStringHandlerArgumentAttribute(params string[] arguments)
		{
			Arguments = arguments;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class InterpolatedStringHandlerAttribute : Attribute
	{
	}
	[EditorBrowsable(EditorBrowsableState.Never)]
	[ExcludeFromCodeCoverage]
	internal static class IsExternalInit
	{
	}
	[AttributeUsage(AttributeTargets.Method, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ModuleInitializerAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class OverloadResolutionPriorityAttribute : Attribute
	{
		public int Priority { get; }

		public OverloadResolutionPriorityAttribute(int priority)
		{
			Priority = priority;
		}
	}
	[AttributeUsage(AttributeTargets.Parameter, Inherited = true, AllowMultiple = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ParamCollectionAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class RequiredMemberAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
	[EditorBrowsable(EditorBrowsableState.Never)]
	[ExcludeFromCodeCoverage]
	internal sealed class RequiresLocationAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event | AttributeTargets.Interface, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class SkipLocalsInitAttribute : Attribute
	{
	}
}