Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of JBLSpeakerMod v2.0.1
JBLSpeaker.dll
Decompiled 3 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using JBLSpeaker.Valuables; using Microsoft.CodeAnalysis; using Photon.Pun; using REPOLib; using REPOLib.Modules; using UnityEngine; using UnityEngine.Events; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("")] [assembly: AssemblyCompany("Brian Hepp")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+9ac551fb13dd04021120ed82d5d6d242729081fa")] [assembly: AssemblyProduct("JBLSpeaker")] [assembly: AssemblyTitle("JBLSpeaker")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] 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; } } } namespace JBLSpeaker { [BepInPlugin("drb.jblspeaker", "JBLSpeaker", "1.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugins : BaseUnityPlugin { private void Awake() { ((BaseUnityPlugin)this).Logger.LogInfo((object)"JBLSpeaker Plugin Awake"); string directoryName = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location); string text = Path.Combine(directoryName, "jblspeaker.bundle"); ((BaseUnityPlugin)this).Logger.LogInfo((object)("BundlePath = " + text.ToString())); BundleLoader.LoadBundle(text, (Action<AssetBundle>)delegate(AssetBundle assetBundle) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"BundleLoader callback fired"); if ((Object)(object)assetBundle == (Object)null) { ((BaseUnityPlugin)this).Logger.LogError((object)"AssetBundle is NULL"); } else { GameObject val = assetBundle.LoadAsset<GameObject>("jblspeaker"); if ((Object)(object)val == (Object)null) { ((BaseUnityPlugin)this).Logger.LogError((object)"JBLSpeaker prefab NOT found in bundle"); } else { ((BaseUnityPlugin)this).Logger.LogInfo((object)("Prefab found: " + ((Object)val).name)); JBLSpeaker.Valuables.JBLSpeaker jBLSpeaker = default(JBLSpeaker.Valuables.JBLSpeaker); if (!val.TryGetComponent<JBLSpeaker.Valuables.JBLSpeaker>(ref jBLSpeaker)) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"JBLSpeaker component NOT found on prefab — adding"); jBLSpeaker = val.AddComponent<JBLSpeaker.Valuables.JBLSpeaker>(); jBLSpeaker.tracks = new List<AudioSource>(val.GetComponentsInChildren<AudioSource>(true)); jBLSpeaker.particles = new List<ParticleSystem>(val.GetComponentsInChildren<ParticleSystem>(true)); } else { ((BaseUnityPlugin)this).Logger.LogInfo((object)"JBLSpeaker component already exists on prefab"); } ((BaseUnityPlugin)this).Logger.LogInfo((object)"Registering JBLSpeaker valuable"); Valuables.RegisterValuable(val); } } }, false); } } } namespace JBLSpeaker.Valuables { public class JBLSpeaker : MonoBehaviourPun { private enum State { Idle, Active } private PhysGrabObject grab; private bool wasGrabbed; public List<AudioSource> tracks; [Header("Audio")] public List<ParticleSystem> particles; private int musicIndex = -1; [Header("Behavior")] public float slamVelocityThreshold = 6f; public int maxSkipsBeforeOff = 6; private int skipCount; private bool isActive; [Header("Drop Audio")] public float droppedVolume = 0.5f; public float heldVolume = 0.8f; [SerializeField] private AudioSource connectedSource; [SerializeField] private AudioSource skipSource; [SerializeField] private List<AudioSource> musicTracks; private Dictionary<AudioSource, string[]> lyricLines; private AudioSource currentMusic; private State currentState; private float coolDownUntilNextSentence = 3f; private string playerName = "{playerName}"; private PhysGrabObject physGrabObject; private bool hasStartedMusic; private void Awake() { grab = ((Component)this).GetComponent<PhysGrabObject>(); particles = new List<ParticleSystem>(((Component)this).GetComponentsInChildren<ParticleSystem>(true)); AudioSource[] componentsInChildren = ((Component)this).GetComponentsInChildren<AudioSource>(true); AudioSource[] array = componentsInChildren; foreach (AudioSource val in array) { if (((Object)((Component)val).gameObject).name == "ConnectedSource") { connectedSource = val; } else if (((Object)((Component)val).gameObject).name == "SkipSource") { skipSource = val; } else if (((Object)((Component)val).gameObject).name.StartsWith("Music")) { musicTracks.Add(val); } } if (musicTracks.Count == 0) { Debug.LogError((object)"JBLSpeaker: musicTracks is empty!"); } if (!Object.op_Implicit((Object)(object)skipSource)) { Debug.LogError((object)"JBLSpeaker: SkipSource not assigned"); } } private void Start() { physGrabObject = ((Component)this).GetComponent<PhysGrabObject>(); GenerateLyrics(); } private void Update() { if (!Object.op_Implicit((Object)(object)grab)) { return; } if (grab.grabbed && !wasGrabbed) { OnPickup(); } if (!grab.grabbed && wasGrabbed) { OnDrop(); } wasGrabbed = grab.grabbed; if (grab.grabbedLocal && Input.GetKeyDown((KeyCode)101)) { RequestSkip(); } foreach (AudioSource musicTrack in musicTracks) { if (musicTrack.isPlaying) { ApplyHeadBob(musicTrack); break; } } if (grab.grabbed && Object.op_Implicit((Object)(object)currentMusic) && currentMusic.isPlaying && SemiFunc.IsMultiplayer()) { switch (currentState) { case State.Idle: StateIdle(); break; case State.Active: StateActive(); break; } } } private void OnPickup() { isActive = true; skipCount = 0; RestoreMusicVolume(); if (!IsAnyMusicPlaying() && Object.op_Implicit((Object)(object)connectedSource) && Object.op_Implicit((Object)(object)connectedSource.clip)) { musicIndex = -1; connectedSource.Play(); } if (hasStartedMusic || musicTracks.Count <= 0) { return; } hasStartedMusic = true; if (SemiFunc.IsMultiplayer()) { if (HasAuthority()) { ((MonoBehaviourPun)this).photonView.RPC("RPC_PlayTrackIndex", (RpcTarget)0, new object[1] { 0 }); } } else { PlayTrackByIndex(0); } } private void OnDrop() { SetMusicVolume(droppedVolume); StopParticles(); } private void PerformSkipAuthoritative() { skipCount++; if (skipCount >= maxSkipsBeforeOff) { PowerOff(); return; } int nextTrackIndex = GetNextTrackIndex(); if (SemiFunc.IsMultiplayer()) { ((MonoBehaviourPun)this).photonView.RPC("RPC_PlayTrackIndex", (RpcTarget)0, new object[1] { nextTrackIndex }); } else { PlayTrackByIndex(nextTrackIndex); } } private void PlayCurrentMusic() { if (!isActive || musicTracks.Count == 0) { return; } currentMusic = musicTracks[musicIndex]; currentMusic.volume = (grab.grabbed ? heldVolume : droppedVolume); currentMusic.Play(); foreach (ParticleSystem particle in particles) { particle.Play(); } } private void PowerOff() { isActive = false; StopMusicOnly(); StopParticles(clear: true); } private void StopMusicOnly() { foreach (AudioSource musicTrack in musicTracks) { musicTrack.Stop(); } } private void StopParticles(bool clear = false) { foreach (ParticleSystem particle in particles) { if (clear) { particle.Stop(true, (ParticleSystemStopBehavior)0); } else { particle.Stop(true, (ParticleSystemStopBehavior)1); } } } private void OnCollisionEnter(Collision collision) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)grab) && grab.grabbed) { Vector3 relativeVelocity = collision.relativeVelocity; if (((Vector3)(ref relativeVelocity)).magnitude >= slamVelocityThreshold && HasAuthority()) { PerformSkipAuthoritative(); } } } private void ApplyHeadBob(AudioSource src) { if (!Object.op_Implicit((Object)(object)src) || !src.isPlaying || !physGrabObject.grabbed) { return; } float num = 0f; string name = ((Object)src).name; if (1 == 0) { } float num2 = name switch { "Music_01" => 104f, "Music_02" => 93f, "Music_03" => 128f, "Music_04" => 140f, _ => 0f, }; if (1 == 0) { } num = num2; float num3; if (num <= 0f) { num3 = Mathf.Sin(Time.time * 15f) * 25f; } else { float num4 = num / 60f; float num5 = Mathf.Sin(Time.time * MathF.PI * 2f * num4); num3 = num5 * 25f; } foreach (PhysGrabber item in physGrabObject.playerGrabbing) { if (!((Object)(object)item == (Object)null)) { if (item.isLocal) { item.playerAvatar.playerExpression.OverrideExpressionSet(4, 100f); PlayerExpressionsUI.instance.playerExpression.OverrideExpressionSet(4, 100f); PlayerExpressionsUI.instance.playerAvatarVisuals.HeadTiltOverride(num3 * 0.5f); } else { item.playerAvatar.playerAvatarVisuals.HeadTiltOverride(num3); } } } } private bool IsAnyMusicPlaying() { foreach (AudioSource musicTrack in musicTracks) { if (Object.op_Implicit((Object)(object)musicTrack) && musicTrack.isPlaying) { return true; } } return false; } private void SetMusicVolume(float volume) { foreach (AudioSource musicTrack in musicTracks) { if (Object.op_Implicit((Object)(object)musicTrack) && musicTrack.isPlaying) { musicTrack.volume = volume; } } } private void RestoreMusicVolume() { SetMusicVolume(heldVolume); } private void GenerateLyrics() { Debug.Log((object)"JBLSpeaker: Generate Lyrics"); lyricLines = new Dictionary<AudioSource, string[]>(); foreach (AudioSource musicTrack in musicTracks) { if (((Object)musicTrack).name.Contains("Music_01")) { lyricLines[musicTrack] = new string[5] { "I got a glock in my rari", "I'm like, yeah, she's fine", "Wonder when {playerName} will be mine", "17 shots, no 38", "Seventeen Thirty Eight" }; } else if (((Object)musicTrack).name.Contains("Music_02")) { lyricLines[musicTrack] = new string[5] { "I want you to be mine again baby", "I know my lifestyle is driving you crazy", "Married to the money I aint never letting go", "I go out of the way to see you", "{playerName} I hope you know I need you" }; } else if (((Object)musicTrack).name.Contains("Music_03")) { lyricLines[musicTrack] = new string[5] { "{playerName} won't you come my way", "Got something I want to say", "Watch me pull out all this dough", "Cannot keep you out my brain", "Flexin on your ex I know" }; } else if (((Object)musicTrack).name.Contains("Music_04")) { lyricLines[musicTrack] = new string[5] { "She's my trap queen, let her hit the bando", "I'm like hey, what's up? Hello", "Seventeen Thirty Eight ayy", "And I can ride with my baby", "{playerName} can hit it from behind" }; } else { lyricLines[musicTrack] = new string[5] { "This song slaps", "Certified banger", "Straight fire", "Seventeen Thirty Eight", "{playerName} is the best" }; } } } private void StateIdle() { //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) if (coolDownUntilNextSentence > 0f && physGrabObject.grabbed) { coolDownUntilNextSentence -= Time.deltaTime; } else { if (!Object.op_Implicit((Object)(object)PhysGrabber.instance) || !PhysGrabber.instance.grabbed || !Object.op_Implicit((Object)(object)PhysGrabber.instance.grabbedPhysGrabObject) || !((Object)(object)PhysGrabber.instance.grabbedPhysGrabObject == (Object)(object)physGrabObject)) { return; } bool flag = false; if (!SemiFunc.IsMultiplayer()) { playerName = "JBL Speaker"; flag = true; } else { List<PlayerAvatar> list = SemiFunc.PlayerGetAllPlayerAvatarWithinRange(10f, ((Component)PhysGrabber.instance).transform.position, false, default(LayerMask)); PlayerAvatar val = null; float num = float.MaxValue; foreach (PlayerAvatar item in list) { if (!((Object)(object)item == (Object)(object)PlayerAvatar.instance)) { float num2 = Vector3.Distance(((Component)PhysGrabber.instance).transform.position, ((Component)item).transform.position); if (num2 < num) { num = num2; val = item; } } } flag = true; if ((Object)(object)val != (Object)null) { playerName = val.playerName; } else { playerName = "JBL Speaker"; } } if (flag) { string text = TrySpeakLyricForCurrentTrack(); if (text != null) { currentState = State.Active; Color val2 = default(Color); ((Color)(ref val2))..ctor(1f, 0.3f, 0.6f, 1f); ChatManager.instance.PossessChatScheduleStart(10); ChatManager.instance.PossessChat((PossessChatID)1, text, 1f, val2, 0f, false, 0, (UnityEvent)null); ChatManager.instance.PossessChatScheduleEnd(); } } } } private void StateActive() { if (PhysGrabber.instance.grabbed && Object.op_Implicit((Object)(object)PhysGrabber.instance.grabbedPhysGrabObject) && (Object)(object)PhysGrabber.instance.grabbedPhysGrabObject != (Object)(object)physGrabObject) { currentState = State.Idle; coolDownUntilNextSentence = Random.Range(15f, 30f); } else if (!ChatManager.instance.StateIsPossessed()) { currentState = State.Idle; coolDownUntilNextSentence = Random.Range(15f, 30f); } } private string TrySpeakLyricForCurrentTrack() { if (!Object.op_Implicit((Object)(object)currentMusic) || !currentMusic.isPlaying) { return null; } if (!lyricLines.ContainsKey(currentMusic)) { return null; } string[] array = lyricLines[currentMusic]; if (array.Length == 0) { return null; } string text = array[Random.Range(0, array.Length)]; return text.Replace("{playerName}", playerName); } private void PlayTrackByIndex(int index) { if (index < 0 || index >= musicTracks.Count) { return; } StopMusicOnly(); musicIndex = index; currentMusic = musicTracks[musicIndex]; currentMusic.volume = (grab.grabbed ? heldVolume : droppedVolume); currentMusic.Play(); foreach (ParticleSystem particle in particles) { particle.Play(); } } private int GetNextTrackIndex() { if (musicTracks == null || musicTracks.Count == 0) { return -1; } int num = musicIndex + 1; if (num >= musicTracks.Count) { num = 0; } return num; } private void PlaySkipSound() { if (Object.op_Implicit((Object)(object)skipSource) && Object.op_Implicit((Object)(object)skipSource.clip)) { skipSource.Play(); } } private void RequestSkip() { if (isActive) { PlaySkipSound(); if (SemiFunc.IsMultiplayer()) { ((MonoBehaviourPun)this).photonView.RPC("RPC_RequestSkip", (RpcTarget)2, Array.Empty<object>()); } else { PerformSkipAuthoritative(); } } } private bool HasAuthority() { if (!SemiFunc.IsMultiplayer()) { return true; } if (!Object.op_Implicit((Object)(object)((MonoBehaviourPun)this).photonView)) { return false; } return ((MonoBehaviourPun)this).photonView.IsMine || PhotonNetwork.IsMasterClient; } [PunRPC] private void RPC_PlayTrackIndex(int index) { PlayTrackByIndex(index); } [PunRPC] private void RPC_RequestSkip() { if (PhotonNetwork.IsMasterClient) { PerformSkipAuthoritative(); } } } }