Decompiled source of CustomBoombox v1.0.3

BeplnEx/plugins/customboombox/CustomBoombox.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using FMOD;
using FMODUnity;
using Mirror;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("CustomBoombox")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("CustomBoombox")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("cf8bd6d7-5d01-4cb9-82c0-f839260bd127")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
[BepInPlugin("eva.customboombox.display", "Boombox Display", "2.4.1")]
public class BoomboxDisplay : BaseUnityPlugin
{
	private CustomBoombox boomboxPlugin;

	private BoomboxMusic musicPlugin;

	private FieldInfo boomboxField;

	private FieldInfo volumeField;

	private FieldInfo pausedField;

	private FieldInfo hasChannelField;

	private GameObject currentBoombox;

	private GameObject displayObject;

	private GameObject equalizerObject;

	private GameObject frameObject;

	private Transform borderTransform;

	private Transform backgroundTransform;

	private TextMesh volumeText;

	private readonly Transform[] bars = (Transform[])(object)new Transform[13];

	private readonly float[] barHeights = new float[13];

	private Material panelMaterial;

	private Material borderMaterial;

	private Material[] barMaterials;

	private Vector3 displayPosition = new Vector3(0.01f, 0.32f, -0.58f);

	private float displayScale = 0.7499999f;

	private bool flipped = true;

	private Vector3 equalizerPosition = new Vector3(-0.01f, -0.07f, -0.02f);

	private float equalizerScale = 2.049999f;

	private float barWidth = 0.011f;

	private float barSpacing = 0.013f;

	private float barHeightMultiplier = 2.2f;

	private Vector3 framePosition = new Vector3(-0.02f, -0.01f, 0f);

	private float frameWidth = 0.4450001f;

	private float frameHeight = 0.1789595f;

	private float frameThickness = 0.009499999f;

	private const float BarMinHeight = 0.004f;

	private const float BarMaxHeight = 0.022f;

	private float animationTime = 0f;

	private void Awake()
	{
		BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.NonPublic;
		boomboxField = typeof(CustomBoombox).GetField("activeBoombox", bindingAttr);
		volumeField = typeof(BoomboxMusic).GetField("volume", bindingAttr);
		pausedField = typeof(BoomboxMusic).GetField("isPaused", bindingAttr);
		hasChannelField = typeof(BoomboxMusic).GetField("hasChannel", bindingAttr);
		CreateMaterials();
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Boombox Display 2.4.1 запущен!");
	}

	private void CreateMaterials()
	{
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Expected O, but got Unknown
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Expected O, but got Unknown
		//IL_009d: 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_00c2: Expected O, but got Unknown
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f7: Expected O, but got Unknown
		//IL_0113: Unknown result type (might be due to invalid IL or missing references)
		//IL_0126: Unknown result type (might be due to invalid IL or missing references)
		//IL_012c: Expected O, but got Unknown
		//IL_0148: Unknown result type (might be due to invalid IL or missing references)
		Shader val = Shader.Find("Unlit/Color");
		if ((Object)(object)val == (Object)null)
		{
			val = Shader.Find("Sprites/Default");
		}
		if ((Object)(object)val == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"Не найден шейдер дисплея.");
			return;
		}
		panelMaterial = new Material(val);
		panelMaterial.color = new Color(0.075f, 0.035f, 0.15f, 1f);
		borderMaterial = new Material(val);
		borderMaterial.color = new Color(0.95f, 0.38f, 0.78f, 1f);
		barMaterials = (Material[])(object)new Material[3];
		barMaterials[0] = new Material(val);
		barMaterials[0].color = new Color(1f, 0.94f, 1f, 1f);
		barMaterials[1] = new Material(val);
		barMaterials[1].color = new Color(0.94f, 0.38f, 0.78f, 1f);
		barMaterials[2] = new Material(val);
		barMaterials[2].color = new Color(0.55f, 0.35f, 0.95f, 1f);
	}

	private void Update()
	{
		FindBoombox();
		if (!((Object)(object)currentBoombox == (Object)null))
		{
			if ((Object)(object)displayObject == (Object)null)
			{
				CreateDisplay();
			}
			UpdateVolumeText();
			UpdateEqualizer();
		}
	}

	private void FindBoombox()
	{
		if ((Object)(object)boomboxPlugin == (Object)null)
		{
			boomboxPlugin = Object.FindFirstObjectByType<CustomBoombox>();
		}
		if ((Object)(object)musicPlugin == (Object)null)
		{
			musicPlugin = Object.FindFirstObjectByType<BoomboxMusic>();
		}
		if ((Object)(object)boomboxPlugin == (Object)null || boomboxField == null)
		{
			return;
		}
		object? value = boomboxField.GetValue(boomboxPlugin);
		GameObject val = (GameObject)((value is GameObject) ? value : null);
		if (!((Object)(object)val == (Object)(object)currentBoombox))
		{
			DestroyDisplay();
			currentBoombox = val;
			if ((Object)(object)currentBoombox != (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Дисплей подключён к бумбоксу!");
			}
		}
	}

	private void CreateDisplay()
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Expected O, but got Unknown
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0105: Unknown result type (might be due to invalid IL or missing references)
		//IL_010f: Expected O, but got Unknown
		displayObject = new GameObject("Boombox Digital Display");
		displayObject.transform.SetParent(currentBoombox.transform, false);
		frameObject = new GameObject("Adjustable Display Frame");
		frameObject.transform.SetParent(displayObject.transform, false);
		GameObject val = CreateRectangle("Pink Border", frameObject.transform, Vector3.zero, frameWidth, frameHeight, borderMaterial);
		borderTransform = val.transform;
		GameObject val2 = CreateRectangle("Dark Screen", frameObject.transform, new Vector3(0f, 0f, -0.0005f), frameWidth - frameThickness * 2f, frameHeight - frameThickness * 2f, panelMaterial);
		backgroundTransform = val2.transform;
		CreateVolumeText();
		equalizerObject = new GameObject("Adjustable Equalizer");
		equalizerObject.transform.SetParent(displayObject.transform, false);
		CreateEqualizer();
		ApplyDisplayTransform();
		ApplyEqualizerTransform();
		ApplyFrameTransform();
	}

	private GameObject CreateRectangle(string objectName, Transform parent, Vector3 position, float width, float height, Material material)
	{
		//IL_0024: 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_004b: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = GameObject.CreatePrimitive((PrimitiveType)5);
		((Object)val).name = objectName;
		val.transform.SetParent(parent, false);
		val.transform.localPosition = position;
		val.transform.localRotation = Quaternion.identity;
		val.transform.localScale = new Vector3(width, height, 1f);
		Collider component = val.GetComponent<Collider>();
		if ((Object)(object)component != (Object)null)
		{
			Object.Destroy((Object)(object)component);
		}
		MeshRenderer component2 = val.GetComponent<MeshRenderer>();
		if ((Object)(object)component2 != (Object)null)
		{
			((Renderer)component2).sharedMaterial = material;
			((Renderer)component2).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)component2).receiveShadows = false;
		}
		return val;
	}

	private void CreateVolumeText()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("Volume Text");
		val.transform.SetParent(displayObject.transform, false);
		val.transform.localPosition = new Vector3(0f, 0.012f, -0.0015f);
		volumeText = val.AddComponent<TextMesh>();
		volumeText.text = "VOL70%";
		volumeText.anchor = (TextAnchor)4;
		volumeText.alignment = (TextAlignment)1;
		volumeText.fontSize = 64;
		volumeText.characterSize = 0.01f;
		volumeText.color = new Color(1f, 0.76f, 0.94f, 1f);
		Font builtinResource = Resources.GetBuiltinResource<Font>("Arial.ttf");
		if ((Object)(object)builtinResource != (Object)null)
		{
			volumeText.font = builtinResource;
			MeshRenderer component = val.GetComponent<MeshRenderer>();
			if ((Object)(object)component != (Object)null)
			{
				((Renderer)component).sharedMaterial = builtinResource.material;
				((Renderer)component).shadowCastingMode = (ShadowCastingMode)0;
			}
		}
	}

	private void CreateEqualizer()
	{
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)equalizerObject == (Object)null) && barMaterials != null)
		{
			for (int i = 0; i < bars.Length; i++)
			{
				GameObject val = CreateRectangle("Equalizer Bar " + i, equalizerObject.transform, Vector3.zero, barWidth, 0.004f, barMaterials[i % 3]);
				bars[i] = val.transform;
				barHeights[i] = 0.004f;
				SetBarHeight(i, 0.004f);
			}
		}
	}

	private void SetBarHeight(int index, float height)
	{
		//IL_0058: 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)
		if (!((Object)(object)bars[index] == (Object)null))
		{
			float num = ((float)index - (float)(bars.Length - 1) / 2f) * barSpacing;
			float num2 = height * barHeightMultiplier;
			float num3 = -0.011f;
			bars[index].localPosition = new Vector3(num, num3 + num2 / 2f, 0f);
			bars[index].localScale = new Vector3(barWidth, num2, 1f);
		}
	}

	private void UpdateVolumeText()
	{
		if ((Object)(object)volumeText == (Object)null || (Object)(object)musicPlugin == (Object)null || volumeField == null || pausedField == null)
		{
			return;
		}
		try
		{
			float num = (float)volumeField.GetValue(musicPlugin);
			if ((bool)pausedField.GetValue(musicPlugin))
			{
				volumeText.text = "PAUSE";
				return;
			}
			int num2 = Mathf.RoundToInt(num * 100f);
			volumeText.text = "VOL" + num2 + "%";
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("Ошибка дисплея: " + ex.Message));
		}
	}

	private bool IsMusicPlaying()
	{
		if ((Object)(object)musicPlugin == (Object)null || hasChannelField == null || pausedField == null)
		{
			return false;
		}
		try
		{
			bool flag = (bool)hasChannelField.GetValue(musicPlugin);
			bool flag2 = (bool)pausedField.GetValue(musicPlugin);
			return flag && !flag2;
		}
		catch
		{
			return false;
		}
	}

	private void UpdateEqualizer()
	{
		bool flag = IsMusicPlaying();
		if (flag)
		{
			animationTime += Time.deltaTime;
		}
		for (int i = 0; i < bars.Length; i++)
		{
			if (!((Object)(object)bars[i] == (Object)null))
			{
				float num4;
				if (flag)
				{
					float num = Mathf.Sin(animationTime * 12f + (float)i * 1.37f);
					float num2 = Mathf.Sin(animationTime * 7f - (float)i * 0.83f);
					float num3 = Mathf.Abs(num * 0.65f + num2 * 0.35f);
					num4 = Mathf.Lerp(0.004f, 0.022f, num3);
				}
				else
				{
					num4 = 0.004f;
				}
				barHeights[i] = Mathf.Lerp(barHeights[i], num4, Mathf.Clamp01(Time.deltaTime * 12f));
				SetBarHeight(i, barHeights[i]);
			}
		}
	}

	private void ApplyDisplayTransform()
	{
		//IL_0020: 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_006a: 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)
		if (!((Object)(object)displayObject == (Object)null))
		{
			displayObject.transform.localPosition = displayPosition;
			displayObject.transform.localRotation = Quaternion.Euler(0f, flipped ? 0f : 180f, 0f);
			displayObject.transform.localScale = Vector3.one * displayScale;
		}
	}

	private void ApplyEqualizerTransform()
	{
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)equalizerObject == (Object)null)
		{
			return;
		}
		equalizerObject.transform.localPosition = equalizerPosition;
		equalizerObject.transform.localRotation = Quaternion.identity;
		equalizerObject.transform.localScale = Vector3.one * equalizerScale;
		for (int i = 0; i < bars.Length; i++)
		{
			if ((Object)(object)bars[i] != (Object)null)
			{
				SetBarHeight(i, barHeights[i]);
			}
		}
	}

	private void ApplyFrameTransform()
	{
		//IL_0042: 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_00b8: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)frameObject == (Object)null) && !((Object)(object)borderTransform == (Object)null) && !((Object)(object)backgroundTransform == (Object)null))
		{
			frameObject.transform.localPosition = framePosition;
			borderTransform.localScale = new Vector3(frameWidth, frameHeight, 1f);
			float num = Mathf.Max(0.001f, frameWidth - frameThickness * 2f);
			float num2 = Mathf.Max(0.001f, frameHeight - frameThickness * 2f);
			backgroundTransform.localScale = new Vector3(num, num2, 1f);
		}
	}

	private void DestroyDisplay()
	{
		if ((Object)(object)displayObject != (Object)null)
		{
			Object.Destroy((Object)(object)displayObject);
		}
		displayObject = null;
		equalizerObject = null;
		frameObject = null;
		borderTransform = null;
		backgroundTransform = null;
		volumeText = null;
		for (int i = 0; i < bars.Length; i++)
		{
			bars[i] = null;
			barHeights[i] = 0f;
		}
	}

	private void OnDestroy()
	{
		DestroyDisplay();
		if ((Object)(object)panelMaterial != (Object)null)
		{
			Object.Destroy((Object)(object)panelMaterial);
		}
		if ((Object)(object)borderMaterial != (Object)null)
		{
			Object.Destroy((Object)(object)borderMaterial);
		}
		if (barMaterials == null)
		{
			return;
		}
		Material[] array = barMaterials;
		foreach (Material val in array)
		{
			if ((Object)(object)val != (Object)null)
			{
				Object.Destroy((Object)(object)val);
			}
		}
	}
}
[BepInPlugin("eva.customboombox.effects", "Boombox Effects", "2.7.0")]
public class BoomboxEffects : BaseUnityPlugin
{
	private class SoundWave
	{
		public GameObject gameObject;

		public LineRenderer line;

		public float age;

		public float strength;

		public Color color;

		public float sizeMultiplier;

		public float forwardMultiplier;

		public float widthMultiplier;

		public float lifetimeMultiplier;

		public float layerOffset;
	}

	private readonly Vector3 leftSpeaker = new Vector3(-0.25f, 0f, -0.12f);

	private readonly Vector3 rightSpeaker = new Vector3(0.25f, 0f, -0.12f);

	private const float WaveLifetime = 0.85f;

	private const int RingSegments = 48;

	private const float MinimumBeatInterval = 0.18f;

	private const float BackgroundInterval = 1f;

	private const float MainWaveRadius = 0.6687525f;

	private const float LayerOffset = 0.16f;

	private CustomBoombox boomboxPlugin;

	private BoomboxMusic musicPlugin;

	private FieldInfo boomboxField;

	private FieldInfo channelField;

	private FieldInfo hasChannelField;

	private FieldInfo pausedField;

	private GameObject currentBoombox;

	private Material waveMaterial;

	private readonly List<SoundWave> waves = new List<SoundWave>();

	private DSP fft;

	private Channel analyzedChannel;

	private bool hasFFT = false;

	private float averageBass = 0f;

	private float previousBass = 0f;

	private float lastBeatTime = -10f;

	private float lastWaveTime = -10f;

	private void Awake()
	{
		//IL_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Expected O, but got Unknown
		boomboxField = typeof(CustomBoombox).GetField("activeBoombox", BindingFlags.Instance | BindingFlags.NonPublic);
		Type typeFromHandle = typeof(BoomboxMusic);
		channelField = typeFromHandle.GetField("channel", BindingFlags.Instance | BindingFlags.NonPublic);
		hasChannelField = typeFromHandle.GetField("hasChannel", BindingFlags.Instance | BindingFlags.NonPublic);
		pausedField = typeFromHandle.GetField("isPaused", BindingFlags.Instance | BindingFlags.NonPublic);
		Shader val = Shader.Find("Sprites/Default");
		if ((Object)(object)val == (Object)null)
		{
			val = Shader.Find("Unlit/Transparent");
		}
		if ((Object)(object)val != (Object)null)
		{
			waveMaterial = new Material(val);
		}
		else
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"Не найден шейдер для звуковых волн.");
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Boombox Effects 2.7.0 запущен!");
	}

	private void Update()
	{
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		FindBoombox();
		Channel channel;
		bool flag = TryGetPlayingChannel(out channel);
		if (flag && (Object)(object)currentBoombox != (Object)null && (Object)(object)waveMaterial != (Object)null)
		{
			EnsureFFT(channel);
			AnalyzeBass();
		}
		else
		{
			averageBass = 0f;
			previousBass = 0f;
			if (!flag)
			{
				ReleaseFFT();
			}
		}
		UpdateWaves();
	}

	private void FindBoombox()
	{
		if ((Object)(object)boomboxPlugin == (Object)null)
		{
			boomboxPlugin = Object.FindFirstObjectByType<CustomBoombox>();
		}
		if ((Object)(object)musicPlugin == (Object)null)
		{
			musicPlugin = Object.FindFirstObjectByType<BoomboxMusic>();
		}
		if ((Object)(object)boomboxPlugin == (Object)null || boomboxField == null)
		{
			return;
		}
		object? value = boomboxField.GetValue(boomboxPlugin);
		GameObject val = (GameObject)((value is GameObject) ? value : null);
		if (!((Object)(object)val == (Object)(object)currentBoombox))
		{
			ReleaseFFT();
			ClearWaves();
			currentBoombox = val;
			averageBass = 0f;
			previousBass = 0f;
			if ((Object)(object)currentBoombox != (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Эффекты подключены к бумбоксу!");
			}
		}
	}

	private bool TryGetPlayingChannel(out Channel channel)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c6: 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_00cb: Invalid comparison between Unknown and I4
		channel = default(Channel);
		if ((Object)(object)musicPlugin == (Object)null || channelField == null || hasChannelField == null || pausedField == null)
		{
			return false;
		}
		try
		{
			bool flag = (bool)hasChannelField.GetValue(musicPlugin);
			bool flag2 = (bool)pausedField.GetValue(musicPlugin);
			if (!flag || flag2)
			{
				return false;
			}
			channel = (Channel)channelField.GetValue(musicPlugin);
			if (!((Channel)(ref channel)).hasHandle())
			{
				return false;
			}
			bool flag3 = default(bool);
			RESULT val = ((Channel)(ref channel)).isPlaying(ref flag3);
			return (int)val == 0 && flag3;
		}
		catch
		{
			return false;
		}
	}

	private unsafe void EnsureFFT(Channel musicChannel)
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: 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)
		//IL_0055: 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_0058: Invalid comparison between Unknown and I4
		//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_0099: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Invalid comparison between Unknown and I4
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d9: Invalid comparison between Unknown and I4
		//IL_0120: Unknown result type (might be due to invalid IL or missing references)
		//IL_0121: Unknown result type (might be due to invalid IL or missing references)
		//IL_010b: Unknown result type (might be due to invalid IL or missing references)
		if (hasFFT && ((Channel)(ref analyzedChannel)).hasHandle() && analyzedChannel.handle == musicChannel.handle)
		{
			return;
		}
		ReleaseFFT();
		System coreSystem = RuntimeManager.CoreSystem;
		RESULT val = ((System)(ref coreSystem)).createDSPByType((DSP_TYPE)26, ref fft);
		if ((int)val > 0)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("Не удалось создать FFT: " + ((object)(*(RESULT*)(&val))/*cast due to .constrained prefix*/).ToString()));
			return;
		}
		val = ((DSP)(ref fft)).setParameterInt(0, 2048);
		if ((int)val > 0)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("Не удалось настроить FFT: " + ((object)(*(RESULT*)(&val))/*cast due to .constrained prefix*/).ToString()));
		}
		val = ((Channel)(ref musicChannel)).addDSP(0, fft);
		if ((int)val > 0)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("Не удалось подключить FFT: " + ((object)(*(RESULT*)(&val))/*cast due to .constrained prefix*/).ToString()));
			((DSP)(ref fft)).release();
			((DSP)(ref fft)).clearHandle();
		}
		else
		{
			analyzedChannel = musicChannel;
			hasFFT = true;
			averageBass = 0f;
			previousBass = 0f;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"FFT подключён. Анализируем бас!");
		}
	}

	private void AnalyzeBass()
	{
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		if (!hasFFT || !((DSP)(ref fft)).hasHandle())
		{
			EmitBackgroundWave();
			return;
		}
		IntPtr intPtr = default(IntPtr);
		uint num = default(uint);
		RESULT parameterData = ((DSP)(ref fft)).getParameterData(4, ref intPtr, ref num);
		if ((int)parameterData != 0 || intPtr == IntPtr.Zero)
		{
			EmitBackgroundWave();
			return;
		}
		DSP_PARAMETER_FFT val;
		try
		{
			val = (DSP_PARAMETER_FFT)Marshal.PtrToStructure(intPtr, typeof(DSP_PARAMETER_FFT));
		}
		catch
		{
			EmitBackgroundWave();
			return;
		}
		if (val.numchannels <= 0 || val.length <= 0 || ((DSP_PARAMETER_FFT)(ref val)).spectrum == null || ((DSP_PARAMETER_FFT)(ref val)).spectrum[0] == null)
		{
			EmitBackgroundWave();
			return;
		}
		float[] array = ((DSP_PARAMETER_FFT)(ref val)).spectrum[0];
		int num2 = 2;
		int num3 = Mathf.Min(12, array.Length - 1);
		if (num3 < num2)
		{
			EmitBackgroundWave();
			return;
		}
		float num4 = 0f;
		for (int i = num2; i <= num3; i++)
		{
			num4 += array[i];
		}
		num4 /= (float)(num3 - num2 + 1);
		if (averageBass <= 0f)
		{
			averageBass = num4;
		}
		else
		{
			averageBass = Mathf.Lerp(averageBass, num4, Mathf.Clamp01(Time.deltaTime * 2f));
		}
		float num5 = Mathf.Max(averageBass * 1.45f, 0.0001f);
		bool flag = num4 > num5;
		bool flag2 = num4 > previousBass * 1.08f;
		bool flag3 = Time.time - lastBeatTime >= 0.18f;
		if (flag && flag2 && flag3)
		{
			float strength = Mathf.Clamp(num4 / Mathf.Max(averageBass, 0.0001f), 1f, 2f);
			EmitWaves(strength);
			lastBeatTime = Time.time;
			lastWaveTime = Time.time;
		}
		else
		{
			EmitBackgroundWave();
		}
		previousBass = num4;
	}

	private void EmitBackgroundWave()
	{
		if (!(Time.time - lastWaveTime < 1f))
		{
			EmitWaves(0.65f);
			lastWaveTime = Time.time;
		}
	}

	private void EmitWaves(float strength)
	{
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		EmitSpeakerWaves(leftSpeaker, strength, isLeft: true);
		EmitSpeakerWaves(rightSpeaker, strength, isLeft: false);
	}

	private void EmitSpeakerWaves(Vector3 position, float strength, bool isLeft)
	{
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: 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_0072: 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_00ad: Unknown result type (might be due to invalid IL or missing references)
		Color color = (isLeft ? new Color(1f, 0.35f, 0.85f, 0.85f) : new Color(0.7f, 0.35f, 1f, 0.85f));
		CreateWave(position, color, strength, 1f, 1f, 1f, 1f, 0f);
		CreateWave(position, new Color(0.22f, 0.12f, 0.75f, 0.85f), strength, 1.22f, 1.15f, 0.85f, 1.12f, -0.16f);
		CreateWave(position, new Color(1f, 1f, 1f, 0.9f), strength, 0.68f, 0.85f, 0.75f, 0.8f, 0.16f);
	}

	private void CreateWave(Vector3 speakerPosition, Color color, float strength, float sizeMultiplier, float forwardMultiplier, float widthMultiplier, float lifetimeMultiplier, float layerOffset)
	{
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Expected O, but got Unknown
		//IL_0040: 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_00bb: 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)
		if (!((Object)(object)currentBoombox == (Object)null))
		{
			GameObject val = new GameObject("Boombox Sound Wave");
			val.transform.SetParent(currentBoombox.transform, false);
			val.transform.localPosition = speakerPosition;
			val.transform.localRotation = Quaternion.identity;
			LineRenderer val2 = val.AddComponent<LineRenderer>();
			val2.useWorldSpace = false;
			val2.loop = true;
			val2.positionCount = 48;
			((Renderer)val2).sharedMaterial = waveMaterial;
			((Renderer)val2).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)val2).receiveShadows = false;
			SoundWave soundWave = new SoundWave
			{
				gameObject = val,
				line = val2,
				age = 0f,
				strength = strength,
				color = color,
				sizeMultiplier = sizeMultiplier,
				forwardMultiplier = forwardMultiplier,
				widthMultiplier = widthMultiplier,
				lifetimeMultiplier = lifetimeMultiplier,
				layerOffset = layerOffset
			};
			waves.Add(soundWave);
			DrawWave(soundWave);
		}
	}

	private void UpdateWaves()
	{
		for (int num = waves.Count - 1; num >= 0; num--)
		{
			SoundWave soundWave = waves[num];
			if ((Object)(object)soundWave.gameObject == (Object)null || (Object)(object)soundWave.line == (Object)null)
			{
				waves.RemoveAt(num);
			}
			else
			{
				soundWave.age += Time.deltaTime;
				float num2 = 0.85f * soundWave.lifetimeMultiplier;
				if (soundWave.age >= num2)
				{
					Object.Destroy((Object)(object)soundWave.gameObject);
					waves.RemoveAt(num);
				}
				else
				{
					DrawWave(soundWave);
				}
			}
		}
	}

	private void DrawWave(SoundWave wave)
	{
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: 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_0121: Unknown result type (might be due to invalid IL or missing references)
		float num = 0.85f * wave.lifetimeMultiplier;
		float num2 = Mathf.Clamp01(wave.age / num);
		float num3 = Mathf.Lerp(0.08f * wave.sizeMultiplier, 0.6687525f * wave.strength * wave.sizeMultiplier, num2);
		float num4 = Mathf.Lerp(0f, 0.35f * wave.forwardMultiplier, num2);
		num4 += wave.layerOffset;
		float num5 = (1f - num2) * (1f - num2);
		Color color = wave.color;
		color.a *= num5;
		wave.line.startColor = color;
		wave.line.endColor = color;
		float num6 = Mathf.Lerp(0.035f * wave.widthMultiplier, 0.008f * wave.widthMultiplier, num2);
		wave.line.startWidth = num6;
		wave.line.endWidth = num6;
		for (int i = 0; i < 48; i++)
		{
			float num7 = (float)i / 48f * (float)Math.PI * 2f;
			float num8 = Mathf.Cos(num7) * num3;
			float num9 = Mathf.Sin(num7) * num3;
			wave.line.SetPosition(i, new Vector3(num8, num9, num4));
		}
	}

	private void ReleaseFFT()
	{
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		if (hasFFT)
		{
			if (((Channel)(ref analyzedChannel)).hasHandle() && ((DSP)(ref fft)).hasHandle())
			{
				((Channel)(ref analyzedChannel)).removeDSP(fft);
			}
			if (((DSP)(ref fft)).hasHandle())
			{
				((DSP)(ref fft)).release();
				((DSP)(ref fft)).clearHandle();
			}
			analyzedChannel = default(Channel);
			hasFFT = false;
		}
	}

	private void ClearWaves()
	{
		foreach (SoundWave wave in waves)
		{
			if ((Object)(object)wave.gameObject != (Object)null)
			{
				Object.Destroy((Object)(object)wave.gameObject);
			}
		}
		waves.Clear();
	}

	private void OnDestroy()
	{
		ReleaseFFT();
		ClearWaves();
		if ((Object)(object)waveMaterial != (Object)null)
		{
			Object.Destroy((Object)(object)waveMaterial);
		}
	}
}
[BepInPlugin("eva.customboombox.hands", "Boombox Hands", "1.6.0")]
public class BoomboxHands : BaseUnityPlugin
{
	private CustomBoombox boomboxPlugin;

	private FieldInfo holdingField;

	private Animator handsAnimator;

	private Transform handsTransform;

	private string holdingParam;

	private string widthParam;

	private string clutchParam;

	private bool animationActive;

	private bool previousHolding;

	private bool originalHolding;

	private float originalWidth;

	private float originalClutch;

	private Vector3 originalHandsPosition;

	private bool warningShown;

	private float nextSearchTime;

	private const float HandWidth = 0.55f;

	private const float HandClutch = 0.55f;

	private const float HandsBackOffset = -0.035f;

	private readonly BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

	private void Awake()
	{
		holdingField = typeof(CustomBoombox).GetField("isHolding", BindingFlags.Instance | BindingFlags.NonPublic);
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Boombox Hands 1.6.0 запущен!");
	}

	private void LateUpdate()
	{
		if (holdingField == null)
		{
			return;
		}
		try
		{
			if ((Object)(object)boomboxPlugin == (Object)null)
			{
				boomboxPlugin = Object.FindFirstObjectByType<CustomBoombox>();
			}
			if ((Object)(object)boomboxPlugin == (Object)null)
			{
				return;
			}
			bool flag = (bool)holdingField.GetValue(boomboxPlugin);
			if (flag && !previousHolding)
			{
				warningShown = false;
				nextSearchTime = 0f;
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Бумбокс поднят. Настраиваем руки.");
			}
			if (flag)
			{
				if (!animationActive && Time.unscaledTime >= nextSearchTime)
				{
					nextSearchTime = Time.unscaledTime + 3f;
					FindAndActivateHands();
				}
				if (animationActive)
				{
					ApplyHoldingPose();
				}
			}
			else if (animationActive)
			{
				RestoreHands();
			}
			previousHolding = flag;
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)ex);
			if (animationActive)
			{
				RestoreHands();
			}
			((Behaviour)this).enabled = false;
		}
	}

	private void FindAndActivateHands()
	{
		//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
		PlayerInventory val = FindLocalInventory();
		if ((Object)(object)val == (Object)null)
		{
			WarnOnce("Локальный инвентарь не найден.");
			return;
		}
		FieldInfo field = typeof(PlayerInventory).GetField("playerHands", flags);
		GameObject val2 = null;
		if (field != null)
		{
			object? value = field.GetValue(val);
			val2 = (GameObject)((value is GameObject) ? value : null);
		}
		if ((Object)(object)val2 == (Object)null)
		{
			WarnOnce("PlayerHands не найден.");
			return;
		}
		Animator[] array = val2.GetComponentsInChildren<Animator>(true);
		if (array.Length == 0)
		{
			Animator componentInParent = val2.GetComponentInParent<Animator>();
			if ((Object)(object)componentInParent != (Object)null)
			{
				array = (Animator[])(object)new Animator[1] { componentInParent };
			}
		}
		Animator[] array2 = array;
		foreach (Animator val3 in array2)
		{
			if (!((Object)(object)val3 == (Object)null) && HasParameter(val3, "isHoldingItem", (AnimatorControllerParameterType)4) && HasParameter(val3, "handsWidth", (AnimatorControllerParameterType)1) && HasParameter(val3, "handsClutching", (AnimatorControllerParameterType)1))
			{
				handsAnimator = val3;
				holdingParam = "isHoldingItem";
				widthParam = "handsWidth";
				clutchParam = "handsClutching";
				originalHolding = handsAnimator.GetBool(holdingParam);
				originalWidth = handsAnimator.GetFloat(widthParam);
				originalClutch = handsAnimator.GetFloat(clutchParam);
				handsTransform = val2.transform;
				originalHandsPosition = handsTransform.localPosition;
				animationActive = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Animator найден. Новая поза включена!");
				ApplyHoldingPose();
				return;
			}
		}
		WarnOnce("Animator с параметрами удержания не найден.");
	}

	private bool HasParameter(Animator animator, string name, AnimatorControllerParameterType type)
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		AnimatorControllerParameter[] parameters = animator.parameters;
		foreach (AnimatorControllerParameter val in parameters)
		{
			if (val.name == name && val.type == type)
			{
				return true;
			}
		}
		return false;
	}

	private PlayerInventory FindLocalInventory()
	{
		if ((Object)(object)NetworkClient.localPlayer != (Object)null)
		{
			PlayerInventory val = ((Component)NetworkClient.localPlayer).GetComponentInChildren<PlayerInventory>(true);
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)NetworkClient.localPlayer).GetComponentInParent<PlayerInventory>();
			}
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
		}
		Camera main = Camera.main;
		if ((Object)(object)main != (Object)null)
		{
			return ((Component)main).GetComponentInParent<PlayerInventory>();
		}
		return null;
	}

	private void ApplyHoldingPose()
	{
		//IL_0074: 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_008d: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)handsAnimator == (Object)null)
		{
			animationActive = false;
			return;
		}
		handsAnimator.SetBool(holdingParam, true);
		handsAnimator.SetFloat(widthParam, 0.55f);
		handsAnimator.SetFloat(clutchParam, 0.55f);
		if ((Object)(object)handsTransform != (Object)null)
		{
			handsTransform.localPosition = originalHandsPosition + new Vector3(0f, 0f, -0.035f);
		}
	}

	private void RestoreHands()
	{
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)handsAnimator != (Object)null)
		{
			handsAnimator.SetBool(holdingParam, originalHolding);
			handsAnimator.SetFloat(widthParam, originalWidth);
			handsAnimator.SetFloat(clutchParam, originalClutch);
		}
		if ((Object)(object)handsTransform != (Object)null)
		{
			handsTransform.localPosition = originalHandsPosition;
		}
		animationActive = false;
		handsAnimator = null;
		handsTransform = null;
		holdingParam = null;
		widthParam = null;
		clutchParam = null;
		warningShown = false;
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Руки возвращены в обычное положение.");
	}

	private void WarnOnce(string message)
	{
		if (!warningShown)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)message);
			warningShown = true;
		}
	}

	private void OnDisable()
	{
		if (animationActive)
		{
			RestoreHands();
		}
	}
}
public class BoomboxItem : Item
{
	protected override void OnPickedUp(PlayerInventory playerInventory)
	{
		((Item)this).OnPickedUp(playerInventory);
	}

	protected override void OnDropped(PlayerInventory playerInventory)
	{
		((Item)this).OnDropped(playerInventory);
	}
}
[BepInPlugin("eva.customboombox.multiplayer", "Boombox Multiplayer", "1.3.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class BoomboxMultiplayer : BaseUnityPlugin
{
	public struct State : NetworkMessage
	{
		public bool exists;

		public Vector3 position;

		public Quaternion rotation;

		public bool playing;

		public bool paused;

		public int song;

		public float volume;

		public uint positionMs;

		public uint holderNetId;
	}

	public struct Request : NetworkMessage
	{
		public byte action;

		public uint playerNetId;
	}

	private CustomBoombox boombox;

	private BoomboxMusic music;

	private FieldInfo activeField;

	private FieldInfo musicObjectField;

	private FieldInfo songField;

	private FieldInfo volumeField;

	private FieldInfo pausedField;

	private FieldInfo hasChannelField;

	private FieldInfo channelField;

	private MethodInfo spawnMethod;

	private MethodInfo playMethod;

	private MethodInfo toggleMethod;

	private MethodInfo nextMethod;

	private MethodInfo prevMethod;

	private MethodInfo volumeMethod;

	private GameObject hostObject;

	private GameObject remoteObject;

	private uint holderId;

	private bool clientRegistered;

	private bool serverRegistered;

	private float nextState;

	private int lastSong = -1;

	private bool lastPlaying;

	private bool lastPaused;

	private Vector3 targetPosition;

	private Quaternion targetRotation;

	private bool haveTarget;

	private bool applyingRemote;

	private const BindingFlags Flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

	private static void WriteState(NetworkWriter w, State s)
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		NetworkWriterExtensions.WriteBool(w, s.exists);
		NetworkWriterExtensions.WriteVector3(w, s.position);
		NetworkWriterExtensions.WriteQuaternion(w, s.rotation);
		NetworkWriterExtensions.WriteBool(w, s.playing);
		NetworkWriterExtensions.WriteBool(w, s.paused);
		NetworkWriterExtensions.WriteInt(w, s.song);
		NetworkWriterExtensions.WriteFloat(w, s.volume);
		NetworkWriterExtensions.WriteUInt(w, s.positionMs);
		NetworkWriterExtensions.WriteUInt(w, s.holderNetId);
	}

	private static State ReadState(NetworkReader r)
	{
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)
		return new State
		{
			exists = NetworkReaderExtensions.ReadBool(r),
			position = NetworkReaderExtensions.ReadVector3(r),
			rotation = NetworkReaderExtensions.ReadQuaternion(r),
			playing = NetworkReaderExtensions.ReadBool(r),
			paused = NetworkReaderExtensions.ReadBool(r),
			song = NetworkReaderExtensions.ReadInt(r),
			volume = NetworkReaderExtensions.ReadFloat(r),
			positionMs = NetworkReaderExtensions.ReadUInt(r),
			holderNetId = NetworkReaderExtensions.ReadUInt(r)
		};
	}

	private static void WriteRequest(NetworkWriter w, Request s)
	{
		w.WriteByte(s.action);
		NetworkWriterExtensions.WriteUInt(w, s.playerNetId);
	}

	private static Request ReadRequest(NetworkReader r)
	{
		return new Request
		{
			action = r.ReadByte(),
			playerNetId = NetworkReaderExtensions.ReadUInt(r)
		};
	}

	private void Awake()
	{
		Writer<State>.write = WriteState;
		Reader<State>.read = ReadState;
		Writer<Request>.write = WriteRequest;
		Reader<Request>.read = ReadRequest;
		((BaseUnityPlugin)this).Logger.LogInfo((object)"[MULTIPLAYER] 1.3 loaded");
	}

	private bool Resolve()
	{
		if ((Object)(object)boombox == (Object)null)
		{
			boombox = Object.FindFirstObjectByType<CustomBoombox>();
		}
		if ((Object)(object)music == (Object)null)
		{
			music = Object.FindFirstObjectByType<BoomboxMusic>();
		}
		if ((Object)(object)boombox == (Object)null || (Object)(object)music == (Object)null)
		{
			return false;
		}
		if (activeField != null)
		{
			return true;
		}
		Type type = ((object)boombox).GetType();
		Type type2 = ((object)music).GetType();
		activeField = type.GetField("activeBoombox", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		spawnMethod = type.GetMethod("SpawnBoombox", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		musicObjectField = type2.GetField("currentBoombox", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		songField = type2.GetField("currentSong", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		volumeField = type2.GetField("volume", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		pausedField = type2.GetField("isPaused", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		hasChannelField = type2.GetField("hasChannel", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		channelField = type2.GetField("channel", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		playMethod = type2.GetMethod("PlayCurrentSong", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		toggleMethod = type2.GetMethod("ToggleMusic", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		nextMethod = type2.GetMethod("NextSong", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		prevMethod = type2.GetMethod("PreviousSong", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		volumeMethod = type2.GetMethod("ChangeVolume", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		if (activeField == null || spawnMethod == null || songField == null || musicObjectField == null || volumeField == null || pausedField == null || hasChannelField == null || channelField == null || playMethod == null || toggleMethod == null || nextMethod == null || prevMethod == null || volumeMethod == null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"[MULTIPLAYER] Missing field or method in CustomBoombox/BoomboxMusic");
			((Behaviour)this).enabled = false;
			return false;
		}
		return true;
	}

	private void Update()
	{
		if (!Resolve())
		{
			return;
		}
		if (NetworkClient.active && !clientRegistered)
		{
			NetworkClient.RegisterHandler<State>((Action<State>)OnState, false);
			clientRegistered = true;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[MULTIPLAYER] Client handler registered");
		}
		if (!NetworkClient.active)
		{
			clientRegistered = false;
		}
		if (NetworkServer.active && !serverRegistered)
		{
			NetworkServer.RegisterHandler<Request>((Action<NetworkConnectionToClient, Request>)OnRequest, false);
			serverRegistered = true;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[MULTIPLAYER] Server handler registered");
		}
		if (!NetworkServer.active)
		{
			serverRegistered = false;
			holderId = 0u;
			hostObject = null;
		}
		if (NetworkServer.active)
		{
			ref GameObject reference = ref hostObject;
			object? value = activeField.GetValue(boombox);
			reference = (GameObject)((value is GameObject) ? value : null);
			if ((Object)(object)hostObject != (Object)null && holderId != 0)
			{
				FollowHolder();
			}
			if (Time.unscaledTime >= nextState)
			{
				nextState = Time.unscaledTime + 0.15f;
				NetworkServer.SendToAll<State>(CaptureState(), 0, false);
			}
		}
		else if (NetworkClient.active && (Object)(object)remoteObject != (Object)null && Keyboard.current != null)
		{
			Keyboard current = Keyboard.current;
			if (((ButtonControl)current.eKey).wasPressedThisFrame)
			{
				SendRequest(1);
			}
			if (((ButtonControl)current.pKey).wasPressedThisFrame)
			{
				SendRequest(2);
			}
			if (((ButtonControl)current.nKey).wasPressedThisFrame)
			{
				SendRequest(3);
			}
			if (((ButtonControl)current.bKey).wasPressedThisFrame)
			{
				SendRequest(4);
			}
			if (((ButtonControl)current.minusKey).wasPressedThisFrame || ((ButtonControl)current.numpadMinusKey).wasPressedThisFrame)
			{
				SendRequest(5);
			}
			if (((ButtonControl)current.equalsKey).wasPressedThisFrame || ((ButtonControl)current.numpadPlusKey).wasPressedThisFrame)
			{
				SendRequest(6);
			}
		}
	}

	private void LateUpdate()
	{
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		if (!NetworkServer.active && (Object)(object)remoteObject != (Object)null && haveTarget)
		{
			remoteObject.transform.position = targetPosition;
			remoteObject.transform.rotation = targetRotation;
		}
	}

	private void SendRequest(byte action)
	{
		if (!((Object)(object)NetworkClient.localPlayer == (Object)null))
		{
			NetworkClient.Send<Request>(new Request
			{
				action = action,
				playerNetId = NetworkClient.localPlayer.netId
			}, 0);
		}
	}

	private void OnRequest(NetworkConnectionToClient sender, Request req)
	{
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
		if (!NetworkServer.active || (Object)(object)hostObject == (Object)null || sender == null || (Object)(object)((NetworkConnection)sender).identity == (Object)null || ((NetworkConnection)sender).identity.netId != req.playerNetId)
		{
			return;
		}
		try
		{
			if (req.action == 1)
			{
				if (holderId == req.playerNetId)
				{
					holderId = 0u;
				}
				else if (holderId == 0 && Vector3.Distance(((Component)((NetworkConnection)sender).identity).transform.position, hostObject.transform.position) < 4f)
				{
					holderId = req.playerNetId;
				}
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[MULTIPLAYER] Holder: " + holderId));
			}
			else if (req.action == 2)
			{
				toggleMethod.Invoke(music, null);
			}
			else if (req.action == 3)
			{
				nextMethod.Invoke(music, null);
			}
			else if (req.action == 4)
			{
				prevMethod.Invoke(music, null);
			}
			else if (req.action == 5)
			{
				volumeMethod.Invoke(music, new object[1] { -0.1f });
			}
			else if (req.action == 6)
			{
				volumeMethod.Invoke(music, new object[1] { 0.1f });
			}
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("[MULTIPLAYER] Request: " + ex));
		}
	}

	private void FollowHolder()
	{
		//IL_009f: 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)
		if (!NetworkServer.spawned.TryGetValue(holderId, out var value) || (Object)(object)value == (Object)null)
		{
			holderId = 0u;
			return;
		}
		Component componentInChildren = (Component)(object)((Component)value).GetComponentInChildren<PlayerInventory>();
		if ((Object)(object)componentInChildren == (Object)null)
		{
			holderId = 0u;
			return;
		}
		FieldInfo field = ((object)componentInChildren).GetType().GetField("handTransform", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		Transform val = (Transform)((field == null) ? null : /*isinst with value type is only supported in some contexts*/);
		if ((Object)(object)val == (Object)null)
		{
			holderId = 0u;
			return;
		}
		hostObject.transform.position = val.position;
		hostObject.transform.rotation = val.rotation;
	}

	private State CaptureState()
	{
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_011a: Unknown result type (might be due to invalid IL or missing references)
		State result = new State
		{
			exists = ((Object)(object)hostObject != (Object)null)
		};
		if (!result.exists)
		{
			return result;
		}
		result.position = hostObject.transform.position;
		result.rotation = hostObject.transform.rotation;
		result.song = (int)songField.GetValue(music);
		result.volume = (float)volumeField.GetValue(music);
		result.paused = (bool)pausedField.GetValue(music);
		result.playing = (bool)hasChannelField.GetValue(music);
		result.holderNetId = holderId;
		if (result.playing)
		{
			try
			{
				Channel val = (Channel)channelField.GetValue(music);
				if (((Channel)(ref val)).hasHandle())
				{
					((Channel)(ref val)).getPosition(ref result.positionMs, (TIMEUNIT)1);
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("[MULTIPLAYER] FMOD position: " + ex.Message));
			}
		}
		return result;
	}

	private void OnState(State s)
	{
		//IL_0150: Unknown result type (might be due to invalid IL or missing references)
		//IL_0155: Unknown result type (might be due to invalid IL or missing references)
		//IL_015c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0161: Unknown result type (might be due to invalid IL or missing references)
		if (NetworkServer.active || !Resolve())
		{
			return;
		}
		if (!s.exists)
		{
			if ((Object)(object)remoteObject != (Object)null)
			{
				Object.Destroy((Object)(object)remoteObject);
			}
			remoteObject = null;
			activeField.SetValue(boombox, null);
			haveTarget = false;
			lastSong = -1;
			lastPlaying = false;
			return;
		}
		if ((Object)(object)remoteObject == (Object)null)
		{
			try
			{
				spawnMethod.Invoke(boombox, null);
				ref GameObject reference = ref remoteObject;
				object? value = activeField.GetValue(boombox);
				reference = (GameObject)((value is GameObject) ? value : null);
				if ((Object)(object)remoteObject == (Object)null)
				{
					return;
				}
				((BaseUnityPlugin)this).Logger.LogInfo((object)"[MULTIPLAYER] Host boombox created locally");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("[MULTIPLAYER] Spawn: " + ex));
				return;
			}
		}
		if (musicObjectField.GetValue(music) != remoteObject)
		{
			musicObjectField.SetValue(music, remoteObject);
		}
		targetPosition = s.position;
		targetRotation = s.rotation;
		haveTarget = true;
		ApplyMusic(s);
	}

	private void ApplyMusic(State s)
	{
		//IL_015e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0163: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_017a: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
		if (applyingRemote)
		{
			return;
		}
		applyingRemote = true;
		try
		{
			volumeField.SetValue(music, s.volume);
			bool flag = lastSong != s.song || lastPlaying != s.playing;
			if (!s.playing)
			{
				if (lastPlaying)
				{
					((object)music).GetType().GetMethod("StopMusic", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Invoke(music, null);
				}
				songField.SetValue(music, s.song);
			}
			else if (flag)
			{
				songField.SetValue(music, s.song);
				playMethod.Invoke(music, new object[2] { s.positionMs, s.paused });
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[MULTIPLAYER] Synced song " + s.song));
			}
			else if (lastPaused != s.paused)
			{
				Channel val = (Channel)channelField.GetValue(music);
				if (((Channel)(ref val)).hasHandle())
				{
					((Channel)(ref val)).setPaused(s.paused);
				}
				pausedField.SetValue(music, s.paused);
			}
			if (s.playing)
			{
				Channel val2 = (Channel)channelField.GetValue(music);
				if (((Channel)(ref val2)).hasHandle())
				{
					((Channel)(ref val2)).setVolume(s.volume);
				}
			}
			lastSong = s.song;
			lastPlaying = s.playing;
			lastPaused = s.paused;
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("[MULTIPLAYER] Music sync: " + ex));
		}
		finally
		{
			applyingRemote = false;
		}
	}
}
[BepInPlugin("eva.customboombox.music", "Boombox Music", "2.1.0")]
public class BoomboxMusic : BaseUnityPlugin
{
	private CustomBoombox boomboxPlugin;

	private FieldInfo boomboxField;

	private GameObject currentBoombox;

	private string musicFolder;

	private string[] songs = new string[0];

	private int currentSong = 0;

	private float volume = 0.7f;

	private Sound sound;

	private Channel channel;

	private bool hasSound = false;

	private bool hasChannel = false;

	private bool isPaused = false;

	private bool wasPlaying = false;

	private float nextEndCheck = 0f;

	private bool changingScene = false;

	private Coroutine sceneCoroutine;

	private void Awake()
	{
		string directoryName = Path.GetDirectoryName(typeof(BoomboxMusic).Assembly.Location);
		musicFolder = Path.Combine(directoryName, "Music");
		Directory.CreateDirectory(musicFolder);
		boomboxField = typeof(CustomBoombox).GetField("activeBoombox", BindingFlags.Instance | BindingFlags.NonPublic);
		RefreshPlaylist();
		SceneManager.activeSceneChanged += OnSceneChanged;
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Boombox Music 2.1.0 запущен!");
	}

	private void Update()
	{
		if (!changingScene)
		{
			FindBoombox();
		}
		if (Keyboard.current != null && !changingScene)
		{
			if (((ButtonControl)Keyboard.current.pKey).wasPressedThisFrame)
			{
				ToggleMusic();
			}
			if (((ButtonControl)Keyboard.current.bKey).wasPressedThisFrame)
			{
				PreviousSong();
			}
			if (((ButtonControl)Keyboard.current.nKey).wasPressedThisFrame)
			{
				NextSong();
			}
			if (((ButtonControl)Keyboard.current.minusKey).wasPressedThisFrame || ((ButtonControl)Keyboard.current.numpadMinusKey).wasPressedThisFrame)
			{
				ChangeVolume(-0.1f);
			}
			if (((ButtonControl)Keyboard.current.equalsKey).wasPressedThisFrame || ((ButtonControl)Keyboard.current.numpadPlusKey).wasPressedThisFrame)
			{
				ChangeVolume(0.1f);
			}
		}
		if (!changingScene)
		{
			UpdateSoundPosition();
			CheckSongEnd();
		}
	}

	private void RefreshPlaylist()
	{
		songs = Directory.GetFiles(musicFolder, "*.mp3").OrderBy<string, string>((string path) => Path.GetFileName(path), StringComparer.OrdinalIgnoreCase).ToArray();
		if (currentSong >= songs.Length)
		{
			currentSong = 0;
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)("Найдено MP3: " + songs.Length));
	}

	private GameObject GetPluginBoombox()
	{
		if ((Object)(object)boomboxPlugin == (Object)null)
		{
			boomboxPlugin = Object.FindFirstObjectByType<CustomBoombox>();
		}
		if ((Object)(object)boomboxPlugin == (Object)null || boomboxField == null)
		{
			return null;
		}
		object? value = boomboxField.GetValue(boomboxPlugin);
		return (GameObject)((value is GameObject) ? value : null);
	}

	private void FindBoombox()
	{
		GameObject pluginBoombox = GetPluginBoombox();
		if (!((Object)(object)pluginBoombox == (Object)(object)currentBoombox))
		{
			StopMusic();
			currentBoombox = pluginBoombox;
			if ((Object)(object)currentBoombox != (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"FMOD подключён к бумбоксу!");
			}
		}
	}

	private void ToggleMusic()
	{
		//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Invalid comparison between Unknown and I4
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: 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_00a0: Invalid comparison between Unknown and I4
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fa: Invalid comparison between Unknown and I4
		if ((Object)(object)currentBoombox == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)"Сначала создай бумбокс через F8.");
			return;
		}
		if (songs.Length == 0)
		{
			RefreshPlaylist();
			if (songs.Length == 0)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"В папке Music нет MP3.");
				return;
			}
		}
		if (hasChannel && ((Channel)(ref channel)).hasHandle())
		{
			if (isPaused)
			{
				RESULT val = ((Channel)(ref channel)).setPaused(false);
				if ((int)val == 0)
				{
					isPaused = false;
					wasPlaying = true;
					((BaseUnityPlugin)this).Logger.LogInfo((object)"Музыка продолжена.");
				}
				return;
			}
			bool flag = default(bool);
			RESULT val2 = ((Channel)(ref channel)).isPlaying(ref flag);
			if ((int)val2 == 0 && flag)
			{
				RESULT val3 = ((Channel)(ref channel)).setPaused(true);
				if ((int)val3 == 0)
				{
					isPaused = true;
					((BaseUnityPlugin)this).Logger.LogInfo((object)"Пауза.");
				}
				return;
			}
		}
		PlayCurrentSong(0u, startPaused: false);
	}

	private unsafe void PlayCurrentSong(uint startPositionMs, bool startPaused)
	{
		//IL_0058: 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_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Invalid comparison between Unknown and I4
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Invalid comparison between Unknown and I4
		//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_0101: Unknown result type (might be due to invalid IL or missing references)
		//IL_0106: Unknown result type (might be due to invalid IL or missing references)
		//IL_0107: Unknown result type (might be due to invalid IL or missing references)
		//IL_0109: Invalid comparison between Unknown and I4
		//IL_0154: Unknown result type (might be due to invalid IL or missing references)
		//IL_016a: Unknown result type (might be due to invalid IL or missing references)
		//IL_017b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0180: Unknown result type (might be due to invalid IL or missing references)
		//IL_0181: Unknown result type (might be due to invalid IL or missing references)
		//IL_0183: Invalid comparison between Unknown and I4
		//IL_0207: Unknown result type (might be due to invalid IL or missing references)
		//IL_020c: Unknown result type (might be due to invalid IL or missing references)
		//IL_020d: Unknown result type (might be due to invalid IL or missing references)
		//IL_020f: Invalid comparison between Unknown and I4
		//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)currentBoombox == (Object)null || songs.Length == 0)
		{
			return;
		}
		StopMusic();
		string text = songs[currentSong];
		((BaseUnityPlugin)this).Logger.LogInfo((object)("Открываем MP3: " + Path.GetFileName(text)));
		try
		{
			System coreSystem = RuntimeManager.CoreSystem;
			RESULT val = ((System)(ref coreSystem)).createSound(text, (MODE)2097297, ref sound);
			if ((int)val > 0)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Не удалось открыть MP3: " + ((object)(*(RESULT*)(&val))/*cast due to .constrained prefix*/).ToString()));
				return;
			}
			hasSound = true;
			ChannelGroup val2 = default(ChannelGroup);
			val = ((System)(ref coreSystem)).getMasterChannelGroup(ref val2);
			if ((int)val > 0)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Ошибка звуковой группы: " + ((object)(*(RESULT*)(&val))/*cast due to .constrained prefix*/).ToString()));
				StopMusic();
				return;
			}
			val = ((System)(ref coreSystem)).playSound(sound, val2, true, ref channel);
			if ((int)val > 0)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Ошибка запуска MP3: " + ((object)(*(RESULT*)(&val))/*cast due to .constrained prefix*/).ToString()));
				StopMusic();
				return;
			}
			hasChannel = true;
			((Channel)(ref channel)).setVolume(volume);
			((Channel)(ref channel)).set3DMinMaxDistance(2f, 25f);
			val = ((Channel)(ref channel)).set3DDopplerLevel(0f);
			if ((int)val > 0)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Не удалось отключить Доплер: " + ((object)(*(RESULT*)(&val))/*cast due to .constrained prefix*/).ToString()));
			}
			UpdateSoundPosition();
			if (startPositionMs != 0)
			{
				uint num = default(uint);
				val = ((Sound)(ref sound)).getLength(ref num, (TIMEUNIT)1);
				if ((int)val == 0 && num != 0)
				{
					uint num2 = Math.Min(startPositionMs, num - 1);
					((Channel)(ref channel)).setPosition(num2, (TIMEUNIT)1);
				}
			}
			val = ((Channel)(ref channel)).setPaused(startPaused);
			if ((int)val > 0)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Не удалось настроить паузу: " + ((object)(*(RESULT*)(&val))/*cast due to .constrained prefix*/).ToString()));
				StopMusic();
				return;
			}
			isPaused = startPaused;
			wasPlaying = !startPaused;
			nextEndCheck = Time.time + 2f;
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Сейчас играет: " + Path.GetFileName(text)));
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Ошибка FMOD: " + ex));
			StopMusic();
		}
	}

	private void UpdateSoundPosition()
	{
		//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_0047: 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_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: 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_0079: 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_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Invalid comparison between Unknown and I4
		//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: Invalid comparison between Unknown and I4
		if (!((Object)(object)currentBoombox == (Object)null) && hasChannel && ((Channel)(ref channel)).hasHandle())
		{
			Vector3 position = currentBoombox.transform.position;
			VECTOR val = new VECTOR
			{
				x = position.x,
				y = position.y,
				z = position.z
			};
			VECTOR val2 = new VECTOR
			{
				x = 0f,
				y = 0f,
				z = 0f
			};
			RESULT val3 = ((Channel)(ref channel)).set3DAttributes(ref val, ref val2);
			if ((int)val3 > 0 && (int)val3 == 30)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"FMOD-канал стал недействительным.");
				StopMusic();
			}
		}
	}

	private unsafe void CheckSongEnd()
	{
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Invalid comparison between Unknown and I4
		if (hasChannel && ((Channel)(ref channel)).hasHandle() && !isPaused && wasPlaying && !(Time.time < nextEndCheck))
		{
			bool flag = default(bool);
			RESULT val = ((Channel)(ref channel)).isPlaying(ref flag);
			if ((int)val > 0)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("FMOD-канал недоступен: " + ((object)(*(RESULT*)(&val))/*cast due to .constrained prefix*/).ToString()));
				StopMusic();
			}
			else if (!flag)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Песня закончилась.");
				NextSong();
			}
		}
	}

	private void NextSong()
	{
		if (!((Object)(object)currentBoombox == (Object)null))
		{
			if (songs.Length == 0)
			{
				RefreshPlaylist();
			}
			if (songs.Length != 0)
			{
				currentSong = (currentSong + 1) % songs.Length;
				PlayCurrentSong(0u, startPaused: false);
			}
		}
	}

	private void PreviousSong()
	{
		if (!((Object)(object)currentBoombox == (Object)null))
		{
			if (songs.Length == 0)
			{
				RefreshPlaylist();
			}
			if (songs.Length != 0)
			{
				currentSong = (currentSong - 1 + songs.Length) % songs.Length;
				PlayCurrentSong(0u, startPaused: false);
			}
		}
	}

	private void ChangeVolume(float amount)
	{
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		volume = Mathf.Clamp01(volume + amount);
		if (hasChannel && ((Channel)(ref channel)).hasHandle())
		{
			((Channel)(ref channel)).setVolume(volume);
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)("Громкость: " + Mathf.RoundToInt(volume * 100f) + "%"));
	}

	private void OnSceneChanged(Scene oldScene, Scene newScene)
	{
		if (sceneCoroutine != null)
		{
			((MonoBehaviour)this).StopCoroutine(sceneCoroutine);
		}
		sceneCoroutine = ((MonoBehaviour)this).StartCoroutine(RestoreAfterSceneChange());
	}

	private IEnumerator RestoreAfterSceneChange()
	{
		changingScene = true;
		bool resumeMusic = false;
		bool resumePaused = false;
		uint savedPositionMs = 0u;
		if (hasChannel && ((Channel)(ref channel)).hasHandle())
		{
			bool playing = default(bool);
			RESULT status = ((Channel)(ref channel)).isPlaying(ref playing);
			resumeMusic = isPaused || ((int)status == 0 && playing);
			resumePaused = isPaused;
			if (resumeMusic)
			{
				((Channel)(ref channel)).getPosition(ref savedPositionMs, (TIMEUNIT)1);
			}
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Смена локации. Переподключаем звук.");
		StopMusic();
		yield return (object)new WaitForSecondsRealtime(0.5f);
		currentBoombox = null;
		boomboxPlugin = null;
		float deadline = Time.realtimeSinceStartup + 5f;
		while ((Object)(object)currentBoombox == (Object)null && Time.realtimeSinceStartup < deadline)
		{
			currentBoombox = GetPluginBoombox();
			if ((Object)(object)currentBoombox == (Object)null)
			{
				yield return (object)new WaitForSecondsRealtime(0.2f);
			}
		}
		changingScene = false;
		sceneCoroutine = null;
		if ((Object)(object)currentBoombox == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)"В новой локации бумбокс не найден. Создай его через F8.");
			yield break;
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Бумбокс найден в новой локации.");
		if (resumeMusic)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Восстанавливаем песню с позиции " + (float)savedPositionMs / 1000f + " секунд."));
			PlayCurrentSong(savedPositionMs, resumePaused);
		}
	}

	private void StopMusic()
	{
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		wasPlaying = false;
		isPaused = false;
		if (hasChannel)
		{
			if (((Channel)(ref channel)).hasHandle())
			{
				((Channel)(ref channel)).stop();
			}
			hasChannel = false;
			((Channel)(ref channel)).clearHandle();
		}
		if (hasSound)
		{
			if (((Sound)(ref sound)).hasHandle())
			{
				((Sound)(ref sound)).release();
			}
			hasSound = false;
			((Sound)(ref sound)).clearHandle();
		}
	}

	private void OnDestroy()
	{
		SceneManager.activeSceneChanged -= OnSceneChanged;
		if (sceneCoroutine != null)
		{
			((MonoBehaviour)this).StopCoroutine(sceneCoroutine);
		}
		StopMusic();
	}
}
[BepInPlugin("eva.customboombox", "Custom Boombox", "1.5.0")]
public class CustomBoombox : BaseUnityPlugin
{
	private GameObject boomboxPrefab;

	private GameObject activeBoombox;

	private AssetBundle bundle;

	private Rigidbody boomboxRb;

	private Collider[] boomboxColliders;

	private bool isHolding = false;

	private float pickupDistance = 3f;

	private float holdingDistance = 0.95f;

	private float holdingHeight = 0.35f;

	private float holdingTilt = 0f;

	private Transform handTransform;

	private Vector3 initialHandLocalPosition;

	private bool handPositionInitialized = false;

	private readonly BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

	private void Awake()
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Custom Boombox 1.5.0 запущен!");
		try
		{
			string directoryName = Path.GetDirectoryName(typeof(CustomBoombox).Assembly.Location);
			string text = Path.Combine(directoryName, "customboombox");
			bundle = AssetBundle.LoadFromFile(text);
			if ((Object)(object)bundle == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"Не удалось загрузить customboombox.");
				return;
			}
			GameObject[] array = bundle.LoadAllAssets<GameObject>();
			if (array.Length == 0)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"В AssetBundle нет моделей.");
				return;
			}
			boomboxPrefab = array[0];
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Модель загружена: " + ((Object)boomboxPrefab).name));
			((BaseUnityPlugin)this).Logger.LogInfo((object)"F8 — создать бумбокс.");
			((BaseUnityPlugin)this).Logger.LogInfo((object)"E — поднять или положить бумбокс.");
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)ex);
		}
	}

	private void Update()
	{
		if (Keyboard.current != null)
		{
			if (((ButtonControl)Keyboard.current.f8Key).wasPressedThisFrame)
			{
				SpawnBoombox();
			}
			if (((ButtonControl)Keyboard.current.eKey).wasPressedThisFrame)
			{
				TogglePickup();
			}
		}
	}

	private void LateUpdate()
	{
		if (isHolding)
		{
			UpdateHeldPosition();
		}
	}

	private void SpawnBoombox()
	{
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: 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)
		if ((Object)(object)boomboxPrefab == (Object)null)
		{
			return;
		}
		Camera main = Camera.main;
		if ((Object)(object)main == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)"Камера не найдена.");
			return;
		}
		if ((Object)(object)activeBoombox != (Object)null)
		{
			Object.Destroy((Object)(object)activeBoombox);
		}
		isHolding = false;
		boomboxRb = null;
		boomboxColliders = null;
		handTransform = null;
		handPositionInitialized = false;
		Vector3 val = ((Component)main).transform.position + ((Component)main).transform.forward * 2f;
		activeBoombox = Object.Instantiate<GameObject>(boomboxPrefab, val, Quaternion.identity);
		((Object)activeBoombox).name = "CustomBoombox";
		ApplyLitMaterials(activeBoombox);
		boomboxRb = activeBoombox.GetComponent<Rigidbody>();
		if ((Object)(object)boomboxRb == (Object)null)
		{
			boomboxRb = activeBoombox.AddComponent<Rigidbody>();
		}
		boomboxRb.mass = 1f;
		boomboxRb.useGravity = true;
		boomboxRb.isKinematic = false;
		boomboxColliders = activeBoombox.GetComponentsInChildren<Collider>(true);
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Бумбокс создан!");
	}

	private void TogglePickup()
	{
		if (!((Object)(object)activeBoombox == (Object)null))
		{
			if (isHolding)
			{
				DropBoombox();
			}
			else
			{
				TryPickupBoombox();
			}
		}
	}

	private void TryPickupBoombox()
	{
		//IL_001f: 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_00b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		Camera main = Camera.main;
		RaycastHit val = default(RaycastHit);
		if ((Object)(object)main == (Object)null || !Physics.Raycast(((Component)main).transform.position, ((Component)main).transform.forward, ref val, pickupDistance, -5, (QueryTriggerInteraction)2))
		{
			return;
		}
		Transform transform = ((Component)((RaycastHit)(ref val)).collider).transform;
		if ((Object)(object)transform != (Object)(object)activeBoombox.transform && !transform.IsChildOf(activeBoombox.transform))
		{
			return;
		}
		isHolding = true;
		if ((Object)(object)boomboxRb != (Object)null)
		{
			boomboxRb.linearVelocity = Vector3.zero;
			boomboxRb.angularVelocity = Vector3.zero;
			boomboxRb.useGravity = false;
			boomboxRb.isKinematic = true;
		}
		if (boomboxColliders != null)
		{
			Collider[] array = boomboxColliders;
			foreach (Collider val2 in array)
			{
				if ((Object)(object)val2 != (Object)null)
				{
					val2.enabled = false;
				}
			}
		}
		FindHandTransform();
		handPositionInitialized = false;
		UpdateHeldPosition();
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Бумбокс поднят!");
	}

	private void FindHandTransform()
	{
		handTransform = null;
		PlayerInventory val = null;
		if ((Object)(object)NetworkClient.localPlayer != (Object)null)
		{
			val = ((Component)NetworkClient.localPlayer).GetComponentInChildren<PlayerInventory>(true);
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)NetworkClient.localPlayer).GetComponentInParent<PlayerInventory>();
			}
		}
		if ((Object)(object)val == (Object)null)
		{
			Camera main = Camera.main;
			if ((Object)(object)main != (Object)null)
			{
				val = ((Component)main).GetComponentInParent<PlayerInventory>();
			}
		}
		if ((Object)(object)val == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)"Инвентарь не найден. Используем прежнее движение бумбокса.");
			return;
		}
		FieldInfo field = typeof(PlayerInventory).GetField("handTransform", flags);
		if (field != null)
		{
			ref Transform reference = ref handTransform;
			object? value = field.GetValue(val);
			reference = (Transform)((value is Transform) ? value : null);
		}
		if ((Object)(object)handTransform != (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)("HandTransform найден: " + ((Object)handTransform).name));
		}
		else
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)"HandTransform не найден. Используем прежнее движение.");
		}
	}

	private void UpdateHeldPosition()
	{
		//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0103: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: 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_00c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: 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_0091: 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)
		if (!isHolding || (Object)(object)activeBoombox == (Object)null)
		{
			return;
		}
		Camera main = Camera.main;
		if ((Object)(object)main == (Object)null)
		{
			return;
		}
		Transform transform = ((Component)main).transform;
		Vector3 val = default(Vector3);
		((Vector3)(ref val))..ctor(0f, 0f - holdingHeight, holdingDistance);
		if ((Object)(object)handTransform != (Object)null)
		{
			Vector3 val2 = transform.InverseTransformPoint(handTransform.position);
			if (!handPositionInitialized)
			{
				initialHandLocalPosition = val2;
				handPositionInitialized = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Движение HandTransform подключено!");
			}
			Vector3 val3 = val2 - initialHandLocalPosition;
			val += val3;
		}
		activeBoombox.transform.position = transform.TransformPoint(val);
		activeBoombox.transform.rotation = Quaternion.Euler(holdingTilt, transform.eulerAngles.y, 0f);
	}

	private void DropBoombox()
	{
		//IL_0040: 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_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: 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)
		if ((Object)(object)activeBoombox == (Object)null)
		{
			return;
		}
		isHolding = false;
		Camera main = Camera.main;
		if ((Object)(object)main != (Object)null)
		{
			activeBoombox.transform.position = ((Component)main).transform.position + ((Component)main).transform.forward * 1.5f - ((Component)main).transform.up * 0.4f;
		}
		if ((Object)(object)boomboxRb != (Object)null)
		{
			boomboxRb.isKinematic = false;
			boomboxRb.useGravity = true;
			boomboxRb.linearVelocity = Vector3.zero;
			boomboxRb.angularVelocity = Vector3.zero;
		}
		if (boomboxColliders != null)
		{
			Collider[] array = boomboxColliders;
			foreach (Collider val in array)
			{
				if ((Object)(object)val != (Object)null)
				{
					val.enabled = true;
				}
			}
		}
		handTransform = null;
		handPositionInitialized = false;
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Бумбокс положен!");
	}

	private void ApplyLitMaterials(GameObject boombox)
	{
		//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_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e8: Expected O, but got Unknown
		//IL_0108: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		Shader val = Shader.Find("Universal Render Pipeline/Lit");
		if ((Object)(object)val == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"URP/Lit не найден.");
			return;
		}
		Renderer[] componentsInChildren = boombox.GetComponentsInChildren<Renderer>(true);
		Dictionary<Material, Material> dictionary = new Dictionary<Material, Material>();
		Renderer[] array = componentsInChildren;
		foreach (Renderer val2 in array)
		{
			Material[] sharedMaterials = val2.sharedMaterials;
			for (int j = 0; j < sharedMaterials.Length; j++)
			{
				Material val3 = sharedMaterials[j];
				if ((Object)(object)val3 == (Object)null)
				{
					continue;
				}
				if (!dictionary.TryGetValue(val3, out var value))
				{
					Color val4 = Color.white;
					if (val3.HasProperty("_BaseColor"))
					{
						val4 = val3.GetColor("_BaseColor");
					}
					else if (val3.HasProperty("_Color"))
					{
						val4 = val3.GetColor("_Color");
					}
					value = new Material(val);
					((Object)value).name = ((Object)val3).name + "_URP_Lit";
					value.SetColor("_BaseColor", val4);
					value.SetFloat("_Metallic", 0f);
					value.SetFloat("_Smoothness", 0.35f);
					dictionary.Add(val3, value);
				}
				sharedMaterials[j] = value;
			}
			val2.sharedMaterials = sharedMaterials;
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)("Материалы URP/Lit применены: " + dictionary.Count));
	}
}