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(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 = ((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("UI/Skin/InputFieldBackground.psd") ?? Resources.GetBuiltinResource("UI/Skin/UISprite.psd"); Image bg = val5.AddComponent(); ((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(); component2.anchorsToFillParent(); num = 7; GameObject val7 = new GameObject("Text", new Type[1] { typeof(RectTransform) }); val7.transform.SetParent(val6.transform, false); RectTransform component3 = val7.GetComponent(); component3.anchorsToFillParent(); num = 8; TextMeshProUGUI textComponent = val7.AddComponent(); 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(); 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)(object)inputField.onSelect).AddListener((UnityAction)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)(object)inputField.onEndEdit).AddListener((UnityAction)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)(object)unitySlider.onValueChanged).AddListener((UnityAction)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; } } }