The BepInEx console will not appear when launching like it does for other games on Thunderstore (you can turn it back on in your BepInEx.cfg file). If your PEAK crashes on startup, add -dx12 to your launch parameters.
Decompiled source of PeakRadio v1.0.0
peakradiomod.peakradiomod.dll
Decompiled 2 weeks agousing 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 { } }