using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Koop;
using MeteorCore.Localiser;
using MeteorCore.Localiser.Dictionaries;
using MeteorCore.Setting;
using MeteorCore.Setting.AbstractClasses;
using MeteorCore.Setting.Interfaces;
using MeteorCore.Setting.Interfaces.Internal;
using MeteorCore.Utils;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Rewired;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
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.6", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("MeteorCore")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Core plugin for MeteorMod")]
[assembly: AssemblyFileVersion("0.2.0.0")]
[assembly: AssemblyInformationalVersion("0.2.0+0e3f2f6e4dbe75d8844716add93267e4a32980ca")]
[assembly: AssemblyProduct("MeteorCore")]
[assembly: AssemblyTitle("MeteorCore")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.2.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.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 MeteorCore
{
[BepInPlugin("MeteorCore", "MeteorCore", "0.2.0")]
public class Plugin : BaseUnityPlugin
{
internal static ManualLogSource Logger;
internal static Transform PluginManager;
internal static Harmony harmony;
internal static BepInPlugin metadata;
private void Awake()
{
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_006f: Expected O, but got Unknown
//IL_0097: Unknown result type (might be due to invalid IL or missing references)
ConfigEntry<bool> val = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "UnityLogging", true, "Enables unity logging");
Debug.unityLogger.logEnabled = val.Value;
Debug.unityLogger.filterLogType = (LogType)2;
metadata = MetadataHelper.GetMetadata((object)this);
Logger = ((BaseUnityPlugin)this).Logger;
Logger.LogInfo((object)"Plugin MeteorCore is loaded!");
harmony = new Harmony("MeteorCore");
harmony.PatchAll();
PluginLocaliser.RegisterPlugin(metadata);
GameObject val2 = GameObject.Find("MANAGER_MASTER");
PluginManager = new GameObject("MeteorCore").transform;
PluginManager.SetParent(val2.transform);
SceneHelper.Init();
Mgr_PluginSettings.Create();
}
}
public static class SceneHelper
{
public static bool IsSplashScene { get; private set; }
public static bool IsTitleScene { get; private set; }
public static bool IsPerformenceScene { get; private set; }
public static bool IsMinigameScene { get; private set; }
public static bool IsGameScene { get; private set; }
public static bool IsLNLScene { get; private set; }
public static void Init()
{
SceneManager.sceneLoaded += SceneLoaded;
}
private static void SceneLoaded(Scene scene, LoadSceneMode mode)
{
IsTitleScene = ((Scene)(ref scene)).name == "Title";
IsSplashScene = ((Scene)(ref scene)).name == "Splash";
GameObject val = GameObject.Find("GameplayUI Root");
IsPerformenceScene = (Object)(object)val != (Object)null;
GameObject val2 = GameObject.Find("MG_Basics/Controller");
IsMinigameScene = (Object)(object)val2 != (Object)null;
IsLNLScene = false;
IsGameScene = !IsSplashScene && !IsTitleScene && !IsPerformenceScene && !IsMinigameScene;
}
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "MeteorCore";
public const string PLUGIN_NAME = "MeteorCore";
public const string PLUGIN_VERSION = "0.2.0";
}
}
namespace MeteorCore.Utils
{
public static class MeteorUtils
{
public static T CopyComponent<T>(T original, GameObject destination) where T : Component
{
Type type = ((object)original).GetType();
Component component = destination.GetComponent(type);
T val = (T)(object)((component is T) ? component : null);
if (!Object.op_Implicit((Object)(object)val))
{
Component obj = destination.AddComponent(type);
val = (T)(object)((obj is T) ? obj : null);
}
FieldInfo[] fields = type.GetFields();
FieldInfo[] array = fields;
foreach (FieldInfo fieldInfo in array)
{
if (!fieldInfo.IsStatic)
{
fieldInfo.SetValue(val, fieldInfo.GetValue(original));
}
}
PropertyInfo[] properties = type.GetProperties();
PropertyInfo[] array2 = properties;
foreach (PropertyInfo propertyInfo in array2)
{
if (propertyInfo.CanWrite && propertyInfo.CanWrite && !(propertyInfo.Name == "name"))
{
propertyInfo.SetValue(val, propertyInfo.GetValue(original, null), null);
}
}
return val;
}
public static T CopyComponentValues<T>(T original, T destination, bool copyPrivate, ICollection<string> ignoreFields = null, ICollection<string> ignoreProperties = null) where T : Component
{
if ((Object)(object)destination == (Object)null)
{
Plugin.Logger.LogError((object)"CopyComponent destination is null");
}
if ((Object)(object)original == (Object)null)
{
Plugin.Logger.LogError((object)"CopyComponent original is null");
}
BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public;
if (copyPrivate)
{
bindingFlags |= BindingFlags.NonPublic;
}
Type typeFromHandle = typeof(T);
FieldInfo[] fields = typeFromHandle.GetFields(bindingFlags);
FieldInfo[] array = fields;
foreach (FieldInfo fieldInfo in array)
{
try
{
if (!fieldInfo.IsStatic && (ignoreFields == null || !ignoreFields.Contains(fieldInfo.Name)))
{
fieldInfo.SetValue(destination, fieldInfo.GetValue(original));
}
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)("Could not copy field \"" + fieldInfo.Name + "\" from \"" + ((object)original).GetType().Name + "\" to \"" + ((object)destination).GetType().Name + "\""));
Plugin.Logger.LogError((object)ex);
throw ex;
}
}
PropertyInfo[] properties = typeFromHandle.GetProperties(bindingFlags);
PropertyInfo[] array2 = properties;
foreach (PropertyInfo propertyInfo in array2)
{
try
{
if (propertyInfo.CanWrite && propertyInfo.CanWrite && !(propertyInfo.Name == "name") && (ignoreProperties == null || !ignoreProperties.Contains(propertyInfo.Name)))
{
propertyInfo.SetValue(destination, propertyInfo.GetValue(original, null), null);
}
}
catch (Exception ex2)
{
Plugin.Logger.LogError((object)("Could not copy property " + propertyInfo.Name + " from " + ((object)original).GetType().Name + " to " + ((object)destination).GetType().Name));
Plugin.Logger.LogError((object)ex2);
throw ex2;
}
}
return destination;
}
}
}
namespace MeteorCore.Setting
{
public class Mgr_PluginSettings : MonoBehaviour
{
private class PluginSettingContainer
{
public BepInPlugin ownerMetadata;
public ConfigEntryBase configEntryBase;
public string pageName;
public IPluginSetting setting;
public Type settingUIItemType;
}
private class PluginSettingPageContainer
{
public string pageGameObjectName;
public string pageName;
public string dictionaryName;
public Type pageType;
public IPluginSettingsPage pageInstance;
}
private static Mgr_PluginSettings _instance;
public static Transform settingPagesHolder;
private Dictionary<string, PluginSettingPageContainer> settingPages = new Dictionary<string, PluginSettingPageContainer>();
private List<PluginSettingContainer> settings = new List<PluginSettingContainer>();
private Dictionary<BepInPlugin, ConfigFile> configFiles = new Dictionary<BepInPlugin, ConfigFile>();
public static Mgr_PluginSettings Instance
{
get
{
if ((Object)(object)_instance == (Object)null)
{
_instance = Object.FindObjectOfType<Mgr_PluginSettings>();
}
return _instance;
}
}
public static bool SceneHasSettingsMenu => SceneHelper.IsTitleScene || SceneHelper.IsGameScene || SceneHelper.IsLNLScene;
private void Awake()
{
if ((Object)(object)_instance == (Object)null)
{
_instance = this;
}
if ((Object)(object)_instance != (Object)(object)this)
{
Object.Destroy((Object)(object)this);
}
SceneManager.sceneLoaded += SceneLoaded;
}
public static GameObject Create()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Expected O, but got Unknown
GameObject val = new GameObject("Mgr_PluginSettings");
val.AddComponent<Mgr_PluginSettings>();
val.transform.SetParent(Plugin.PluginManager);
GameObject val2 = SettingsUIPrefabs.Create();
val2.transform.SetParent(val.transform);
return val;
}
public static void AddPage<T>(string pageName, string dictionaryName, string pageGameObjectName) where T : IPluginSettingsPage
{
if (Instance.settingPages.ContainsKey(pageName))
{
Plugin.Logger.LogError((object)("Setting page " + pageName + " already exists"));
return;
}
Plugin.Logger.LogInfo((object)("Adding setting page " + pageName));
Instance.settingPages.Add(pageName, new PluginSettingPageContainer
{
pageGameObjectName = pageGameObjectName,
dictionaryName = dictionaryName,
pageName = pageName,
pageType = typeof(T),
pageInstance = null
});
}
public static void AddSetting<TSettingValue, TUIItem>(IPluginSetting<TSettingValue> setting, string pageName, BepInPlugin owner) where TUIItem : MonoBehaviour, IPluginSettingUIItem
{
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Expected O, but got Unknown
Plugin.Logger.LogInfo((object)("Adding setting " + setting.settingKey + " to page " + pageName));
if (!Instance.settingPages.ContainsKey(pageName))
{
Plugin.Logger.LogError((object)("Setting is not added as the page " + pageName + ", it does not exist. Make sure to call AddPage first"));
return;
}
try
{
GameObject val = new GameObject($"Generic Test {typeof(TUIItem)}");
Component val2 = (Component)(object)val.AddComponent<TUIItem>();
if (!(val2 is IPluginSettingUIItem))
{
Plugin.Logger.LogError((object)$"Could not add setting ui item {typeof(TUIItem)}, it may have a generic type problem. Make sure to pass a concrete type.");
return;
}
Object.Destroy((Object)(object)val);
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)$"Could not add setting ui item {typeof(TUIItem)}, it may have a generic type problem. Make sure to pass a concrete type.");
Plugin.Logger.LogError((object)ex);
throw ex;
}
if (!Instance.configFiles.ContainsKey(owner))
{
Instance.CreateConfigFile(owner);
}
ConfigEntry<TSettingValue> val3 = Instance.configFiles[owner].Bind<TSettingValue>(pageName, setting.settingKey, setting.DefaultValue, setting.tooltip);
Instance.settings.Add(new PluginSettingContainer
{
ownerMetadata = owner,
configEntryBase = (ConfigEntryBase)(object)val3,
pageName = pageName,
setting = setting,
settingUIItemType = typeof(TUIItem)
});
setting.SetValue(val3.Value, save: false, pending: false, notify: false);
}
private void SceneLoaded(Scene scene, LoadSceneMode mode)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
SettingsUIPrefabs.Instance.SceneLoaded(scene, mode);
if (!SceneHasSettingsMenu)
{
return;
}
foreach (KeyValuePair<string, PluginSettingPageContainer> settingPage in settingPages)
{
Plugin.Logger.LogInfo((object)("Creating page " + settingPage.Key));
PluginSettingPageContainer value = settingPage.Value;
IPluginSettingsPage pageInstance = CreatePageInstance(value);
value.pageInstance = pageInstance;
}
foreach (PluginSettingContainer setting in settings)
{
Plugin.Logger.LogInfo((object)("Creating setting UI item for" + setting.setting.settingKey));
string pageName = setting.pageName;
if (!settingPages.ContainsKey(pageName))
{
return;
}
IPluginSettingsPage pageInstance2 = settingPages[pageName].pageInstance;
IPluginSettingUIItem pluginSettingUIItem = CreateUIItem(setting.settingUIItemType, setting.setting, pageInstance2.settingsHolder);
pageInstance2.AddSettingUIItem(pluginSettingUIItem);
pluginSettingUIItem.SetSettingInternal(setting.setting);
}
foreach (PluginSettingPageContainer value2 in settingPages.Values)
{
value2.pageInstance.OnInitialized();
}
}
private IPluginSettingUIItem CreateUIItem(Type settingType, IPluginSetting setting, Transform parent)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Expected O, but got Unknown
try
{
GameObject val = new GameObject(settingType.Name);
Component val2 = val.AddComponent(settingType);
if (!(val2 is IPluginSettingUIItem pluginSettingUIItem))
{
Plugin.Logger.LogError((object)("Could not create ui item instance of type " + settingType.Name + " does it implement IPluginSettingUIItem?"));
return null;
}
GameObject val3 = pluginSettingUIItem.Initialize(parent, setting);
return val3.GetComponent<IPluginSettingUIItem>();
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)("Error creating ui item instance of type " + settingType.Name));
Plugin.Logger.LogError((object)ex);
throw ex;
}
}
private IPluginSettingsPage CreatePageInstance(PluginSettingPageContainer pageContainer)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Expected O, but got Unknown
GameObject val = new GameObject(pageContainer.pageGameObjectName);
val.transform.SetParent(settingPagesHolder);
IPluginSettingsPage pluginSettingsPage = val.AddComponent(pageContainer.pageType) as IPluginSettingsPage;
if (pluginSettingsPage == null)
{
Plugin.Logger.LogError((object)("Could not create page instance of type " + pageContainer.pageType?.Name + " with name " + pageContainer.pageGameObjectName + " does it implement IPluginSettingsPage?"));
}
try
{
val = pluginSettingsPage.Initialize(pageContainer.pageName, GetPageSettingsByPageName(pageContainer.pageName));
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)("Could not initialize page instance of type " + pageContainer.pageType?.Name + " with name " + pageContainer.pageGameObjectName));
Plugin.Logger.LogError((object)ex);
throw ex;
}
return val.GetComponent<IPluginSettingsPage>();
}
private List<IPluginSetting> GetPageSettingsByPageName(string pageName)
{
List<IPluginSetting> list = new List<IPluginSetting>();
foreach (PluginSettingContainer setting in settings)
{
if (setting.pageName == pageName)
{
list.Add(setting.setting);
}
}
return list;
}
private void CreateConfigFile(BepInPlugin ownerMetadata)
{
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Expected O, but got Unknown
string text = Path.Combine(Paths.ConfigPath, ownerMetadata.Name + ".cfg");
ConfigFile val = new ConfigFile(text, true, ownerMetadata);
val.SaveOnConfigSet = false;
configFiles.Add(ownerMetadata, val);
}
public void ApplySettings()
{
foreach (PluginSettingContainer setting in settings)
{
setting.setting.ApplyPendingValue();
}
}
public void RevertSettings()
{
foreach (PluginSettingContainer setting in settings)
{
setting.setting.RevertPendingValue();
}
}
public void SaveSettings()
{
foreach (PluginSettingContainer setting in settings)
{
ConfigEntryBase configEntryBase = setting.configEntryBase;
configEntryBase.BoxedValue = setting.setting.BoxedValue;
}
foreach (ConfigFile value in configFiles.Values)
{
value.Save();
}
Plugin.Logger.LogInfo((object)"Saved settings");
}
public bool HaveSettingsChangedWhileOpen()
{
foreach (PluginSettingContainer setting in settings)
{
if (setting.setting.isDirty)
{
return true;
}
}
return false;
}
}
[HarmonyPatch(typeof(SettingsMenu), "HaveSettingsChangedWhileOpen")]
public class SettingsPage_HaveSettingsChangedWhileOpen_Patch
{
public static void Postfix(ref bool __result)
{
__result = __result || Mgr_PluginSettings.Instance.HaveSettingsChangedWhileOpen();
}
}
[HarmonyPatch(typeof(Mgr_Settings), "ApplySettings")]
public class Mgr_Settings_ApplySettings_Patch
{
public static void Postfix()
{
Mgr_PluginSettings.Instance.ApplySettings();
Mgr_PluginSettings.Instance.SaveSettings();
}
}
[HarmonyPatch(typeof(SettingsMenu), "RevertAllPendingSettingsChanges")]
public class SettingsMenu_RevertAllPendingSettingsChanges_Patch
{
public static void Postfix()
{
Mgr_PluginSettings.Instance.RevertSettings();
}
}
public class SettingsUIPrefabs : MonoBehaviour
{
private static SettingsUIPrefabs _instance;
private bool firstSceneLoad = true;
public static SettingsUIPrefabs Instance
{
get
{
if ((Object)(object)_instance == (Object)null)
{
_instance = Object.FindObjectOfType<SettingsUIPrefabs>();
}
return _instance;
}
}
public static GameObject LabelPrefab { get; private set; }
public static GameObject TogglePrefab { get; private set; }
public static GameObject SliderPrefab { get; private set; }
public static GameObject ListPrefab { get; private set; }
private void Awake()
{
if ((Object)(object)_instance == (Object)null)
{
_instance = this;
}
if ((Object)(object)_instance != (Object)(object)this)
{
Object.Destroy((Object)(object)this);
}
}
public static GameObject Create()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Expected O, but got Unknown
GameObject val = new GameObject("SettingsUIPrefabs");
val.transform.SetParent(((Component)Mgr_PluginSettings.Instance).transform);
val.AddComponent<RectTransform>();
val.AddComponent<SettingsUIPrefabs>();
return val;
}
public void SceneLoaded(Scene scene, LoadSceneMode mode)
{
if (firstSceneLoad && Mgr_PluginSettings.SceneHasSettingsMenu)
{
firstSceneLoad = false;
CopyBaseUIITems();
}
}
private void CopyBaseUIITems()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Expected O, but got Unknown
GameObject val = new GameObject("SettingsUIPrefabs");
val.transform.SetParent(((Component)this).transform);
SettingsItemToggle val2 = Object.FindObjectOfType<SettingsItemToggle>(true);
if ((Object)(object)val2 != (Object)null)
{
TogglePrefab = Object.Instantiate<GameObject>(((Component)val2).gameObject, val.transform);
TogglePrefab.SetActive(false);
((Object)TogglePrefab).name = "PluginSettingsItemToggle";
}
else
{
Plugin.Logger.LogError((object)"Could not find toggle prefab");
}
StaticStringLocaliser componentInChildren = TogglePrefab.GetComponentInChildren<StaticStringLocaliser>();
if ((Object)(object)componentInChildren != (Object)null)
{
LabelPrefab = Object.Instantiate<GameObject>(((Component)componentInChildren).gameObject, val.transform);
LabelPrefab.SetActive(false);
((Object)LabelPrefab).name = "PluginSettingsLabel";
componentInChildren.BaseText = "LocaliserUnsetText";
componentInChildren.Dictionary = "LocaliserUnsetDictionary";
}
else
{
Plugin.Logger.LogError((object)"Could not find label prefab");
}
SettingsItemSlider val3 = Object.FindObjectOfType<SettingsItemSlider>(true);
if ((Object)(object)val3 != (Object)null)
{
SliderPrefab = Object.Instantiate<GameObject>(((Component)val3).gameObject, val.transform);
SliderPrefab.SetActive(false);
((Object)SliderPrefab).name = "PluginSettingsItemSlider";
}
else
{
Plugin.Logger.LogError((object)"Could not find slider prefab");
}
SettingsItemList val4 = Object.FindObjectOfType<SettingsItemList>(true);
if ((Object)(object)val4 != (Object)null)
{
ListPrefab = Object.Instantiate<GameObject>(((Component)val4).gameObject, val.transform);
ListPrefab.SetActive(false);
((Object)ListPrefab).name = "PluginSettingsItemList";
}
else
{
Plugin.Logger.LogError((object)"Could not find list prefab");
}
Plugin.Logger.LogInfo((object)"Loaded base setting UI prefabs");
}
private void EnableAllChildComponents(GameObject gameObject)
{
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Expected O, but got Unknown
MonoBehaviour[] components = gameObject.GetComponents<MonoBehaviour>();
foreach (MonoBehaviour val in components)
{
((Behaviour)val).enabled = true;
}
foreach (Transform item in gameObject.transform)
{
Transform val2 = item;
EnableAllChildComponents(((Component)val2).gameObject);
}
}
}
public class PluginSettingBool : PluginSetting<bool>
{
public PluginSettingBool(string settingKey, string settingName, bool defaultValue, string tooltip, string configSection, BepInPlugin owner)
: base(settingKey, settingName, defaultValue, tooltip, configSection, owner)
{
}
public override string GetValueText(bool value)
{
return PluginLocaliser.Translate(value ? "On" : "Off", Plugin.metadata);
}
}
public class PluginSettingFloat : PluginSetting<float>
{
public float minValue { get; set; }
public float maxValue { get; set; }
public float steps { get; set; }
public PluginSettingFloat(string settingKey, string settingName, string tooltip, string configSection, BepInPlugin owner, float defaultValue, float minValue = 0f, float maxValue = 1f, float steps = 0.1f)
: base(settingKey, settingName, defaultValue, tooltip, configSection, owner)
{
this.minValue = minValue;
this.maxValue = maxValue;
this.steps = steps;
}
public override void SetValue(float value, bool save, bool pending, bool notify)
{
value = Normalize(value);
if ((!pending || value != PendingValue) && (pending || value != Value))
{
base.SetValue(value, save, pending, notify);
}
}
public float Normalize(float value)
{
value = Mathf.Clamp(value, minValue, maxValue);
if (steps > 0f)
{
value = Mathf.Round(value / steps) * steps;
}
return value;
}
public override string GetValueText(float value)
{
return value.ToString("F" + CalculateDecimals());
}
private int CalculateDecimals()
{
if (steps == 0f || steps > 1f)
{
return 0;
}
return Mathf.CeilToInt(Mathf.Log10(steps) * -1f);
}
}
public class PluginSettingList<T> : PluginSetting<int>
{
public List<PluginSettingListOption<T>> options;
public Type optionType { get; protected set; }
public int optionCount => options.Count;
public PluginSettingList(string settingKey, string settingName, int defaultValue, string tooltip, string configSection, BepInPlugin owner, List<PluginSettingListOption<T>> options)
: base(settingKey, settingName, defaultValue, tooltip, configSection, owner)
{
this.options = options;
optionType = typeof(T);
if (!this.options.Exists((PluginSettingListOption<T> option) => option.id == defaultValue))
{
Plugin.Logger.LogError((object)$"Default value id {defaultValue} not found in options for {settingKey}. Using first option instead");
DefaultValue = this.options[0].id;
}
}
public virtual PluginSettingListOption<T> GetCurrentOption()
{
return GetOptionById(Value);
}
public virtual PluginSettingListOption<T> GetPendingOption()
{
return GetOptionById(PendingValue);
}
public virtual PluginSettingListOption<T> GetOptionById(int id)
{
return options.Find((PluginSettingListOption<T> option) => option.id == id);
}
public virtual int GetOptionIndex(int id)
{
return options.FindIndex((PluginSettingListOption<T> option) => option.id == id);
}
public virtual int GetOptionIndex(PluginSettingListOption<T> value)
{
return options.IndexOf(value);
}
public override string GetValueText(int id)
{
return PluginLocaliser.Translate(GetOptionById(id).text, owner);
}
}
public struct PluginSettingListOption<T>
{
public int id { get; set; }
public string text { get; set; }
public T value { get; set; }
public PluginSettingListOption(int id, string text, T value)
{
this.id = id;
this.text = text;
this.value = value;
}
}
public class PluginSettingListUIItem<T> : PluginSettingUIItem<PluginSettingList<T>, int>
{
protected TextMeshProUGUI valueLabel;
protected Image imgLeftButton;
protected Image imgRightButton;
protected bool wrapAround = false;
protected float arrowOffAlpha = 0.2f;
protected RewiredAxisAction uiHorizontal;
protected StaticStringLocaliser localiser;
protected float holdTime;
protected int lastInput;
protected int selectedOptionIndex;
public override GameObject Initialize(Transform parent, IPluginSetting setting)
{
//IL_0184: Unknown result type (might be due to invalid IL or missing references)
//IL_018e: Expected O, but got Unknown
//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
//IL_01b3: Expected O, but got Unknown
if (!(setting is PluginSettingList<T> pluginSettingList))
{
Plugin.Logger.LogError((object)("Could not convert setting to PluginSettingList<T> with key " + setting?.settingKey));
return null;
}
GameObject val = Object.Instantiate<GameObject>(SettingsUIPrefabs.ListPrefab, parent);
((Object)val).name = setting.settingKey;
SettingsItemList component = val.GetComponent<SettingsItemList>();
Component val2 = val.AddComponent(((object)this).GetType());
PluginSettingListUIItem<T> pluginSettingListUIItem = val2 as PluginSettingListUIItem<T>;
if ((Object)(object)pluginSettingListUIItem == (Object)null)
{
Plugin.Logger.LogError((object)$"PluginSettingListUIItem Could not add component {((object)this).GetType()} to {((Object)val).name}");
return null;
}
MeteorUtils.CopyComponentValues<SelectableElement>((SelectableElement)(object)component, (SelectableElement)(object)pluginSettingListUIItem, copyPrivate: true, (ICollection<string>)null, (ICollection<string>)null);
pluginSettingListUIItem.setting = pluginSettingList;
pluginSettingListUIItem.label = ((SettingsItem)component).label;
pluginSettingListUIItem.isDirtyIndicator = ((SettingsItem)component).isDirtyIndicator;
pluginSettingListUIItem.actionsToAddToControls = ((SettingsItem)component).actionsToAddToControls;
pluginSettingListUIItem.settingChangedAudio = ((SettingsItem)component).settingChangedAudio;
pluginSettingListUIItem.valueLabel = component.textLabel;
pluginSettingListUIItem.imgLeftButton = component.imgLeftButton;
pluginSettingListUIItem.imgRightButton = component.imgRightButton;
pluginSettingListUIItem.wrapAround = component.wrapAround;
pluginSettingListUIItem.arrowOffAlpha = component.arrowOffAlpha;
pluginSettingListUIItem.uiHorizontal = component.uiHorizontal;
pluginSettingListUIItem.localiser = component.Localiser;
pluginSettingListUIItem.holdTime = component.holdTime;
pluginSettingListUIItem.lastInput = component.lastInput;
((UnityEvent)((Component)pluginSettingListUIItem.imgLeftButton).GetComponent<Button>().onClick).AddListener(new UnityAction(pluginSettingListUIItem.PreviousChoice));
((UnityEvent)((Component)pluginSettingListUIItem.imgRightButton).GetComponent<Button>().onClick).AddListener(new UnityAction(pluginSettingListUIItem.NextChoice));
StaticStringLocaliser component2 = ((Component)pluginSettingListUIItem.valueLabel).GetComponent<StaticStringLocaliser>();
if ((Object)(object)component2 != (Object)null)
{
Object.Destroy((Object)(object)component2);
}
Object.Destroy((Object)(object)component);
((Behaviour)component).enabled = false;
Object.Destroy((Object)(object)((Component)this).gameObject);
StaticStringLocaliser component3 = ((Component)((Component)pluginSettingListUIItem).transform.GetChild(0)).GetComponent<StaticStringLocaliser>();
if ((Object)(object)component3 == (Object)null)
{
Plugin.Logger.LogError((object)"PluginSettingListUIItem Could not find localiser");
return null;
}
component3.BaseText = setting.settingName;
component3.Dictionary = PluginLocaliser.ConvertPluginToDictionaryName(setting.owner);
val.SetActive(true);
pluginSettingListUIItem.SelectOption(pluginSettingListUIItem.setting.GetOptionIndex(pluginSettingListUIItem.setting.Value), pending: false);
pluginSettingListUIItem.Refresh();
return val;
}
protected virtual void Update()
{
if (!((SelectableElement)this).isSelected || !((Interactable)this).IsInteractable())
{
return;
}
bool flag = RewiredExtensions.GetButtonDown(base.Player, uiHorizontal, (Dir)1);
bool flag2 = RewiredExtensions.GetButtonDown(base.Player, uiHorizontal, (Dir)0);
if (flag)
{
holdTime = 0f;
lastInput = 1;
}
else if (flag2)
{
holdTime = 0f;
lastInput = -1;
}
else if (lastInput != 0)
{
if (!RewiredExtensions.GetButton(base.Player, uiHorizontal, (Dir)(lastInput == 1)))
{
lastInput = 0;
}
else
{
holdTime += Time.deltaTime;
if (holdTime >= Scr_InputMaster.Instance.TimeToHoldBeforeLoopInputs)
{
while (holdTime > Scr_InputMaster.Instance.TimeToHoldBeforeLoopInputs + Scr_InputMaster.Instance.TimeBetweenLoopInputs)
{
holdTime -= Scr_InputMaster.Instance.TimeBetweenLoopInputs;
if (lastInput == 1)
{
flag = true;
}
else if (lastInput == -1)
{
flag2 = true;
}
}
}
}
}
if (flag)
{
PreviousChoice();
}
else if (flag2)
{
NextChoice();
}
}
protected virtual void PreviousChoice()
{
SelectOption(selectedOptionIndex - 1, pending: true);
Mgr_AudioPersistant.Instance.oneShotAudioSource.PlayOneShot(settingChangedAudio, ((SelectableElement)this).sfxVol);
}
protected virtual void NextChoice()
{
SelectOption(selectedOptionIndex + 1, pending: true);
Mgr_AudioPersistant.Instance.oneShotAudioSource.PlayOneShot(settingChangedAudio, ((SelectableElement)this).sfxVol);
}
protected virtual void SelectOption(int index, bool pending)
{
if (index < 0)
{
Scr_GamepadManager.Instance.PlayGamepadFeedback(Scr_GamepadManager.SettingsListLeft, (Side)30, 1f, 1f);
if (!wrapAround)
{
return;
}
index = base.setting.optionCount - 1;
}
else if (index >= base.setting.optionCount)
{
Scr_GamepadManager.Instance.PlayGamepadFeedback(Scr_GamepadManager.SettingsListRight, (Side)20, 1f, 1f);
if (!wrapAround)
{
return;
}
index = 0;
}
selectedOptionIndex = index;
SetValue(base.setting.options[index].id, save: false, pending, notify: true);
}
public override void SetValue(int id, bool save = false, bool pending = true, bool notify = true)
{
base.setting.SetValue(id, save, pending, notify);
Refresh();
}
public override void RevertToDefault()
{
base.setting.RevertPendingValue();
selectedOptionIndex = base.setting.GetOptionIndex(base.setting.Value);
Mgr_AudioPersistant.Instance.oneShotAudioSource.PlayOneShot(settingChangedAudio, ((SelectableElement)this).sfxVol);
Refresh();
}
protected override void OnLanguagedChanged()
{
Refresh();
}
protected override void Refresh()
{
//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)
//IL_006e: 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_004f: 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)
base.Refresh();
RefreshValueLabel();
if ((Object)(object)imgLeftButton != (Object)null)
{
Color color = ((Graphic)imgLeftButton).color;
color.a = ((selectedOptionIndex > 0) ? 1f : arrowOffAlpha);
((Graphic)imgLeftButton).color = color;
}
if ((Object)(object)imgRightButton != (Object)null)
{
Color color2 = ((Graphic)imgRightButton).color;
color2.a = ((selectedOptionIndex < base.setting.optionCount - 1) ? 1f : arrowOffAlpha);
((Graphic)imgRightButton).color = color2;
}
}
protected virtual void RefreshValueLabel()
{
if ((Object)(object)valueLabel != (Object)null)
{
((TMP_Text)valueLabel).text = base.setting.GetPendingValueText();
}
}
}
public class PluginStringListSettingUIItem : PluginSettingListUIItem<string>
{
}
public class PluginIntListSettingUIItem : PluginSettingListUIItem<int>
{
}
public class PluginFloatListSettingUIItem : PluginSettingListUIItem<float>
{
}
public class PluginBoolListSettingUIItem : PluginSettingListUIItem<bool>
{
}
public class PluginSettingsPage : ElementListPage, IPluginSettingsPage
{
protected TextMeshProUGUI tooltipTitle;
protected TextMeshProUGUI tooltip;
protected TextMeshProUGUI defaultValueTip;
protected LabelledRewiredAction revertToDefault;
public List<IPluginSettingUIItem> settingsUIItems = new List<IPluginSettingUIItem>();
protected IPluginSettingUIItem selectedSettingUIItem
{
get
{
if ((Object)(object)base.elementController == (Object)null || base.elementController.selectedElementIndex < 0)
{
return null;
}
return settingsUIItems[base.elementController.selectedElementIndex];
}
}
public Transform settingsHolder { get; private set; }
public List<IPluginSetting> settings { get; private set; }
public override void OnEnable()
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Expected O, but got Unknown
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Expected O, but got Unknown
((ElementListPage)this).OnEnable();
RefreshTooltip(selectedSettingUIItem);
LocalisationManager instance = LocalisationManager.Instance;
instance.LanguageChanged = (Notify)Delegate.Combine((Delegate?)(object)instance.LanguageChanged, (Delegate?)new Notify(OnLanguagedChanged));
if ((Object)(object)base.elementController != (Object)null && base.elementController.selectedElementIndex == -1)
{
base.elementController.SelectElement(0);
}
}
protected override void OnDisable()
{
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Expected O, but got Unknown
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Expected O, but got Unknown
((UIBehaviour)this).OnDisable();
LocalisationManager instance = LocalisationManager.Instance;
instance.LanguageChanged = (Notify)Delegate.Remove((Delegate?)(object)instance.LanguageChanged, (Delegate?)new Notify(OnLanguagedChanged));
}
protected override void OnDestroy()
{
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Expected O, but got Unknown
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Expected O, but got Unknown
if ((Object)(object)LocalisationManager.Instance != (Object)null)
{
LocalisationManager instance = LocalisationManager.Instance;
instance.LanguageChanged = (Notify)Delegate.Remove((Delegate?)(object)instance.LanguageChanged, (Delegate?)new Notify(OnLanguagedChanged));
}
}
public override void Update()
{
if (((MenuPage)this).isActive && ((Interactable)this).IsInteractable())
{
((ElementListPage)this).Update();
if (base.elementController.selectedElementIndex != -1 && base.player.GetButtonDown(revertToDefault.action))
{
selectedSettingUIItem.RevertToDefault();
}
}
}
public override void InitializePage()
{
}
protected virtual void OnLanguagedChanged()
{
RefreshTooltip(selectedSettingUIItem);
}
public override void OnSelectionChanged(int previousIndex, int currentIndex)
{
if ((Object)(object)((MenuPage)this).selectionChangedAudio != (Object)null)
{
Mgr_AudioPersistant.instance.oneShotAudioSource.PlayOneShot(((MenuPage)this).selectionChangedAudio, ((MenuPage)this).sfxVol);
}
IPluginSettingUIItem settingUIItem = settingsUIItems[currentIndex];
RefreshTooltip(settingUIItem);
((MenuPage)this).UpdateControls();
}
protected virtual void RefreshTooltip(IPluginSettingUIItem settingUIItem)
{
if (!((Object)(object)tooltipTitle == (Object)null) && !((Object)(object)tooltip == (Object)null) && settingUIItem != null)
{
((TMP_Text)tooltipTitle).text = settingUIItem.settingInterface.GetSettingName();
((TMP_Text)tooltip).text = settingUIItem.settingInterface.GetTooltip();
string text = PluginLocaliser.Translate("Default", Plugin.metadata);
string value = settingUIItem.settingInterface.DefaultValueText();
if (string.IsNullOrEmpty(value))
{
((TMP_Text)defaultValueTip).text = "";
return;
}
((TMP_Text)defaultValueTip).text = "(" + text + ": " + settingUIItem.settingInterface.DefaultValueText() + ")";
}
}
public override void GetControlsToAdd(List<LabelledRewiredAction> actions)
{
((MenuPage)this).GetControlsToAdd(actions);
if (base.elementController.selectedElementIndex != -1)
{
actions.Add(revertToDefault);
actions.AddRange(settingsUIItems[base.elementController.selectedElementIndex].actionsToAddToControls);
}
}
public virtual GameObject Initialize(string pageName, List<IPluginSetting> settings)
{
//IL_0138: Unknown result type (might be due to invalid IL or missing references)
//IL_013f: Expected O, but got Unknown
//IL_018e: 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)
SettingsMenu val = Object.FindObjectOfType<SettingsMenu>(true);
if ((Object)(object)val == (Object)null)
{
Plugin.Logger.LogError((object)"Could not find SettingsMenu GameObject");
return null;
}
GameObject gameObject = ((Component)((TabbedMenu)val).pages[0]).gameObject;
Transform parent = gameObject.transform.parent;
GameObject val2 = Object.Instantiate<GameObject>(gameObject, parent);
SettingsPage component = val2.GetComponent<SettingsPage>();
PluginSettingsPage pluginSettingsPage = val2.AddComponent<PluginSettingsPage>();
MeteorUtils.CopyComponentValues<MenuPage>((MenuPage)(object)component, (MenuPage)(object)pluginSettingsPage, copyPrivate: true, (ICollection<string>)null, (ICollection<string>)null);
MeteorUtils.CopyComponentValues<ElementListPage>((ElementListPage)(object)component, (ElementListPage)(object)pluginSettingsPage, copyPrivate: true, (ICollection<string>)null, (ICollection<string>)null);
pluginSettingsPage.tooltip = component.tooltip;
pluginSettingsPage.tooltipTitle = component.tooltipTitle;
pluginSettingsPage.defaultValueTip = component.defaultValueTip;
pluginSettingsPage.revertToDefault = component.revertToDefault;
((MenuPage)pluginSettingsPage).tabName = pageName;
Array.Resize(ref ((TabbedMenu)val).pages, ((TabbedMenu)val).pages.Length + 1);
((TabbedMenu)val).pages[((TabbedMenu)val).pages.Length - 1] = (MenuPage)(object)pluginSettingsPage;
pluginSettingsPage.settingsHolder = val2.transform.Find("ContentCanvasGroup/ContentParent/Content/Viewport/Items/");
if ((Object)(object)pluginSettingsPage.settingsHolder == (Object)null)
{
Plugin.Logger.LogError((object)"Could not get Items of newly instantiated settings page");
}
foreach (Transform item in pluginSettingsPage.settingsHolder)
{
Transform val3 = item;
Object.Destroy((Object)(object)((Component)val3).gameObject);
}
RectTransform component2 = ((Component)pluginSettingsPage.settingsHolder).gameObject.GetComponent<RectTransform>();
component2.anchorMin = new Vector2(0f, 1f);
component2.pivot = new Vector2(0f, 1f);
ContentSizeFitter val4 = ((Component)pluginSettingsPage.settingsHolder).gameObject.AddComponent<ContentSizeFitter>();
val4.verticalFit = (FitMode)1;
((Behaviour)component).enabled = false;
Object.Destroy((Object)(object)component);
Object.Destroy((Object)(object)((Component)this).gameObject);
val2.SetActive(false);
return val2;
}
public void OnInitialized()
{
//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
//IL_0103: Expected O, but got Unknown
//IL_0103: Unknown result type (might be due to invalid IL or missing references)
//IL_010d: Expected O, but got Unknown
if ((Object)(object)base.elementController == (Object)null)
{
Plugin.Logger.LogError((object)"Could not get ElementController in PluginSettingsPage");
return;
}
List<SelectableElement> list = new List<SelectableElement>();
foreach (IPluginSettingUIItem settingsUIItem in settingsUIItems)
{
SelectableElement[] components = settingsUIItem.gameObject.GetComponents<SelectableElement>();
if (components.Length == 0)
{
Plugin.Logger.LogWarning((object)("SelectableElement not found for setting UI item " + settingsUIItem.settingInterface?.settingKey));
continue;
}
SelectableElement[] array = components;
foreach (SelectableElement val in array)
{
if (((Behaviour)val).enabled)
{
list.Add(val);
}
}
}
SelectableGroupController elementController = base.elementController;
elementController.onSelectionChanged = (SelectionChangeCallback)Delegate.Combine((Delegate?)(object)elementController.onSelectionChanged, (Delegate?)new SelectionChangeCallback(((ElementListPage)this).OnSelectionChanged));
base.elementController.SetSelectableList(list.ToArray());
((ElementListPage)this).SetElements(list.ToArray());
}
public void AddSettingUIItem(IPluginSettingUIItem setting)
{
settingsUIItems.Add(setting);
}
}
public class PluginSettingSliderUIItem : PluginSettingUIItem<PluginSettingFloat, float>
{
protected TextMeshProUGUI valueLabel;
protected Slider slider;
protected RewiredAxisAction uiHorizontal;
protected float holdTime;
protected int lastInput;
public override GameObject Initialize(Transform parent, IPluginSetting setting)
{
if (!(setting is PluginSettingFloat pluginSettingFloat))
{
Plugin.Logger.LogError((object)("Could not convert setting to PluginSettingFloat with key " + setting?.settingKey));
return null;
}
GameObject val = Object.Instantiate<GameObject>(SettingsUIPrefabs.SliderPrefab, parent);
((Object)val).name = setting.settingKey;
SettingsItemSlider component = val.GetComponent<SettingsItemSlider>();
PluginSettingSliderUIItem pluginSettingSliderUIItem = val.AddComponent<PluginSettingSliderUIItem>();
MeteorUtils.CopyComponentValues<SelectableElement>((SelectableElement)(object)component, (SelectableElement)(object)pluginSettingSliderUIItem, copyPrivate: true, (ICollection<string>)null, (ICollection<string>)null);
pluginSettingSliderUIItem.setting = pluginSettingFloat;
pluginSettingSliderUIItem.label = ((SettingsItem)component).label;
pluginSettingSliderUIItem.isDirtyIndicator = ((SettingsItem)component).isDirtyIndicator;
pluginSettingSliderUIItem.actionsToAddToControls = ((SettingsItem)component).actionsToAddToControls;
pluginSettingSliderUIItem.settingChangedAudio = ((SettingsItem)component).settingChangedAudio;
pluginSettingSliderUIItem.valueLabel = component.textLabel;
pluginSettingSliderUIItem.slider = component.slider;
pluginSettingSliderUIItem.uiHorizontal = component.uiHorizontal;
pluginSettingSliderUIItem.holdTime = component.holdTime;
pluginSettingSliderUIItem.lastInput = component.lastInput;
Slider componentInChildren = ((Component)pluginSettingSliderUIItem).GetComponentInChildren<Slider>();
((UnityEvent<float>)(object)componentInChildren.onValueChanged).AddListener((UnityAction<float>)pluginSettingSliderUIItem.OnSliderValueChanged);
componentInChildren.maxValue = pluginSettingFloat.maxValue;
componentInChildren.minValue = pluginSettingFloat.minValue;
componentInChildren.wholeNumbers = false;
Object.Destroy((Object)(object)component);
((Behaviour)component).enabled = false;
Object.Destroy((Object)(object)((Component)this).gameObject);
StaticStringLocaliser component2 = ((Component)((Component)pluginSettingSliderUIItem).transform.GetChild(0)).GetComponent<StaticStringLocaliser>();
if ((Object)(object)component2 == (Object)null)
{
Plugin.Logger.LogError((object)"PluginSettingSliderUIItem Could not find localiser");
return null;
}
component2.BaseText = setting.settingName;
component2.Dictionary = PluginLocaliser.ConvertPluginToDictionaryName(setting.owner);
val.SetActive(true);
pluginSettingSliderUIItem.slider.value = pluginSettingFloat.Value;
pluginSettingSliderUIItem.Refresh();
return val;
}
protected virtual void Update()
{
if (!((SelectableElement)this).isSelected || !((Interactable)this).IsInteractable())
{
return;
}
bool flag = RewiredExtensions.GetButtonDown(base.Player, uiHorizontal, (Dir)1);
bool flag2 = RewiredExtensions.GetButtonDown(base.Player, uiHorizontal, (Dir)0);
if (flag)
{
holdTime = 0f;
lastInput = 1;
}
else if (flag2)
{
holdTime = 0f;
lastInput = -1;
}
else if (lastInput != 0)
{
if (!RewiredExtensions.GetButton(base.Player, uiHorizontal, (Dir)(lastInput == 1)))
{
lastInput = 0;
}
else
{
holdTime += Time.deltaTime;
if (holdTime >= Scr_InputMaster.Instance.TimeToHoldBeforeLoopInputs)
{
while (holdTime > Scr_InputMaster.Instance.TimeToHoldBeforeLoopInputs + Scr_InputMaster.Instance.TimeBetweenLoopInputs)
{
holdTime -= Scr_InputMaster.Instance.TimeBetweenLoopInputs;
if (lastInput == 1)
{
flag = true;
}
else if (lastInput == -1)
{
flag2 = true;
}
}
}
}
}
if (flag)
{
MoveDownStep();
}
else if (flag2)
{
MoveUpStep();
}
}
private void MoveDownStep()
{
SetValue(base.setting.PendingValue - base.setting.steps, save: false, pending: true, notify: true);
}
private void MoveUpStep()
{
SetValue(base.setting.PendingValue + base.setting.steps, save: false, pending: true, notify: true);
}
public override void SetValue(float value, bool save = false, bool pending = true, bool notify = true)
{
value = base.setting.Normalize(value);
slider.value = value;
base.setting.SetValue(value, save, pending, notify);
Refresh();
}
public override void RevertToDefault()
{
if (!IsDirty())
{
RefreshDirtyIndicator();
return;
}
Mgr_AudioPersistant.Instance.oneShotAudioSource.PlayOneShot(settingChangedAudio, ((SelectableElement)this).sfxVol);
base.setting.SetValue(base.setting.DefaultValue, save: false, pending: false, notify: true);
RefreshDirtyIndicator();
slider.value = base.setting.DefaultValue;
}
protected override void OnLanguagedChanged()
{
}
protected virtual void OnSliderValueChanged(float value)
{
value = base.setting.Normalize(value);
slider.value = value;
if (value != base.setting.PendingValue)
{
Mgr_AudioPersistant.Instance.oneShotAudioSource.PlayOneShot(settingChangedAudio, ((SelectableElement)this).sfxVol);
if (value > base.setting.PendingValue)
{
Scr_GamepadManager.Instance.PlayGamepadFeedback(Scr_GamepadManager.SettingsListLeft, (Side)30, 1f, 1f);
}
else
{
Scr_GamepadManager.Instance.PlayGamepadFeedback(Scr_GamepadManager.SettingsListRight, (Side)20, 1f, 1f);
}
base.setting.SetValue(value, save: false, pending: true, notify: true);
Refresh();
}
}
protected override void Refresh()
{
base.Refresh();
RefreshDirtyIndicator();
if (base.setting != null)
{
((TMP_Text)valueLabel).text = base.setting.GetPendingValueText();
}
}
}
public class PluginSettingToggleUIItem : PluginSettingUIItem<PluginSettingBool, bool>
{
private Image background;
private RectTransform knobParent;
private RectTransform knob;
private TextMeshProUGUI valueLabel;
private Coroutine animCoroutine;
private float animT;
private float animTotalTime = 0.1f;
private Color toggledOffColor = Color.gray;
private Color toggledOnColor = Color.white;
public int input_select { get; set; }
public override GameObject Initialize(Transform parent, IPluginSetting setting)
{
//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
//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_011d: Unknown result type (might be due to invalid IL or missing references)
//IL_0127: Expected O, but got Unknown
if (!(setting is PluginSettingBool pluginSettingBool))
{
Plugin.Logger.LogError((object)("Could not convert setting to PluginSettingBool with key " + setting?.settingKey));
return null;
}
GameObject val = Object.Instantiate<GameObject>(SettingsUIPrefabs.TogglePrefab, parent);
((Object)val).name = setting.settingKey;
SettingsItemToggle component = val.GetComponent<SettingsItemToggle>();
PluginSettingToggleUIItem pluginSettingToggleUIItem = val.AddComponent<PluginSettingToggleUIItem>();
MeteorUtils.CopyComponentValues<SelectableElement>((SelectableElement)(object)component, (SelectableElement)(object)pluginSettingToggleUIItem, copyPrivate: true, (ICollection<string>)null, (ICollection<string>)null);
pluginSettingToggleUIItem.setting = pluginSettingBool;
pluginSettingToggleUIItem.label = ((SettingsItem)component).label;
pluginSettingToggleUIItem.isDirtyIndicator = ((SettingsItem)component).isDirtyIndicator;
pluginSettingToggleUIItem.actionsToAddToControls = ((SettingsItem)component).actionsToAddToControls;
pluginSettingToggleUIItem.settingChangedAudio = ((SettingsItem)component).settingChangedAudio;
pluginSettingToggleUIItem.knob = component.knob;
pluginSettingToggleUIItem.knobParent = component.knobParent;
pluginSettingToggleUIItem.background = component.background;
pluginSettingToggleUIItem.valueLabel = component.valueLabel;
pluginSettingToggleUIItem.animCoroutine = component.animCoroutine;
pluginSettingToggleUIItem.toggledOffColor = component.toggledOffColor;
pluginSettingToggleUIItem.toggledOnColor = component.toggledOnColor;
pluginSettingToggleUIItem.input_select = component.input_select;
((UnityEvent)((Component)pluginSettingToggleUIItem).GetComponentInChildren<Button>().onClick).AddListener(new UnityAction(pluginSettingToggleUIItem.Toggle));
Object.Destroy((Object)(object)component);
((Behaviour)component).enabled = false;
Object.Destroy((Object)(object)((Component)this).gameObject);
StaticStringLocaliser component2 = ((Component)((Component)pluginSettingToggleUIItem).transform.GetChild(0)).GetComponent<StaticStringLocaliser>();
if ((Object)(object)component2 == (Object)null)
{
Plugin.Logger.LogError((object)"PluginSettingToggleUIItem Could not find localiser");
return null;
}
component2.BaseText = setting.settingName;
component2.Dictionary = PluginLocaliser.ConvertPluginToDictionaryName(setting.owner);
val.SetActive(true);
pluginSettingToggleUIItem.RefreshLabel();
return val;
}
public override void OnEnable()
{
base.OnEnable();
OnLanguagedChanged();
}
public virtual void Update()
{
if (((SelectableElement)this).isSelected && ((Interactable)this).IsInteractable() && base.Player.GetButtonDown(input_select))
{
Toggle();
}
}
public virtual void Toggle()
{
Mgr_AudioPersistant.Instance.oneShotAudioSource.PlayOneShot(settingChangedAudio, ((SelectableElement)this).sfxVol);
SetValue(!base.setting.PendingValue, save: false, pending: true, notify: true);
RefreshLabel();
}
public override void SetValue(bool value, bool save = false, bool pending = true, bool notify = true)
{
base.setting.SetValue(value, save, pending, notify);
RefreshDirtyIndicator();
TriggerAnimation();
}
public override void RevertToDefault()
{
if (IsDirty())
{
Mgr_AudioPersistant.Instance.oneShotAudioSource.PlayOneShot(settingChangedAudio, ((SelectableElement)this).sfxVol);
base.setting.SetValue(base.setting.DefaultValue, save: false, pending: false, notify: true);
RefreshDirtyIndicator();
TriggerAnimation();
}
}
protected virtual void RefreshLabel()
{
SetT(base.setting.PendingValue ? 1f : 0f);
OnLanguagedChanged();
}
protected override void OnLanguagedChanged()
{
if ((Object)(object)valueLabel != (Object)null)
{
((TMP_Text)valueLabel).text = base.setting.GetPendingValueText();
}
}
private void TriggerAnimation()
{
if (animCoroutine != null)
{
((MonoBehaviour)this).StopCoroutine(animCoroutine);
}
animCoroutine = ((MonoBehaviour)this).StartCoroutine(AnimCoroutine(base.setting.PendingValue));
}
private IEnumerator AnimCoroutine(bool on)
{
float goTo = (on ? 1f : 0f);
float currentT = animT;
float time = 0f;
while (time < animTotalTime)
{
time += Time.deltaTime;
SetT(Mathf.Lerp(currentT, goTo, time / animTotalTime));
yield return null;
}
}
private void SetT(float t)
{
//IL_0041: 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_004d: 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_006e: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: 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_00a6: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)knob == (Object)null) && !((Object)(object)background == (Object)null) && !((Object)(object)knobParent == (Object)null))
{
animT = t;
((Graphic)background).color = Color.Lerp(toggledOffColor, toggledOnColor, t);
RectTransform obj = knob;
Rect rect = knobParent.rect;
float width = ((Rect)(ref rect)).width;
rect = knob.rect;
obj.anchoredPosition = new Vector2(Mathf.Lerp(2f, width - ((Rect)(ref rect)).width - 2f, t), knob.anchoredPosition.y);
}
}
}
}
namespace MeteorCore.Setting.Interfaces
{
public interface IPluginSetting<T> : IPluginSetting
{
T Value { get; }
T PendingValue { get; }
T DefaultValue { get; }
event Action<IPluginSetting<T>> OnAppliedPendingValue;
event Action<IPluginSetting<T>> OnRevertedPendingValue;
event Action<IPluginSetting<T>> OnPendingValueChanged;
event Action<IPluginSetting<T>> OnValueChanged;
void SetValue(T value, bool save, bool pending, bool notify);
string GetValueText(T value);
}
public interface IPluginSettingsPage
{
Transform settingsHolder { get; }
List<IPluginSetting> settings { get; }
GameObject Initialize(string pageName, List<IPluginSetting> settings);
void OnInitialized();
void AddSettingUIItem(IPluginSettingUIItem setting);
}
public interface IPluginSettingUIItem<T, D> : IPluginSettingUIItem where T : IPluginSetting<D>
{
T setting { get; }
void SetValue(D value, bool save, bool pending, bool notify);
void SetSetting(T setting);
}
}
namespace MeteorCore.Setting.Interfaces.Internal
{
public interface IPluginSetting
{
object BoxedValue { get; }
bool isDirty { get; }
Type type { get; }
string settingKey { get; }
string configSection { get; }
string tooltip { get; }
string settingName { get; }
BepInPlugin owner { get; }
void SetValue(object value, bool save, bool pending, bool notify);
void ApplyPendingValue();
void RevertPendingValue();
string DefaultValueText();
string GetCurrentValueText();
string GetPendingValueText();
string GetSettingName();
string GetTooltip();
}
public interface IPluginSettingUIItem
{
IPluginSetting settingInterface { get; }
GameObject isDirtyIndicator { get; }
TextMeshProUGUI label { get; }
GameObject gameObject { get; }
List<LabelledRewiredAction> actionsToAddToControls { get; }
GameObject Initialize(Transform parent, IPluginSetting setting);
void SetSettingInternal(IPluginSetting setting);
void RevertToDefault();
}
}
namespace MeteorCore.Setting.AbstractClasses
{
public abstract class PluginSetting<T> : IPluginSetting<T>, IPluginSetting
{
public virtual object BoxedValue
{
get
{
return Value;
}
set
{
Value = (T)value;
}
}
public virtual T Value { get; private set; }
public virtual T PendingValue { get; protected set; }
public virtual T DefaultValue { get; protected set; }
public virtual string tooltip { get; protected set; }
public virtual string configSection { get; protected set; }
public virtual BepInPlugin owner { get; protected set; }
public virtual Type type => typeof(T);
public virtual string settingKey { get; }
public virtual string settingName { get; }
public virtual bool isDirty { get; protected set; }
public event Action<IPluginSetting<T>> OnAppliedPendingValue;
public event Action<IPluginSetting<T>> OnRevertedPendingValue;
public event Action<IPluginSetting<T>> OnPendingValueChanged;
public event Action<IPluginSetting<T>> OnValueChanged;
public PluginSetting(string settingKey, string settingName, T defaultValue, string tooltip, string configSection, BepInPlugin owner)
{
this.settingKey = settingKey;
this.settingName = settingName;
DefaultValue = defaultValue;
this.tooltip = tooltip;
this.configSection = configSection;
this.owner = owner;
isDirty = false;
}
public virtual void SetValue(T value, bool save, bool pending, bool notify)
{
if (pending)
{
PendingValue = value;
isDirty = true;
this.OnPendingValueChanged?.Invoke(this);
}
else
{
Value = value;
PendingValue = value;
isDirty = false;
this.OnValueChanged?.Invoke(this);
}
if (save)
{
Mgr_PluginSettings.Instance.SaveSettings();
}
}
public virtual void SetValue(object value, bool save, bool pending, bool notify)
{
if (!(value is T))
{
Plugin.Logger.LogError((object)$"Setting {settingKey} could not be set to {value} because it is not of type {typeof(T)}");
}
else
{
SetValue((T)value, save, pending, notify);
}
}
public virtual void ApplyPendingValue()
{
SetValue(PendingValue, save: false, pending: false, notify: true);
this.OnAppliedPendingValue?.Invoke(this);
}
public virtual void RevertPendingValue()
{
PendingValue = Value;
isDirty = false;
this.OnRevertedPendingValue?.Invoke(this);
}
public virtual string GetValueText(T value)
{
return PluginLocaliser.Translate(value.ToString(), owner);
}
public virtual string DefaultValueText()
{
return GetValueText(DefaultValue);
}
public virtual string GetCurrentValueText()
{
return GetValueText(Value);
}
public virtual string GetPendingValueText()
{
return GetValueText(PendingValue);
}
public virtual string GetSettingName()
{
return PluginLocaliser.Translate(settingName, owner);
}
public virtual string GetTooltip()
{
return PluginLocaliser.Translate(tooltip, owner);
}
}
public abstract class PluginSettingUIItem<T, D> : SelectableElement, IPluginSettingUIItem<T, D>, IPluginSettingUIItem where T : IPluginSetting<D>
{
public AudioClip settingChangedAudio;
public T setting { get; protected set; }
public IPluginSetting settingInterface => setting;
public GameObject isDirtyIndicator { get; protected set; }
public TextMeshProUGUI label { get; protected set; }
public List<LabelledRewiredAction> actionsToAddToControls { get; protected set; }
public Player Player => Scr_InputMaster.Instance.Player;
public virtual GameObject Initialize(Transform parent, IPluginSetting setting)
{
Plugin.Logger.LogWarning((object)"Using Initialize from base PluginSettingUIItem is not recommended");
T val = (T)(setting as IPluginSetting<D>);
if (val == null)
{
Plugin.Logger.LogError((object)"Could not convert setting to IPluginSetting<D>");
Plugin.Logger.LogError((object)$"Setting type: {setting.GetType()}");
Plugin.Logger.LogError((object)("With key " + setting.settingKey));
return null;
}
this.setting = val;
return null;
}
public virtual void SetSetting(T setting)
{
this.setting = setting;
}
public virtual void SetSettingInternal(IPluginSetting setting)
{
this.setting = (T)setting;
}
protected override void Awake()
{
((UIBehaviour)this).Awake();
base._selectOnPointerEnter = true;
}
public override void OnEnable()
{
//IL_0078: Unknown result type (might be due to invalid IL or missing references)
//IL_0082: Expected O, but got Unknown
//IL_0082: Unknown result type (might be due to invalid IL or missing references)
//IL_008c: Expected O, but got Unknown
((SelectableElement)this).OnEnable();
Refresh();
if (setting != null)
{
T val = setting;
val.OnAppliedPendingValue += OnApplied;
val = setting;
val.OnRevertedPendingValue += OnRevert;
}
LocalisationManager instance = LocalisationManager.Instance;
instance.LanguageChanged = (Notify)Delegate.Combine((Delegate?)(object)instance.LanguageChanged, (Delegate?)new Notify(OnLanguagedChanged));
}
public override void OnDisable()
{
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: Expected O, but got Unknown
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_0085: Expected O, but got Unknown
((SelectableElement)this).OnDisable();
if (setting != null)
{
T val = setting;
val.OnAppliedPendingValue -= OnApplied;
val = setting;
val.OnRevertedPendingValue -= OnRevert;
}
LocalisationManager instance = LocalisationManager.Instance;
instance.LanguageChanged = (Notify)Delegate.Remove((Delegate?)(object)instance.LanguageChanged, (Delegate?)new Notify(OnLanguagedChanged));
}
protected override void OnDestroy()
{
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
//IL_0074: Expected O, but got Unknown
//IL_0074: Unknown result type (might be due to invalid IL or missing references)
//IL_007e: Expected O, but got Unknown
if (setting != null)
{
T val = setting;
val.OnAppliedPendingValue -= OnApplied;
val = setting;
val.OnRevertedPendingValue -= OnRevert;
}
LocalisationManager instance = LocalisationManager.Instance;
instance.LanguageChanged = (Notify)Delegate.Remove((Delegate?)(object)instance.LanguageChanged, (Delegate?)new Notify(OnLanguagedChanged));
}
private void OnApplied(IPluginSetting<D> setting)
{
Refresh();
}
private void OnRevert(IPluginSetting<D> setting)
{
Refresh();
}
protected virtual void Refresh()
{
RefreshDirtyIndicator();
RefreshNameLabel();
}
protected virtual void RefreshDirtyIndicator()
{
GameObject obj = isDirtyIndicator;
if (obj != null)
{
obj.SetActive(IsDirty());
}
}
protected virtual void RefreshNameLabel()
{
if ((Object)(object)label != (Object)null && setting != null)
{
((TMP_Text)label).text = setting.GetSettingName();
}
}
protected virtual bool IsDirty()
{
T val = setting;
return val != null && val.isDirty;
}
public abstract void SetValue(D value, bool save, bool pending, bool notify);
public abstract void RevertToDefault();
protected abstract void OnLanguagedChanged();
GameObject IPluginSettingUIItem.get_gameObject()
{
return ((Component)this).gameObject;
}
}
}
namespace MeteorCore.Localiser
{
public static class PluginLocaliser
{
public static Dictionary<string, PluginDictionary> dictionaries = new Dictionary<string, PluginDictionary>();
public static bool ignoreMissingTranslations = false;
public static string language => Enum.GetName(typeof(Language), LocalisationManager.Instance.CurrentLanguage);
public static string ConvertPluginToDictionaryName(BepInPlugin plugin)
{
return plugin.Name;
}
public static string Translate(string key, BepInPlugin plugin)
{
return Translate(key, ConvertPluginToDictionaryName(plugin));
}
public static string Translate(string key, string dictionaryName, bool returnNullIfNotFound = false)
{
if (dictionaries.ContainsKey(dictionaryName))
{
string text = dictionaries[dictionaryName].Translate(key);
if (!Utility.IsNullOrWhiteSpace(text))
{
return text;
}
}
foreach (KeyValuePair<string, PluginDictionary> dictionary in dictionaries)
{
string text2 = dictionary.Value.TranslateFromAdditionalDictionary(key, dictionaryName, language);
if (!Utility.IsNullOrWhiteSpace(text2))
{
return text2;
}
}
if (ignoreMissingTranslations)
{
return key;
}
Plugin.Logger.LogWarning((object)("Could not find translation for key " + key + " in dictionary " + dictionaryName));
if (returnNullIfNotFound)
{
return null;
}
return GetTranslationNotFoundString(key, dictionaryName);
}
internal static string GetTranslationNotFoundString(string key, string dictionaryName)
{
return "\"No '" + key + "' translation in " + dictionaryName + "\"";
}
public static PluginDictionary RegisterPlugin(BepInPlugin plugin, string dictionaryPath = null, string projectName = null)
{
if (projectName == null)
{
projectName = plugin.Name;
}
string text = ConvertPluginToDictionaryName(plugin);
if (dictionaries.ContainsKey(text))
{
Plugin.Logger.LogWarning((object)("Plugin " + projectName + " already has a dictionary registered with name " + text));
return dictionaries[text];
}
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
Assembly assembly = null;
Assembly[] array = assemblies;
foreach (Assembly assembly2 in array)
{
if (assembly2.GetName().Name == projectName)
{
assembly = assembly2;
}
}
if (assembly == null)
{
Plugin.Logger.LogError((object)("Plugin " + projectName + " has no loaded assembly. Does it have the same name as the plugin?"));
return null;
}
string text2 = dictionaryPath ?? (projectName + ".Assets.localisation.json");
Stream manifestResourceStream = assembly.GetManifestResourceStream(text2);
if (manifestResourceStream == null)
{
Plugin.Logger.LogError((object)("Could not find dictionary asset at path " + text2 + " for plugin " + plugin.Name + ". Use embedded resource as the dictionary asset's Build Action property and place the dictionary inside the Assets folder."));
return null;
}
using StreamReader streamReader = new StreamReader(manifestResourceStream);
string text3 = streamReader.ReadToEnd();
if (string.IsNullOrEmpty(text3))
{
Plugin.Logger.LogError((object)("Dictionary asset at path " + text2 + " for plugin " + plugin.Name + " is empty"));
return null;
}
PluginDictionary pluginDictionary;
try
{
pluginDictionary = JsonConvert.DeserializeObject<PluginDictionary>(text3);
if (pluginDictionary == null)
{
Plugin.Logger.LogError((object)("Could not parse dictionary asset at path " + text2 + " for plugin " + plugin.Name + ", it is null"));
return null;
}
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)("Could not parse dictionary asset at path " + text2 + " for plugin " + plugin.Name));
Plugin.Logger.LogError((object)ex);
throw ex;
}
pluginDictionary.name = text;
pluginDictionary.plugin = plugin;
dictionaries.Add(text, pluginDictionary);
Plugin.Logger.LogInfo((object)("Plugin " + projectName + " registered with dictionary " + text));
return pluginDictionary;
}
}
}
namespace MeteorCore.Localiser.Dictionaries
{
[JsonObject(/*Could not decode attribute arguments.*/)]
public class PluginDictionary
{
public string name { get; set; }
public BepInPlugin plugin { get; set; }
[JsonProperty("dictionary")]
public Dictionary<string, Dictionary<string, string>> dictionary { get; set; }
[JsonProperty("additionalDictionaries")]
public Dictionary<string, Dictionary<string, Dictionary<string, string>>> additionalDictionaries { get; set; }
[OnDeserialized]
private void OnDeserialized(StreamingContext context)
{
if (dictionary == null)
{
Plugin.Logger.LogWarning((object)("Plugin " + name + " dictionary file does not include dictionary field"));
dictionary = new Dictionary<string, Dictionary<string, string>>();
}
if (additionalDictionaries == null)
{
Plugin.Logger.LogInfo((object)("Plugin " + name + " dictionary file does not include additionalDictionaries field"));
additionalDictionaries = new Dictionary<string, Dictionary<string, Dictionary<string, string>>>();
}
}
public string Translate(string key)
{
return Translate(key, PluginLocaliser.language);
}
public string Translate(string key, string language)
{
if (dictionary.ContainsKey(language) && dictionary[language].ContainsKey(key))
{
return dictionary[language][key];
}
if (PluginLocaliser.ignoreMissingTranslations)
{
return key;
}
return null;
}
public bool HasAdditionalDictionary(string dictionaryName)
{
return additionalDictionaries.ContainsKey(dictionaryName);
}
public string TranslateFromAdditionalDictionary(string key, string dictionaryName, string language)
{
if (additionalDictionaries.ContainsKey(dictionaryName) && additionalDictionaries[dictionaryName].ContainsKey(language) && additionalDictionaries[dictionaryName][language].ContainsKey(key))
{
return additionalDictionaries[dictionaryName][language][key];
}
return null;
}
public override string ToString()
{
string text = "PluginDictionary: " + name + "\n";
foreach (KeyValuePair<string, Dictionary<string, string>> item in dictionary)
{
text = text + item.Key + "\n";
foreach (KeyValuePair<string, string> item2 in item.Value)
{
text = text + item2.Key + ": " + item2.Value + "\n";
}
}
foreach (KeyValuePair<string, Dictionary<string, Dictionary<string, string>>> additionalDictionary in additionalDictionaries)
{
text = text + "Additional Dictionaries: " + additionalDictionary.Key + "\n";
foreach (KeyValuePair<string, Dictionary<string, string>> item3 in additionalDictionary.Value)
{
text = text + item3.Key + "\n";
foreach (KeyValuePair<string, string> item4 in item3.Value)
{
text = text + item4.Key + ": " + item4.Value + "\n";
}
}
}
return text;
}
}
}
namespace MeteorCore.Localiser.Patches
{
[HarmonyPatch(typeof(LocalisationManager), "TranslateDialogue")]
public class PluginLocalisationPatcher
{
public static void Postfix(ref string __result)
{
if (__result.Contains("No translation found"))
{
string text = __result.Replace("No translation found for '", "");
text = text.Substring(0, text.IndexOf("' in"));
string dictionaryName = __result.Substring(__result.IndexOf(" in ") + 4);
string text2 = PluginLocaliser.Translate(text, dictionaryName);
__result = text2;
}
}
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
List<CodeInstruction> list = new List<CodeInstruction>(instructions);
for (int i = 0; i < list.Count; i++)
{
if (list[i].opcode == OpCodes.Ldloc_0 && list[i + 1].opcode == OpCodes.Call && list[i + 1].operand is MethodInfo methodInfo && methodInfo.Name == "LogError")
{
list[i].opcode = OpCodes.Nop;
list[i + 1].opcode = OpCodes.Nop;
Plugin.Logger.LogInfo((object)"LocalisationManager.TranslateDialogue Patch Success");
return list;
}
}
Plugin.Logger.LogError((object)"LocalisationManager.TranslateDialogue Patch Failed");
return list;
}
}
}