Decompiled source of AutoMusician v1.0.2

REPO_AutoMusician.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using Photon.Pun;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("REPO_AutoMusician")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("REPO_AutoMusician")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("3b97065c-7efe-4237-a4c4-4f995698c041")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace REPOssessed.MusicianMod;

[BepInPlugin("com.yourname.repo.automusician", "Auto Musician Mod", "1.0.2")]
public class AutoMusicianPlugin : BaseUnityPlugin
{
	private const int VK_E = 69;

	private bool wasEKeyPressed;

	private float lastToggleTime = -1f;

	public bool modEnabled = true;

	public bool isLooping = true;

	public bool lockPitchShift = true;

	public float loopInterval = 2f;

	public int keyOffset;

	private string[] songNames = new string[5];

	private string[] songContents = new string[5];

	private float[] songSpeeds = new float[5];

	public int currentSongIndex;

	private string loopIntervalInput = "2.0";

	private string keyOffsetInput = "0";

	private string speedInput = "0.22";

	private ConfigEntry<bool> cfgIsLooping;

	private ConfigEntry<bool> cfgLockPitchShift;

	private ConfigEntry<float> cfgLoopInterval;

	private ConfigEntry<int> cfgKeyOffset;

	private ConfigEntry<int> cfgCurrentSongIndex;

	private ConfigEntry<string>[] cfgSongNames = new ConfigEntry<string>[5];

	private ConfigEntry<float>[] cfgSongSpeeds = new ConfigEntry<float>[5];

	private ConfigEntry<string>[] cfgSongContents = new ConfigEntry<string>[5];

	private bool configDirty;

	private float configSaveTime;

	private bool isPlaying;

	private int currentNoteIndex;

	private float nextPlayTime;

	public bool showMenu;

	private PhysGrabObject lastGrabbedObject;

	private MusicalValuableLogic cachedInstrument;

	private PhotonView cachedInstrumentPv;

	private IDictionary cachedPlayedKeysDict;

	private float checkInstrumentTimer;

	private FieldInfo grabbedField;

	private FieldInfo grabbedObjField;

	private PropertyInfo grabbedObjProp;

	private FieldInfo currentlyPlayedKeysField;

	private MethodInfo rpcMethodInfo;

	private ParameterInfo[] rpcMethodParams;

	private int rpcNetworkParamCount = 2;

	private MethodInfo playKeyMethodInfo;

	private ParameterInfo[] playKeyMethodParams;

	private object[] cachedInvokeArgs;

	private GameObject localPlayerObject;

	private Rigidbody localPlayerRb;

	private List<Behaviour> disabledPlayerBehaviours = new List<Behaviour>();

	private readonly Dictionary<char, int> noteMapping = new Dictionary<char, int>
	{
		{ 'a', 24 },
		{ 'b', 26 },
		{ 'c', 28 },
		{ 'd', 29 },
		{ 'e', 31 },
		{ 'f', 33 },
		{ 'g', 35 },
		{ '1', 36 },
		{ '2', 38 },
		{ '3', 40 },
		{ '4', 41 },
		{ '5', 43 },
		{ '6', 45 },
		{ '7', 47 },
		{ 'A', 48 },
		{ 'B', 50 },
		{ 'C', 52 },
		{ 'D', 53 },
		{ 'E', 55 },
		{ 'F', 57 },
		{ 'G', 59 }
	};

	private Rect windowRect;

	private Vector2 scrollPosition = Vector2.zero;

	private bool stylesInitialized;

	private GUIStyle windowStyle;

	private GUIStyle tabNormalStyle;

	private GUIStyle tabActiveStyle;

	private GUIStyle resetBtnStyle;

	private GUIStyle editAreaStyle;

	private GUIStyle textAreaStyle;

	private GUIStyle labelStyle;

	private GUIStyle nameFieldStyle;

	private GUIStyle floatingTipStyle;

	private GUIStyle toggleStyle;

	private Texture2D texBlack;

	private Texture2D texSkyBlue;

	private Texture2D texDarkBlue;

	private Texture2D texDarkGrey;

	[DllImport("user32.dll")]
	private static extern short GetAsyncKeyState(int vKey);

	private void Awake()
	{
		try
		{
			Type typeFromHandle = typeof(PhysGrabber);
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
			grabbedField = typeFromHandle.GetField("grabbed", bindingAttr);
			grabbedObjField = typeFromHandle.GetField("grabbedPhysGrabObject", bindingAttr);
			grabbedObjProp = typeFromHandle.GetProperty("grabbedPhysGrabObject", bindingAttr);
			Type typeFromHandle2 = typeof(MusicalValuableLogic);
			currentlyPlayedKeysField = typeFromHandle2.GetField("currentlyPlayedKeys", bindingAttr);
			MethodInfo[] methods = typeFromHandle2.GetMethods(bindingAttr);
			foreach (MethodInfo methodInfo in methods)
			{
				if (methodInfo.Name == "MusicKeyPressedRPC")
				{
					rpcMethodInfo = methodInfo;
					rpcMethodParams = methodInfo.GetParameters();
					int num = 0;
					ParameterInfo[] array = rpcMethodParams;
					for (int j = 0; j < array.Length; j++)
					{
						if (array[j].ParameterType.Name != "PhotonMessageInfo")
						{
							num++;
						}
					}
					rpcNetworkParamCount = num;
				}
				else if (methodInfo.Name == "PlayKey")
				{
					playKeyMethodInfo = methodInfo;
					playKeyMethodParams = methodInfo.GetParameters();
				}
			}
			ParameterInfo[] array2 = playKeyMethodParams ?? rpcMethodParams;
			if (array2 != null)
			{
				cachedInvokeArgs = new object[array2.Length];
				for (int k = 0; k < array2.Length; k++)
				{
					Type parameterType = array2[k].ParameterType;
					cachedInvokeArgs[k] = (array2[k].HasDefaultValue ? array2[k].DefaultValue : (parameterType.IsValueType ? Activator.CreateInstance(parameterType) : null));
				}
			}
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Reflection Failed: " + ex.Message));
		}
		InitializeConfigAndLoad();
		((BaseUnityPlugin)this).Logger.LogInfo((object)"=====================================");
		((BaseUnityPlugin)this).Logger.LogInfo((object)"\ud83c\udfb5 Auto Musician V1.2.0 Loaded! (Zero-GC Optimized)");
		((BaseUnityPlugin)this).Logger.LogInfo((object)"=====================================");
	}

	private void GetDefaultSongs(out string[] defNames, out float[] defSpeeds, out string[] defContents)
	{
		defNames = new string[5];
		defSpeeds = new float[5];
		defContents = new string[5];
		defNames[0] = "Jingle Bells";
		defSpeeds[0] = 0.22f;
		defContents[0] = "3 3 3 0 3 3 3 0  3 5 1 2 3 0 0 0 \n4 4 4 4 4 3 3 3  3 2 2 3 2 0 5 0 \n3 3 3 0 3 3 3 0  3 5 1 2 3 0 0 0 \n4 4 4 4 4 3 3 3  5 5 4 2 1 0 0 0 \n\n5 3 2 1 e 0 0 0  e e 3 2 1 f 0 0 0 \nf 4 3 2 g 0 0 0  5 5 4 2 3 0 0 0 \n5 3 2 1 e 0 0 0  e e 3 2 1 f 0 0 0 \nf 4 3 2 5 5 5 5  6 5 4 2 1 0 5 0 \n\n3 3 3 0 3 3 3 0  3 5 1 2 3 0 0 0 \n4 4 4 4 4 3 3 3  3 2 2 3 2 0 5 0 \n3 3 3 0 3 3 3 0  3 5 1 2 3 0 0 0 \n4 4 4 4 4 3 3 3  5 5 4 2 1 0 0 0 ";
		defNames[1] = "Little Star";
		defSpeeds[1] = 0.5f;
		defContents[1] = "1 1 5 5 6 6 5 0\n 4 4 3 3 2 2 1 0 \n5 5 4 4 3 3 2 0 \n5 5 4 4 3 3 2 0 \n1 1 5 5 6 6 5 0 \n4 4 3 3 2 2 1 0 ";
		defNames[2] = "Funny Circus";
		defSpeeds[2] = 0.13f;
		defContents[2] = "5 5 5 0 3 3 3 0  5 5 3 3 1 0 0 0 \n2 2 2 0 4 4 4 0  6 6 4 4 3 0 0 0 \n5 5 5 0 3 3 3 0  5 5 3 3 1 0 0 0 \n2 2 4 4 5 5 7 7  A 0 A 0 A 0 0 0 \n\na 0 A 0 a 0 A 0  b 0 B 0 b 0 B 0 \nc 0 C 0 c 0 C 0  d 0 D 0 d 0 D 0 \nE E D D C C B B  A A 7 7 6 6 5 5 \n4 4 3 3 2 2 1 1  g g f f e 0 0 0 \n\n1 2 3 4 5 6 7 A  B C D E F G F E \nD C B A 7 6 5 4  3 2 1 g f e d c \nc d e f g 1 2 3  4 5 6 7 A B C D \nE 0 C 0 A 0 6 0  4 0 2 0 a 0 0 0 \n\n1 0 1 0 1 0 0 0  5 0 5 0 5 0 0 0 \nA 0 G 0 F 0 E 0  D 0 C 0 B 0 A 0 \n5 0 0 0 5 0 0 0  C 0 0 0 0 0 0 0 ";
		for (int i = 3; i < 5; i++)
		{
			defNames[i] = $"Custom Song {i + 1}";
			defSpeeds[i] = 0.25f;
			defContents[i] = "";
		}
	}

	private string EncodeMultiline(string text)
	{
		if (string.IsNullOrEmpty(text))
		{
			return "";
		}
		return text.Replace("\r\n", "\n").Replace("\r", "\n").Replace("\n", "<br>");
	}

	private string DecodeMultiline(string saved)
	{
		if (string.IsNullOrEmpty(saved))
		{
			return "";
		}
		return saved.Replace("<br>", "\n");
	}

	private void SyncInputStringsFromValues()
	{
		loopIntervalInput = loopInterval.ToString("F1");
		keyOffsetInput = keyOffset.ToString();
		speedInput = songSpeeds[currentSongIndex].ToString("F2");
	}

	private void InitializeConfigAndLoad()
	{
		GetDefaultSongs(out var defNames, out var defSpeeds, out var defContents);
		cfgIsLooping = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "IsLooping", true, "是否循环播放曲目");
		cfgLockPitchShift = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "LockPitchShift", true, "是否锁定防滑音跑调");
		cfgLoopInterval = ((BaseUnityPlugin)this).Config.Bind<float>("General", "LoopInterval", 2f, "循环播放间隔秒数");
		cfgKeyOffset = ((BaseUnityPlugin)this).Config.Bind<int>("General", "KeyOffset", 0, "全局音高微调偏移量");
		cfgCurrentSongIndex = ((BaseUnityPlugin)this).Config.Bind<int>("General", "CurrentSongIndex", 0, "上次选中的歌单序号");
		isLooping = cfgIsLooping.Value;
		lockPitchShift = cfgLockPitchShift.Value;
		loopInterval = Mathf.Clamp(cfgLoopInterval.Value, 0f, 10f);
		keyOffset = Mathf.Clamp(cfgKeyOffset.Value, -48, 48);
		currentSongIndex = Mathf.Clamp(cfgCurrentSongIndex.Value, 0, 4);
		for (int i = 0; i < 5; i++)
		{
			string text = $"Song_{i + 1}";
			cfgSongNames[i] = ((BaseUnityPlugin)this).Config.Bind<string>(text, "Name", defNames[i], $"歌单 {i + 1} 名称");
			cfgSongSpeeds[i] = ((BaseUnityPlugin)this).Config.Bind<float>(text, "Speed", defSpeeds[i], $"歌单 {i + 1} 播放速度");
			cfgSongContents[i] = ((BaseUnityPlugin)this).Config.Bind<string>(text, "Content", EncodeMultiline(defContents[i]), $"歌单 {i + 1} 曲谱内容");
			songNames[i] = cfgSongNames[i].Value;
			songSpeeds[i] = Mathf.Clamp(cfgSongSpeeds[i].Value, 0.05f, 2f);
			songContents[i] = DecodeMultiline(cfgSongContents[i].Value);
		}
		SyncInputStringsFromValues();
	}

	private void MarkConfigDirty()
	{
		configDirty = true;
		configSaveTime = Time.unscaledTime + 1.5f;
	}

	public void SaveAllToConfig()
	{
		if (cfgIsLooping != null)
		{
			configDirty = false;
			cfgIsLooping.Value = isLooping;
			cfgLockPitchShift.Value = lockPitchShift;
			cfgLoopInterval.Value = loopInterval;
			cfgKeyOffset.Value = keyOffset;
			cfgCurrentSongIndex.Value = currentSongIndex;
			for (int i = 0; i < 5; i++)
			{
				cfgSongNames[i].Value = songNames[i];
				cfgSongSpeeds[i].Value = songSpeeds[i];
				cfgSongContents[i].Value = EncodeMultiline(songContents[i]);
			}
			((BaseUnityPlugin)this).Config.Save();
		}
	}

	public void ResetToDefaults()
	{
		GetDefaultSongs(out var defNames, out var defSpeeds, out var defContents);
		isLooping = true;
		lockPitchShift = true;
		loopInterval = 2f;
		keyOffset = 0;
		currentSongIndex = 0;
		for (int i = 0; i < 5; i++)
		{
			songNames[i] = defNames[i];
			songSpeeds[i] = defSpeeds[i];
			songContents[i] = defContents[i];
		}
		SyncInputStringsFromValues();
		SaveAllToConfig();
	}

	private void OnApplicationQuit()
	{
		if (configDirty)
		{
			SaveAllToConfig();
		}
	}

	private void OnDestroy()
	{
		if (configDirty)
		{
			SaveAllToConfig();
		}
	}

	private void ToggleMenu()
	{
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		showMenu = !showMenu;
		if (showMenu)
		{
			SyncInputStringsFromValues();
			windowRect = new Rect((float)((Screen.width - 900) / 2), (float)((Screen.height - 640) / 2), 900f, 640f);
			localPlayerObject = GameObject.FindGameObjectWithTag("Player");
			if (!((Object)(object)localPlayerObject != (Object)null))
			{
				return;
			}
			localPlayerRb = localPlayerObject.GetComponent<Rigidbody>();
			disabledPlayerBehaviours.Clear();
			Behaviour[] componentsInChildren = localPlayerObject.GetComponentsInChildren<Behaviour>(true);
			foreach (Behaviour val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					string text = ((object)val).GetType().Name.ToLower();
					if ((text.Contains("move") || text.Contains("controller") || text.Contains("input") || text.Contains("look") || text.Contains("fall")) && val.enabled)
					{
						val.enabled = false;
						disabledPlayerBehaviours.Add(val);
					}
				}
			}
			return;
		}
		GUIUtility.keyboardControl = 0;
		if (configDirty)
		{
			SaveAllToConfig();
		}
		foreach (Behaviour disabledPlayerBehaviour in disabledPlayerBehaviours)
		{
			if ((Object)(object)disabledPlayerBehaviour != (Object)null)
			{
				disabledPlayerBehaviour.enabled = true;
			}
		}
		disabledPlayerBehaviours.Clear();
		localPlayerRb = null;
		if ((Object)(object)PhysGrabber.instance != (Object)null)
		{
			Cursor.lockState = (CursorLockMode)1;
			Cursor.visible = false;
		}
	}

	private void TogglePlayState()
	{
		if (!(Time.unscaledTime - lastToggleTime < 0.25f))
		{
			lastToggleTime = Time.unscaledTime;
			isPlaying = !isPlaying;
			if (isPlaying)
			{
				currentNoteIndex = 0;
				nextPlayTime = Time.time;
			}
		}
	}

	private bool CheckEKeyDownReliable()
	{
		if (!Application.isFocused)
		{
			wasEKeyPressed = false;
			return false;
		}
		bool flag = (GetAsyncKeyState(69) & 0x8000) != 0;
		bool num = flag && !wasEKeyPressed;
		wasEKeyPressed = flag;
		bool keyDown = Input.GetKeyDown((KeyCode)101);
		return num || keyDown;
	}

	private void Update()
	{
		//IL_004d: 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)
		if (!modEnabled)
		{
			return;
		}
		if (configDirty && Time.unscaledTime >= configSaveTime)
		{
			SaveAllToConfig();
		}
		if (showMenu && (Object)(object)localPlayerRb != (Object)null && !localPlayerRb.isKinematic)
		{
			localPlayerRb.linearVelocity = Vector3.zero;
			localPlayerRb.angularVelocity = Vector3.zero;
		}
		if (Time.time > checkInstrumentTimer)
		{
			checkInstrumentTimer = Time.time + 0.25f;
			UpdateHeldInstrumentFast();
		}
		if ((Object)(object)cachedInstrument != (Object)null)
		{
			if (!showMenu && CheckEKeyDownReliable())
			{
				TogglePlayState();
			}
			if (isPlaying && Time.time >= nextPlayTime)
			{
				PlayNextNote(cachedInstrument);
			}
		}
		else
		{
			wasEKeyPressed = false;
			if (isPlaying)
			{
				isPlaying = false;
			}
		}
	}

	private void LateUpdate()
	{
		if (showMenu && (Object)(object)PhysGrabber.instance != (Object)null)
		{
			Cursor.visible = true;
			Cursor.lockState = (CursorLockMode)0;
		}
	}

	private void UpdateHeldInstrumentFast()
	{
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Expected O, but got Unknown
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Expected O, but got Unknown
		if ((Object)(object)PhysGrabber.instance == (Object)null || grabbedField == null)
		{
			ClearInstrumentCache();
			return;
		}
		if (!(bool)grabbedField.GetValue(PhysGrabber.instance))
		{
			ClearInstrumentCache();
			return;
		}
		PhysGrabObject val = null;
		if (grabbedObjField != null)
		{
			val = (PhysGrabObject)grabbedObjField.GetValue(PhysGrabber.instance);
		}
		else if (grabbedObjProp != null)
		{
			val = (PhysGrabObject)grabbedObjProp.GetValue(PhysGrabber.instance, null);
		}
		if ((Object)(object)val == (Object)(object)lastGrabbedObject)
		{
			return;
		}
		lastGrabbedObject = val;
		cachedInstrument = null;
		cachedInstrumentPv = null;
		cachedPlayedKeysDict = null;
		if (!((Object)(object)val != (Object)null))
		{
			return;
		}
		string text = ((Object)val).name.ToLower();
		if (!text.Contains("guitar") && !text.Contains("piano") && !text.Contains("harp") && !text.Contains("banjo"))
		{
			return;
		}
		MusicalValuableLogic val2 = ((Component)val).GetComponent<MusicalValuableLogic>();
		if ((Object)(object)val2 == (Object)null)
		{
			val2 = ((Component)val).GetComponentInChildren<MusicalValuableLogic>(true);
		}
		if ((Object)(object)val2 != (Object)null)
		{
			cachedInstrument = val2;
			cachedInstrumentPv = ((Component)val2).GetComponent<PhotonView>();
			if (currentlyPlayedKeysField != null)
			{
				cachedPlayedKeysDict = currentlyPlayedKeysField.GetValue(val2) as IDictionary;
			}
		}
	}

	private void ClearInstrumentCache()
	{
		lastGrabbedObject = null;
		cachedInstrument = null;
		cachedInstrumentPv = null;
		cachedPlayedKeysDict = null;
	}

	private int CalculateTargetKey(MusicalValuableLogic instrument, int rawKey)
	{
		int num = ((instrument.musicKeys != null && instrument.musicKeys.Count > 0) ? instrument.musicKeys.Count : 18);
		int num2 = Mathf.Max(1, instrument.numberOfOctaves);
		int num3 = num * num2;
		int num4 = rawKey;
		if (num3 <= 36)
		{
			num4 -= 24;
		}
		num4 += keyOffset;
		return Mathf.Clamp(num4, 0, Mathf.Max(0, num3 - 1));
	}

	private void PlayNextNote(MusicalValuableLogic instrument)
	{
		string text = songContents[currentSongIndex];
		if (currentNoteIndex >= text.Length)
		{
			if (isLooping)
			{
				currentNoteIndex = 0;
				nextPlayTime = Time.time + loopInterval;
			}
			else
			{
				isPlaying = false;
			}
			return;
		}
		while (currentNoteIndex < text.Length)
		{
			char c = text[currentNoteIndex];
			currentNoteIndex++;
			if (c != ' ' && c != ',' && c != '\n' && c != '\r')
			{
				nextPlayTime = Time.time + songSpeeds[currentSongIndex];
				if (c != '0' && noteMapping.TryGetValue(c, out var value))
				{
					int targetKey = CalculateTargetKey(instrument, value);
					TriggerNoteZeroGC(instrument, targetKey);
				}
				break;
			}
		}
	}

	private void TriggerNoteZeroGC(MusicalValuableLogic instrument, int targetKey)
	{
		try
		{
			cachedPlayedKeysDict?.Clear();
			bool hasPitchShift = instrument.hasPitchShift;
			if (lockPitchShift)
			{
				instrument.hasPitchShift = false;
			}
			if ((Object)(object)cachedInstrumentPv != (Object)null && PhotonNetwork.IsConnected && PhotonNetwork.InRoom)
			{
				if (rpcNetworkParamCount == 1)
				{
					cachedInstrumentPv.RPC("MusicKeyPressedRPC", (RpcTarget)0, new object[1] { targetKey });
				}
				else
				{
					int num = -1;
					if (lockPitchShift)
					{
						num = cachedInstrumentPv.ViewID;
					}
					else if ((Object)(object)PhysGrabber.instance != (Object)null)
					{
						PhotonView component = ((Component)PhysGrabber.instance).GetComponent<PhotonView>();
						if ((Object)(object)component != (Object)null)
						{
							num = component.ViewID;
						}
					}
					cachedInstrumentPv.RPC("MusicKeyPressedRPC", (RpcTarget)0, new object[2] { targetKey, num });
				}
			}
			else if (playKeyMethodInfo != null && cachedInvokeArgs != null)
			{
				if (cachedInvokeArgs.Length != 0)
				{
					cachedInvokeArgs[0] = targetKey;
				}
				if (cachedInvokeArgs.Length > 1 && playKeyMethodParams[1].ParameterType == typeof(int))
				{
					cachedInvokeArgs[1] = -1;
				}
				playKeyMethodInfo.Invoke(instrument, cachedInvokeArgs);
			}
			else if (rpcMethodInfo != null && cachedInvokeArgs != null)
			{
				if (cachedInvokeArgs.Length != 0)
				{
					cachedInvokeArgs[0] = targetKey;
				}
				if (cachedInvokeArgs.Length > 1 && rpcMethodParams[1].ParameterType == typeof(int))
				{
					cachedInvokeArgs[1] = -1;
				}
				rpcMethodInfo.Invoke(instrument, cachedInvokeArgs);
			}
			if (lockPitchShift)
			{
				cachedPlayedKeysDict?.Clear();
				instrument.hasPitchShift = hasPitchShift;
			}
		}
		catch (Exception arg)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)$"[AutoMusician] PlayKey Exception: {arg}");
		}
	}

	private void OnGUI()
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Invalid comparison between Unknown and I4
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Invalid comparison between Unknown and I4
		//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e8: Expected O, but got Unknown
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e8: 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)
		if (!modEnabled)
		{
			return;
		}
		if ((int)Event.current.type == 4 && (int)Event.current.keyCode == 284 && Event.current.character == '\0')
		{
			ToggleMenu();
			Event.current.Use();
		}
		else if (!((Object)(object)cachedInstrument == (Object)null) || showMenu)
		{
			InitializeStyles();
			if ((Object)(object)cachedInstrument != (Object)null && !showMenu && !isPlaying)
			{
				GUI.Label(new Rect((float)(Screen.width / 2 - 200), (float)(Screen.height - 220), 400f, 50f), "[E] Play Auto-Music", floatingTipStyle);
			}
			if (showMenu)
			{
				windowRect = GUI.Window(999, windowRect, new WindowFunction(DrawModernMenu), "Auto Musician Menu", windowStyle);
			}
		}
	}

	private void DrawModernMenu(int windowID)
	{
		//IL_048d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0499: Unknown result type (might be due to invalid IL or missing references)
		//IL_049e: Unknown result type (might be due to invalid IL or missing references)
		GUILayout.Space(15f);
		GUI.changed = false;
		GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
		GUILayout.BeginHorizontal((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(680f) });
		isLooping = GUILayout.Toggle(isLooping, " Loop Song\n<size=12>【循环播放】</size>", toggleStyle, Array.Empty<GUILayoutOption>());
		GUILayout.Space(12f);
		lockPitchShift = GUILayout.Toggle(lockPitchShift, " Lock Pitch\n<size=12>【防滑音跑调】</size>", toggleStyle, Array.Empty<GUILayoutOption>());
		GUILayout.Space(12f);
		GUILayout.Label("Delay(s):\n<size=12>【循环间隔】</size>", labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(85f) });
		GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
		GUILayout.Space(5f);
		loopIntervalInput = GUILayout.TextField(loopIntervalInput, nameFieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(55f) });
		if (float.TryParse(loopIntervalInput, out var result))
		{
			loopInterval = Mathf.Clamp(result, 0f, 10f);
		}
		GUILayout.EndVertical();
		GUILayout.Space(12f);
		GUILayout.Label("Offset:\n<size=12>【音调微调】</size>", labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) });
		GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
		GUILayout.Space(5f);
		GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
		if (GUILayout.Button("-", tabNormalStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
		{
			GUILayout.Width(28f),
			GUILayout.Height(28f)
		}))
		{
			keyOffset = Mathf.Clamp(keyOffset - 1, -48, 48);
			keyOffsetInput = keyOffset.ToString();
			MarkConfigDirty();
		}
		keyOffsetInput = GUILayout.TextField(keyOffsetInput, nameFieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(45f) });
		if (int.TryParse(keyOffsetInput, out var result2))
		{
			keyOffset = Mathf.Clamp(result2, -48, 48);
		}
		if (GUILayout.Button("+", tabNormalStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
		{
			GUILayout.Width(28f),
			GUILayout.Height(28f)
		}))
		{
			keyOffset = Mathf.Clamp(keyOffset + 1, -48, 48);
			keyOffsetInput = keyOffset.ToString();
			MarkConfigDirty();
		}
		GUILayout.EndHorizontal();
		GUILayout.EndVertical();
		GUILayout.EndHorizontal();
		GUILayout.FlexibleSpace();
		if (GUILayout.Button("Reset Defaults\n<size=12>【重置默认】</size>", resetBtnStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
		{
			GUILayout.Width(155f),
			GUILayout.Height(50f)
		}))
		{
			GUIUtility.keyboardControl = 0;
			ResetToDefaults();
		}
		GUILayout.EndHorizontal();
		GUILayout.Space(15f);
		GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
		for (int i = 0; i < 5; i++)
		{
			GUIStyle val = ((currentSongIndex == i) ? tabActiveStyle : tabNormalStyle);
			if (GUILayout.Button($"{i + 1}. {songNames[i]}", val, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(45f) }))
			{
				GUIUtility.keyboardControl = 0;
				currentSongIndex = i;
				SyncInputStringsFromValues();
				MarkConfigDirty();
			}
		}
		GUILayout.EndHorizontal();
		GUILayout.BeginVertical(editAreaStyle, Array.Empty<GUILayoutOption>());
		GUILayout.Space(10f);
		GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
		GUILayout.Label("Speed:\n<size=12>【播放速度】</size>", labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) });
		GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
		GUILayout.Space(5f);
		speedInput = GUILayout.TextField(speedInput, nameFieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) });
		if (float.TryParse(speedInput, out var result3))
		{
			songSpeeds[currentSongIndex] = Mathf.Clamp(result3, 0.05f, 2f);
		}
		GUILayout.EndVertical();
		GUILayout.FlexibleSpace();
		GUILayout.Label("Rename:\n<size=12>【歌单命名】</size>", labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) });
		GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
		GUILayout.Space(5f);
		songNames[currentSongIndex] = GUILayout.TextField(songNames[currentSongIndex], nameFieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(200f) });
		GUILayout.EndVertical();
		GUILayout.EndHorizontal();
		GUILayout.Space(10f);
		scrollPosition = GUILayout.BeginScrollView(scrollPosition, false, true, Array.Empty<GUILayoutOption>());
		songContents[currentSongIndex] = GUILayout.TextArea(songContents[currentSongIndex], textAreaStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandHeight(true) });
		GUILayout.EndScrollView();
		GUILayout.EndVertical();
		if (GUI.changed)
		{
			MarkConfigDirty();
		}
		GUI.DragWindow();
	}

	private void InitializeStyles()
	{
		//IL_002f: 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_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: 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_00cf: Expected O, but got Unknown
		//IL_0106: Unknown result type (might be due to invalid IL or missing references)
		//IL_0137: Unknown result type (might be due to invalid IL or missing references)
		//IL_0141: Expected O, but got Unknown
		//IL_014c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0151: Unknown result type (might be due to invalid IL or missing references)
		//IL_015d: Expected O, but got Unknown
		//IL_0168: Unknown result type (might be due to invalid IL or missing references)
		//IL_0196: Unknown result type (might be due to invalid IL or missing references)
		//IL_019b: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a7: Expected O, but got Unknown
		//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_0206: Expected O, but got Unknown
		//IL_024c: Unknown result type (might be due to invalid IL or missing references)
		//IL_027a: Unknown result type (might be due to invalid IL or missing references)
		//IL_027f: Unknown result type (might be due to invalid IL or missing references)
		//IL_028b: Expected O, but got Unknown
		//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e3: Expected O, but got Unknown
		//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f4: Expected O, but got Unknown
		//IL_0315: Unknown result type (might be due to invalid IL or missing references)
		//IL_0320: Unknown result type (might be due to invalid IL or missing references)
		//IL_032a: Expected O, but got Unknown
		//IL_034e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0358: Expected O, but got Unknown
		//IL_0363: Unknown result type (might be due to invalid IL or missing references)
		//IL_036d: Expected O, but got Unknown
		//IL_0378: Unknown result type (might be due to invalid IL or missing references)
		//IL_0382: Expected O, but got Unknown
		//IL_03a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b0: Expected O, but got Unknown
		//IL_03d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0400: Expected O, but got Unknown
		//IL_0417: Unknown result type (might be due to invalid IL or missing references)
		//IL_0421: Expected O, but got Unknown
		//IL_0465: Unknown result type (might be due to invalid IL or missing references)
		if (!stylesInitialized || !((Object)(object)texBlack != (Object)null))
		{
			texBlack = MakeTex(2, 2, new Color(0.12f, 0.12f, 0.12f, 0.95f));
			texDarkGrey = MakeTex(2, 2, new Color(0.18f, 0.18f, 0.18f, 1f));
			texSkyBlue = MakeTex(2, 2, new Color(0.53f, 0.81f, 0.92f, 1f));
			texDarkBlue = MakeTex(2, 2, new Color(0.25f, 0.65f, 0.85f, 1f));
			windowStyle = new GUIStyle(GUI.skin.window)
			{
				richText = true
			};
			windowStyle.normal.background = texBlack;
			windowStyle.onNormal.background = texBlack;
			windowStyle.normal.textColor = Color.white;
			windowStyle.fontSize = 22;
			windowStyle.fontStyle = (FontStyle)1;
			windowStyle.padding = new RectOffset(15, 15, 35, 15);
			labelStyle = new GUIStyle(GUI.skin.label)
			{
				richText = true
			};
			labelStyle.normal.textColor = Color.white;
			labelStyle.fontSize = 20;
			labelStyle.fontStyle = (FontStyle)1;
			toggleStyle = new GUIStyle(GUI.skin.toggle)
			{
				richText = true
			};
			toggleStyle.normal.textColor = Color.white;
			toggleStyle.onNormal.textColor = Color.white;
			toggleStyle.fontSize = 20;
			toggleStyle.fontStyle = (FontStyle)1;
			resetBtnStyle = new GUIStyle(GUI.skin.button)
			{
				richText = true
			};
			resetBtnStyle.normal.background = texDarkGrey;
			resetBtnStyle.hover.background = texBlack;
			resetBtnStyle.normal.textColor = new Color(1f, 0.3f, 0.3f);
			resetBtnStyle.fontSize = 18;
			resetBtnStyle.fontStyle = (FontStyle)1;
			tabNormalStyle = new GUIStyle(GUI.skin.button)
			{
				richText = true
			};
			tabNormalStyle.normal.background = texSkyBlue;
			tabNormalStyle.normal.textColor = Color.black;
			tabNormalStyle.fontSize = 18;
			tabNormalStyle.fontStyle = (FontStyle)1;
			tabNormalStyle.margin = new RectOffset(2, 2, 0, 0);
			tabActiveStyle = new GUIStyle(tabNormalStyle);
			tabActiveStyle.normal.background = texDarkBlue;
			tabActiveStyle.normal.textColor = Color.white;
			editAreaStyle = new GUIStyle();
			editAreaStyle.normal.background = texDarkGrey;
			editAreaStyle.padding = new RectOffset(15, 15, 15, 15);
			editAreaStyle.margin = new RectOffset(0, 0, 10, 0);
			nameFieldStyle = new GUIStyle(GUI.skin.textField);
			nameFieldStyle.fontSize = 18;
			nameFieldStyle.fontStyle = (FontStyle)1;
			textAreaStyle = new GUIStyle(GUI.skin.textArea);
			textAreaStyle.normal.background = texBlack;
			textAreaStyle.normal.textColor = Color.white;
			textAreaStyle.fontSize = 20;
			textAreaStyle.padding = new RectOffset(12, 12, 12, 12);
			textAreaStyle.wordWrap = true;
			floatingTipStyle = new GUIStyle(GUI.skin.label);
			floatingTipStyle.alignment = (TextAnchor)4;
			floatingTipStyle.fontSize = 28;
			floatingTipStyle.fontStyle = (FontStyle)1;
			floatingTipStyle.normal.textColor = new Color(1f, 0.6f, 0f, 1f);
			stylesInitialized = true;
		}
	}

	private Texture2D MakeTex(int width, int height, Color col)
	{
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//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)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Expected O, but got Unknown
		Color[] array = (Color[])(object)new Color[width * height];
		for (int i = 0; i < array.Length; i++)
		{
			array[i] = col;
		}
		Texture2D val = new Texture2D(width, height)
		{
			hideFlags = (HideFlags)61
		};
		val.SetPixels(array);
		val.Apply();
		return val;
	}
}