Decompiled source of JBLSpeakerMod v2.0.0

JBLSpeaker.dll

Decompiled 2 days ago
using 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+360844c77f11bf9350844c36f177991ab19af7e4")]
[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 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))
			{
				SkipTrack();
			}
			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();
			}
		}

		private void OnDrop()
		{
			SetMusicVolume(droppedVolume);
			StopParticles();
		}

		private void SkipTrack()
		{
			if (!isActive || !HasAuthority())
			{
				return;
			}
			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)
				{
					SkipTrack();
				}
			}
		}

		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 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);
		}
	}
}