Decompiled source of BetterVolume v1.0.0

Antro.BetterVolume.dll

Decompiled 2 hours ago
using System;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("Antro.BetterVolume")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Antro.BetterVolume")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0.0")]
[assembly: AssemblyProduct("Antro.BetterVolume")]
[assembly: AssemblyTitle("Antro.BetterVolume")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace BetterVolume
{
	[BepInPlugin("BetterVolume", "BetterVolume", "1.0.9")]
	public class BetterVolumePlugin : BaseUnityPlugin
	{
		public static ManualLogSource Log;

		static BetterVolumePlugin()
		{
			Console.WriteLine("[BetterVolume] Static Constructor: Assembly loaded into Mono context.");
		}

		private void Awake()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Expected O, but got Unknown
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Log.LogInfo((object)"BetterVolume Awake() started execution.");
			try
			{
				Harmony val = new Harmony("BetterVolume");
				MethodInfo methodInfo = AccessTools.PropertySetter(AccessTools.TypeByName("Dissonance.RemoteVoicePlayerState"), "Volume");
				if (methodInfo != null)
				{
					MethodInfo methodInfo2 = AccessTools.Method(typeof(RemoteVoicePlayerStateVolumePatch), "Prefix", (Type[])null, (Type[])null);
					val.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Log.LogInfo((object)"Successfully patched RemoteVoicePlayerState.Volume.");
				}
				else
				{
					Log.LogError((object)"Could not find Dissonance.RemoteVoicePlayerState.Volume property setter!");
				}
				MethodInfo methodInfo3 = AccessTools.Method(AccessTools.TypeByName("IngamePlayerListElement"), "Start", (Type[])null, (Type[])null);
				if (methodInfo3 != null)
				{
					MethodInfo methodInfo4 = AccessTools.Method(typeof(IngamePlayerListElementStartPatch), "Postfix", (Type[])null, (Type[])null);
					val.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, new HarmonyMethod(methodInfo4), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Log.LogInfo((object)"Successfully patched IngamePlayerListElement.Start.");
				}
				else
				{
					Log.LogError((object)"Could not find IngamePlayerListElement.Start method!");
				}
				Log.LogInfo((object)"BetterVolume patches initialized successfully.");
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Failed to initialize BetterVolume: " + ex.ToString()));
			}
		}
	}
	public static class RemoteVoicePlayerStateVolumePatch
	{
		public static bool Prefix(object __instance, float value)
		{
			try
			{
				float num = Mathf.Clamp(value, 0f, 100f);
				PropertyInfo propertyInfo = AccessTools.Property(__instance.GetType(), "PlaybackInternal");
				if (propertyInfo != null)
				{
					object value2 = propertyInfo.GetValue(__instance);
					if (value2 != null)
					{
						PropertyInfo propertyInfo2 = AccessTools.Property(value2.GetType(), "PlaybackVolume");
						if (propertyInfo2 != null)
						{
							propertyInfo2.SetValue(value2, num);
						}
					}
				}
				PropertyInfo propertyInfo3 = AccessTools.Property(__instance.GetType(), "IsLocallyMuted");
				PropertyInfo propertyInfo4 = AccessTools.Property(__instance.GetType(), "Name");
				string text = ((propertyInfo4 != null) ? (propertyInfo4.GetValue(__instance) as string) : "Unknown");
				if (propertyInfo3 != null)
				{
					bool flag = (bool)propertyInfo3.GetValue(__instance);
					if (num <= 0.001f)
					{
						if (!flag)
						{
							propertyInfo3.SetValue(__instance, true);
							BetterVolumePlugin.Log.LogInfo((object)("Player " + text + " was forced to MUTED state because volume is 0."));
						}
					}
					else if (flag)
					{
						propertyInfo3.SetValue(__instance, false);
						BetterVolumePlugin.Log.LogInfo((object)("Player " + text + " was UNMUTED because volume is above 0."));
					}
				}
			}
			catch (Exception ex)
			{
				BetterVolumePlugin.Log.LogError((object)("Error in RemoteVoicePlayerStateVolumePatch: " + ex.ToString()));
			}
			return false;
		}
	}
	public static class IngamePlayerListElementStartPatch
	{
		public static void Postfix(MonoBehaviour __instance)
		{
			try
			{
				BetterVolumePlugin.Log.LogInfo((object)"IngamePlayerListElement.Start Postfix triggered dynamically.");
				Component component = ((Component)__instance).GetComponent("SliderUGUI");
				if ((Object)(object)component == (Object)null)
				{
					BetterVolumePlugin.Log.LogWarning((object)"SliderUGUI component not found on IngamePlayerListElement.");
					return;
				}
				AccessTools.Property(((object)component).GetType(), "MinValue")?.SetValue(component, 0f);
				AccessTools.Property(((object)component).GetType(), "MaxValue")?.SetValue(component, 5f);
				AccessTools.Field(((object)component).GetType(), "StepSize")?.SetValue(component, 0.05f);
				AccessTools.Field(((object)component).GetType(), "ValueFormat")?.SetValue(component, "{0:0%}");
				FieldInfo fieldInfo = AccessTools.Field(((object)component).GetType(), "Slider");
				if (fieldInfo != null)
				{
					object value = fieldInfo.GetValue(component);
					if (value != null)
					{
						AccessTools.Property(value.GetType(), "minValue")?.SetValue(value, 0f);
						AccessTools.Property(value.GetType(), "maxValue")?.SetValue(value, 5f);
					}
				}
				BetterVolumePlugin.Log.LogInfo((object)"SliderUGUI values modified successfully via reflection.");
				CreateInputFieldForSlider(component);
			}
			catch (Exception ex)
			{
				BetterVolumePlugin.Log.LogError((object)("Error in IngamePlayerListElementStartPatch: " + ex.ToString()));
			}
		}

		private static void CreateInputFieldForSlider(Component sliderComponent)
		{
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Expected O, but got Unknown
			//IL_028d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0257: Unknown result type (might be due to invalid IL or missing references)
			//IL_0266: Unknown result type (might be due to invalid IL or missing references)
			//IL_0275: Unknown result type (might be due to invalid IL or missing references)
			//IL_02df: Unknown result type (might be due to invalid IL or missing references)
			//IL_031e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0325: Expected O, but got Unknown
			//IL_0365: Unknown result type (might be due to invalid IL or missing references)
			//IL_036c: Expected O, but got Unknown
			//IL_03e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0467: Unknown result type (might be due to invalid IL or missing references)
			//IL_0495: Unknown result type (might be due to invalid IL or missing references)
			//IL_049a: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ab: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			try
			{
				num = 1;
				object? obj = AccessTools.Field(((object)sliderComponent).GetType(), "ValueTf")?.GetValue(sliderComponent);
				TextMeshProUGUI val = (TextMeshProUGUI)((obj is TextMeshProUGUI) ? obj : null);
				object? obj2 = AccessTools.Field(((object)sliderComponent).GetType(), "TextTf")?.GetValue(sliderComponent);
				TextMeshProUGUI val2 = (TextMeshProUGUI)((obj2 is TextMeshProUGUI) ? obj2 : null);
				if ((Object)(object)val == (Object)null)
				{
					BetterVolumePlugin.Log.LogWarning((object)"ValueTf was null on SliderUGUI. Searching in children...");
					TextMeshProUGUI[] componentsInChildren = sliderComponent.GetComponentsInChildren<TextMeshProUGUI>(true);
					TextMeshProUGUI[] array = componentsInChildren;
					foreach (TextMeshProUGUI val3 in array)
					{
						if ((Object)(object)val3 != (Object)(object)val2 && (((Object)val3).name.ToLower().Contains("value") || ((Object)val3).name.ToLower().Contains("percent") || ((Object)val3).name.ToLower().Contains("val")))
						{
							val = val3;
							break;
						}
					}
					if ((Object)(object)val == (Object)null && componentsInChildren.Length > 1)
					{
						TextMeshProUGUI[] array2 = componentsInChildren;
						foreach (TextMeshProUGUI val4 in array2)
						{
							if ((Object)(object)val4 != (Object)(object)val2)
							{
								val = val4;
								break;
							}
						}
					}
				}
				if ((Object)(object)val == (Object)null)
				{
					BetterVolumePlugin.Log.LogError((object)"Could not find any suitable TextMeshProUGUI for volume percentage.");
					return;
				}
				BetterVolumePlugin.Log.LogInfo((object)("Found percentage text component: " + ((Object)((Component)val).gameObject).name));
				num = 2;
				Color savedOriginalColor = ((Graphic)val).color;
				((Component)val).gameObject.SetActive(false);
				num = 3;
				GameObject val5 = new GameObject("VolumeInputField", new Type[1] { typeof(RectTransform) });
				val5.transform.SetParent(((TMP_Text)val).transform.parent, false);
				num = 4;
				RectTransform component = val5.GetComponent<RectTransform>();
				RectTransform rectTransform = ((TMP_Text)val).rectTransform;
				if ((Object)(object)rectTransform != (Object)null)
				{
					component.anchorMin = rectTransform.anchorMin;
					component.anchorMax = rectTransform.anchorMax;
					component.anchoredPosition = rectTransform.anchoredPosition;
				}
				component.sizeDelta = new Vector2(60f, 30f);
				num = 5;
				Sprite roundedSprite = Resources.GetBuiltinResource<Sprite>("UI/Skin/InputFieldBackground.psd") ?? Resources.GetBuiltinResource<Sprite>("UI/Skin/UISprite.psd");
				Image bg = val5.AddComponent<Image>();
				((Graphic)bg).color = new Color(0f, 0f, 0f, 0f);
				bg.sprite = null;
				((Graphic)bg).raycastTarget = true;
				num = 6;
				GameObject val6 = new GameObject("Text Area", new Type[1] { typeof(RectTransform) });
				val6.transform.SetParent(val5.transform, false);
				RectTransform component2 = val6.GetComponent<RectTransform>();
				component2.anchorsToFillParent();
				num = 7;
				GameObject val7 = new GameObject("Text", new Type[1] { typeof(RectTransform) });
				val7.transform.SetParent(val6.transform, false);
				RectTransform component3 = val7.GetComponent<RectTransform>();
				component3.anchorsToFillParent();
				num = 8;
				TextMeshProUGUI textComponent = val7.AddComponent<TextMeshProUGUI>();
				if ((Object)(object)((TMP_Text)val).font != (Object)null)
				{
					((TMP_Text)textComponent).font = ((TMP_Text)val).font;
				}
				((TMP_Text)textComponent).fontSize = ((TMP_Text)val).fontSize;
				((Graphic)textComponent).color = savedOriginalColor;
				((TMP_Text)textComponent).alignment = ((TMP_Text)val).alignment;
				((Graphic)textComponent).raycastTarget = false;
				num = 9;
				TMP_InputField inputField = val5.AddComponent<TMP_InputField>();
				inputField.textViewport = component2;
				inputField.textComponent = (TMP_Text)(object)textComponent;
				inputField.contentType = (ContentType)2;
				inputField.characterLimit = 5;
				((Selectable)inputField).interactable = true;
				inputField.caretColor = Color.black;
				inputField.customCaretColor = true;
				inputField.caretWidth = 2;
				num = 10;
				Navigation navigation = ((Selectable)inputField).navigation;
				((Navigation)(ref navigation)).mode = (Mode)0;
				((Selectable)inputField).navigation = navigation;
				val5.transform.SetAsLastSibling();
				num = 11;
				PropertyInfo valueProp = AccessTools.Property(((object)sliderComponent).GetType(), "Value");
				float num2 = 1f;
				if (valueProp != null && valueProp.GetValue(sliderComponent) is float num3)
				{
					num2 = num3;
				}
				inputField.text = Mathf.RoundToInt(num2 * 100f) + "%";
				num = 12;
				((UnityEvent<string>)(object)inputField.onSelect).AddListener((UnityAction<string>)delegate(string text)
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_0037: Unknown result type (might be due to invalid IL or missing references)
					((Graphic)bg).color = Color.white;
					bg.sprite = roundedSprite;
					bg.type = (Type)1;
					((Graphic)textComponent).color = Color.black;
					if (text.EndsWith("%"))
					{
						inputField.text = text.Replace("%", "").Trim();
					}
				});
				((UnityEvent<string>)(object)inputField.onEndEdit).AddListener((UnityAction<string>)delegate(string text)
				{
					//IL_001b: 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)
					((Graphic)bg).color = new Color(0f, 0f, 0f, 0f);
					bg.sprite = null;
					((Graphic)textComponent).color = savedOriginalColor;
					string s = text.Replace("%", "").Trim();
					if (float.TryParse(s, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result))
					{
						float num4 = result / 100f;
						float num5 = 0f;
						PropertyInfo propertyInfo = AccessTools.Property(((object)sliderComponent).GetType(), "MinValue");
						if (propertyInfo != null && propertyInfo.GetValue(sliderComponent) is float num6)
						{
							num5 = num6;
						}
						float num7 = Mathf.Max(5f, num4);
						AccessTools.Property(((object)sliderComponent).GetType(), "MaxValue")?.SetValue(sliderComponent, num7);
						FieldInfo fieldInfo2 = AccessTools.Field(((object)sliderComponent).GetType(), "Slider");
						if (fieldInfo2 != null)
						{
							object value2 = fieldInfo2.GetValue(sliderComponent);
							if (value2 != null)
							{
								AccessTools.Property(value2.GetType(), "maxValue")?.SetValue(value2, num7);
							}
						}
						num4 = Mathf.Clamp(num4, num5, num7);
						valueProp?.SetValue(sliderComponent, num4);
						inputField.text = Mathf.RoundToInt(num4 * 100f) + "%";
					}
					else
					{
						float num8 = 1f;
						if (valueProp != null && valueProp.GetValue(sliderComponent) is float num9)
						{
							num8 = num9;
						}
						inputField.text = Mathf.RoundToInt(num8 * 100f) + "%";
					}
				});
				num = 13;
				FieldInfo fieldInfo = AccessTools.Field(((object)sliderComponent).GetType(), "Slider");
				if (fieldInfo != null)
				{
					object value = fieldInfo.GetValue(sliderComponent);
					Slider unitySlider = (Slider)((value is Slider) ? value : null);
					if (unitySlider != null)
					{
						((UnityEvent<float>)(object)unitySlider.onValueChanged).AddListener((UnityAction<float>)delegate(float num6)
						{
							if (!inputField.isFocused)
							{
								float num4 = 5f;
								PropertyInfo propertyInfo = AccessTools.Property(((object)sliderComponent).GetType(), "MaxValue");
								if (propertyInfo != null && propertyInfo.GetValue(sliderComponent) is float num5)
								{
									num4 = num5;
								}
								if (num6 <= 5f && num4 > 5f)
								{
									AccessTools.Property(((object)sliderComponent).GetType(), "MaxValue")?.SetValue(sliderComponent, 5f);
									AccessTools.Property(((object)unitySlider).GetType(), "maxValue")?.SetValue(unitySlider, 5f);
								}
								inputField.text = Mathf.RoundToInt(num6 * 100f) + "%";
							}
						});
					}
				}
				BetterVolumePlugin.Log.LogInfo((object)"Volume InputField successfully created and attached via reflection.");
			}
			catch (Exception ex)
			{
				BetterVolumePlugin.Log.LogError((object)($"Error in CreateInputFieldForSlider at step {num}: " + ex.ToString()));
			}
		}
	}
	public static class RectTransformExtensions
	{
		public static void anchorsToFillParent(this RectTransform t)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			t.anchorMin = Vector2.zero;
			t.anchorMax = Vector2.one;
			t.sizeDelta = Vector2.zero;
			t.anchoredPosition = Vector2.zero;
		}
	}
}