Decompiled source of Configgy v1.0.4
plugins/Configgy.dll
Decompiled 8 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.CodeDom.Compiler; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using Configgable.Assets; using Configgy.Assets; using Configgy.Configuration.AutoGeneration; using Configgy.Properties; using Configgy.UI; using Configgy.UI.Template; using HarmonyLib; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using UnityEngine; using UnityEngine.Events; using UnityEngine.Networking; 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(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] [assembly: AssemblyCompany("Hydraxous")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyCopyright("Copyright © 2024 Hydraxous. All rights reserved.")] [assembly: AssemblyDescription("Configuration plugin")] [assembly: AssemblyFileVersion("1.0.4.0")] [assembly: AssemblyInformationalVersion("1.0.4+6b315237c165210b0f4af72982add3c265577ff4")] [assembly: AssemblyProduct("Configgy")] [assembly: AssemblyTitle("Configgy")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/Hydraxous/Configgy")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.4.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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [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 Configgy { public class BehaviourRelay : MonoBehaviour { public Action<GameObject> OnAwake; public Action<GameObject> OnStart; public Action<GameObject> OnUpdate; public Action<GameObject> OnLateUpdate; public Action<GameObject> OnFixedUpdate; public Action<GameObject> OnOnEnable; public Action<GameObject> OnOnDisable; public Action<GameObject> OnOnDestroy; private void Awake() { OnAwake?.Invoke(((Component)this).gameObject); } private void Start() { OnStart?.Invoke(((Component)this).gameObject); } private void Update() { OnUpdate?.Invoke(((Component)this).gameObject); } private void LateUpdate() { OnLateUpdate?.Invoke(((Component)this).gameObject); } private void FixedUpdate() { OnFixedUpdate?.Invoke(((Component)this).gameObject); } private void OnEnable() { OnOnEnable?.Invoke(((Component)this).gameObject); } private void OnDisable() { OnOnDisable?.Invoke(((Component)this).gameObject); } private void OnDestroy() { OnOnDestroy?.Invoke(((Component)this).gameObject); } } public class ConfigBuilder { internal Assembly owner; internal List<IConfigElement> _configElements; internal static HashSet<Type> environmentBuiltTypes = new HashSet<Type>(); private bool builtGlobal = false; private List<SerializedConfiggable> _data; private bool saveNextFrame; public string GUID { get; } public string DisplayName { get; } internal bool initialized { get; private set; } private List<SerializedConfiggable> data { get { if (_data == null) { LoadData(); } return _data; } } public event Action<IConfigElement[]> OnConfigElementsChanged; public ConfigBuilder(string guid = null, string menuDisplayName = null) { owner = Assembly.GetCallingAssembly(); GUID = (string.IsNullOrEmpty(guid) ? owner.GetName().Name : guid); DisplayName = (string.IsNullOrEmpty(menuDisplayName) ? GUID : menuDisplayName); } public void BuildTypes(params Type[] types) { foreach (Type type in types) { BuildType(type); } } public void BuildType(Type type) { if ((object)owner == null) { owner = Assembly.GetCallingAssembly(); } if (owner != type.Assembly) { throw new Exception("Configgy.ConfigBuilder:" + GUID + ": You can only build types originating from the assembly that owns the ConfigBuilder."); } if (environmentBuiltTypes.Contains(type)) { if (builtGlobal) { throw new Exception("Configgy.ConfigBuilder:" + GUID + ": Type has already been built into an existing config. If this is a mistake and you called BuildAll, you must call BuildType before BuildAll."); } throw new Exception("Configgy.ConfigBuilder:" + GUID + ": Type has already been built into an existing config."); } if (_configElements == null) { _configElements = new List<IConfigElement>(); } ProcessType(type); BuildInternal(); } public void BuildAll() { if (!builtGlobal) { if ((object)owner == null) { owner = Assembly.GetCallingAssembly(); } if (_configElements == null) { _configElements = new List<IConfigElement>(); } Type[] types = owner.GetTypes(); foreach (Type type in types) { ProcessType(type); } builtGlobal = true; BuildInternal(); } } [Obsolete("Build is now obsolete. Use ConfigBuilder.BuildAll to build using your whole assembly.")] public void Build() { if (!initialized) { BuildAll(); } } internal void ProcessType(Type type) { if (!environmentBuiltTypes.Contains(type)) { MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo method in methods) { ProcessMethod(method); } FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo field in fields) { ProcessField(field); } environmentBuiltTypes.Add(type); } } internal void BuildInternal() { if (!initialized) { if (_configElements == null) { _configElements = new List<IConfigElement>(); } CreateSaverObject(); OnConfigElementsChanged += delegate { ConfigurationManager.SubMenuElementsChanged(); }; this.OnConfigElementsChanged?.Invoke(_configElements.ToArray()); initialized = true; ConfigurationManager.RegisterConfiguraitonMenu(this); } } public void Rebuild() { this.OnConfigElementsChanged?.Invoke(_configElements.ToArray()); } internal IConfigElement[] GetConfigElements() { return _configElements.ToArray(); } private void ProcessMethod(MethodInfo method) { ConfiggableAttribute customAttribute = method.GetCustomAttribute<ConfiggableAttribute>(); if (customAttribute == null) { return; } if (method.ReturnType != typeof(void)) { Debug.LogError((object)("Configgy.ConfigBuilder:" + GUID + ": attempted to register method " + method.DeclaringType.Name + "." + method.Name + ". But it's return type is not void. Skipping!")); return; } if (method.GetParameters().Length != 0) { Debug.LogError((object)("Configgy.ConfigBuilder:" + GUID + ": attempted to register method " + method.DeclaringType.Name + "." + method.Name + ". But it has more than 0 parameters. Skipping!")); return; } if (!method.IsStatic) { Debug.LogError((object)("Configgy.ConfigBuilder:" + GUID + ": attempted to register method " + method.DeclaringType.Name + "." + method.Name + ". But it is not static. Skipping!")); return; } customAttribute.SetOwner(this); customAttribute.SetSerializationAddress(GUID + "." + method.DeclaringType.Namespace + "." + method.DeclaringType.Name + "." + method.Name); if (string.IsNullOrEmpty(customAttribute.DisplayName)) { customAttribute.SetDisplayNameFromCamelCase(method.Name); } RegisterMethodAsButton(customAttribute, method); } private void ProcessField(FieldInfo field) { ConfiggableAttribute customAttribute = field.GetCustomAttribute<ConfiggableAttribute>(); if (customAttribute == null) { return; } if (!field.IsStatic) { Debug.LogError((object)("Configgy.ConfigBuilder:" + GUID + ": attempted to register field " + field.DeclaringType.Name + "." + field.Name + ". But it is not static. Skipping!")); return; } customAttribute.SetOwner(this); customAttribute.SetSerializationAddress(GUID + "." + field.DeclaringType.Namespace + "." + field.DeclaringType.Name + "." + field.Name); if (string.IsNullOrEmpty(customAttribute.DisplayName)) { customAttribute.SetDisplayNameFromCamelCase(field.Name); } if (typeof(IConfigElement).IsAssignableFrom(field.FieldType)) { IConfigElement configElement = (IConfigElement)field.GetValue(null); RegisterElementCore(customAttribute, configElement); } else { RegisterPrimitive(customAttribute, field); } } private void RegisterMethodAsButton(ConfiggableAttribute descriptor, MethodInfo method) { ConfigButton configButton = new ConfigButton(delegate { method.Invoke(null, null); }); configButton.BindConfig(this); configButton.BindDescriptor(descriptor); RegisterElementCore(descriptor, configButton); } private void RegisterElementCore(ConfiggableAttribute descriptor, IConfigElement configElement) { configElement.BindDescriptor(descriptor); configElement.BindConfig(this); _configElements.Add(configElement); } public void RegisterElement(ConfiggableAttribute descriptor, IConfigElement configElement) { BuildInternal(); RegisterElementCore(descriptor, configElement); } public void RegisterBepInExConfigEntry(ConfigEntryBase entry) { BuildInternal(); ConfiggableAttribute configgableAttribute = new ConfiggableAttribute(entry.Definition.Section, entry.Definition.Key, 0, entry.Description.Description); configgableAttribute.SetOwner(this); if (!(typeof(ConfigBuilder).GetMethod("MakeBepInExElement", BindingFlags.Static | BindingFlags.NonPublic).MakeGenericMethod(entry.SettingType).Invoke(null, new object[1] { entry }) is ConfigValueElement element)) { Debug.LogWarning((object)("Configgy.ConfigBuilder:" + GUID + ": failed to auto generate BepInEx ConfigEntry " + entry.Definition.Section + "." + entry.Definition.Key + ". It's type (" + entry.SettingType.Name + ") is not supported.")); } else { RegisterElementCore(configgableAttribute, BepinElement.WrapUntyped(entry, element)); } } private static ConfigValueElement MakeBepInExElement<T>(ConfigEntry<T> entry) { ConfigDescription description = ((ConfigEntryBase)entry).Description; AcceptableValueBase val = ((description != null) ? description.AcceptableValues : null); if (val.IsAcceptableValueList()) { MethodInfo method = typeof(ConfigBuilder).GetMethod("MakeBepInExDropdown", BindingFlags.Static | BindingFlags.NonPublic); MethodInfo methodInfo = method.MakeGenericMethod(typeof(T)); return (ConfigDropdown<T>)methodInfo.Invoke(null, new object[1] { entry }); } if (val is AcceptableValueRange<int> val2) { return new IntegerSlider((int)((ConfigEntryBase)entry).DefaultValue, val2.MinValue, val2.MaxValue); } if (val is AcceptableValueRange<float> val3) { return new FloatSlider((float)((ConfigEntryBase)entry).DefaultValue, val3.MinValue, val3.MaxValue); } T @default = entry.GetDefault<T>(); return ConfigValueElement.Create(@default); } private static ConfigDropdown<T> MakeBepInExDropdown<T>(ConfigEntry<T> entry) where T : IEquatable<T> { AcceptableValueList<T> val = (AcceptableValueList<T>)(object)((ConfigEntryBase)entry).Description.AcceptableValues; T[] acceptableValues = val.AcceptableValues; Func<T, string> selector = ((ConfigEntryBase)(object)entry).GetTag<Func<T, string>>() ?? ((Func<T, string>)((T v) => v.ToString())); string[] names = acceptableValues.Select(selector).ToArray(); T @default = entry.GetDefault<T>(); return new ConfigDropdown<T>(acceptableValues, @default, names); } private void RegisterPrimitive(ConfiggableAttribute descriptor, FieldInfo field) { ConfigValueElement configValueElement = MakeElementForField(field); if (configValueElement != null) { configValueElement.BindField(field); RegisterElementCore(descriptor, configValueElement); } } private ConfigValueElement MakeElementForField(FieldInfo field) { object value = field.GetValue(null); RangeAttribute customAttribute = ((MemberInfo)field).GetCustomAttribute<RangeAttribute>(); if (customAttribute != null) { if (value is float num) { float min = customAttribute.min; float max = customAttribute.max; float defaultValue = Mathf.Clamp(num, min, max); return new FloatSlider(defaultValue, min, max); } if (value is int num2) { int num3 = (int)customAttribute.min; int num4 = (int)customAttribute.max; int defaultValue2 = Mathf.Clamp(num2, num3, num4); return new IntegerSlider(defaultValue2, num3, num4); } } ConfigValueElement configValueElement = typeof(ConfigValueElement).GetMethod("Create").MakeGenericMethod(value.GetType()).Invoke(null, new object[1] { value }) as ConfigValueElement; if (configValueElement == null) { Debug.LogError((object)("Configgy.ConfigBuilder:" + GUID + ": attempted to register field " + field.DeclaringType.Name + "." + field.Name + ". But it's type (" + field.FieldType.Name + ") is not supported. Skipping!")); } return configValueElement; } internal void LoadData() { string text = Path.Combine(Paths.DataFolder, owner.GetName().Name); if (!Directory.Exists(text)) { string text2 = Path.Combine(Paths.LegacyDataFolder, owner.GetName().Name); if (Directory.Exists(text2)) { Debug.LogWarning((object)("Found legacy configgy data for " + GUID + ". Moving to new location.")); Directory.Move(text2, text); Debug.LogWarning((object)"Move Complete."); } else { Directory.CreateDirectory(text); Debug.LogWarning((object)("Created configgy directory for " + GUID + ".")); } } string text3 = Path.Combine(text, GUID + ".json"); List<SerializedConfiggable> list = new List<SerializedConfiggable>(); if (!File.Exists(text3)) { string contents = JsonConvert.SerializeObject((object)list); File.WriteAllText(text3, contents); } else { try { string text4 = File.ReadAllText(text3); list = JsonConvert.DeserializeObject<List<SerializedConfiggable>>(text4); Debug.Log((object)$"Loaded Config {GUID} with {list.Count} values"); } catch (Exception ex) { Debug.LogError((object)"Error Loading Configgy Data!"); Debug.LogException(ex); int i; for (i = 0; File.Exists(text3 + ".backup" + ((i > 0) ? $" ({i})" : "")); i++) { } Debug.Log((object)"Created configgy file backup."); File.Copy(text3, text3 + ".backup" + ((i > 0) ? $" ({i})" : "")); File.Delete(text3); list = new List<SerializedConfiggable>(); } } list = list.Where((SerializedConfiggable x) => x.IsValid()).ToList(); _data = list; } public void SaveData() { if (_data != null) { string text = Path.Combine(Paths.DataFolder, owner.GetName().Name); if (!Directory.Exists(text)) { Directory.CreateDirectory(text); } string path = Path.Combine(text, GUID + ".json"); string contents = JsonConvert.SerializeObject((object)_data, (Formatting)1); File.WriteAllText(path, contents); } } internal void SaveDeferred() { saveNextFrame = true; } private IEnumerator SaveChecker() { while (true) { yield return (object)new WaitForEndOfFrame(); if (saveNextFrame) { SaveData(); saveNextFrame = false; } } } internal void CreateSaverObject() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown GameObject val = new GameObject("Configgy_Saver (" + GUID + ")"); BehaviourRelay behaviourRelay = val.AddComponent<BehaviourRelay>(); ((Object)val).hideFlags = (HideFlags)61; ((MonoBehaviour)behaviourRelay).StartCoroutine(SaveChecker()); Object.DontDestroyOnLoad((Object)(object)val); } internal T GetValueAtAddress<T>(string address) { foreach (SerializedConfiggable datum in data) { if (datum.key == address) { return datum.GetValue<T>(); } } return default(T); } internal bool TryGetValueAtAddress<T>(string address, out T value) { value = default(T); foreach (SerializedConfiggable datum in data) { if (datum.key == address) { try { value = datum.GetValue<T>(); return true; } catch (Exception ex) { Debug.LogError((object)"Failed to deserialize value"); Debug.LogException(ex); } break; } } return false; } internal void SetValueAtAddress(string address, object value) { foreach (SerializedConfiggable datum in data) { if (datum.key == address) { datum.SetValue(value); return; } } data.Add(new SerializedConfiggable(address, value)); } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field)] public class ConfiggableAttribute : Attribute { public string Path { get; } public string DisplayName { get; private set; } public string Description { get; private set; } public int OrderInList { get; } public string SerializationAddress { get; private set; } public ConfigBuilder Owner { get; private set; } public ConfiggableAttribute(string path = "", string displayName = null, int orderInList = 0, string description = null) { Path = path; DisplayName = displayName; Description = description; OrderInList = orderInList; } public void SetSerializationAddress(string address) { SerializationAddress = address; } public void SetDisplayName(string name) { DisplayName = name; } public void SetDescription(string description) { Description = description; } public void SetOwner(ConfigBuilder owner) { if (Owner == null) { Owner = owner; } } public void SetDisplayNameFromCamelCase(string camelCaseName) { string input = camelCaseName; input = Regex.Replace(input, "^_", "").Trim(); input = Regex.Replace(input, "([a-z])([A-Z])", "$1 $2").Trim(); input = Regex.Replace(input, "([A-Z])([A-Z][a-z])", "$1 $2").Trim(); input = string.Concat(input.Select((char x) => char.IsUpper(x) ? (" " + x) : x.ToString())).TrimStart(new char[1] { ' ' }); if (input.Length > 0 && char.IsLower(input[0])) { char c = input[0]; input = input.Remove(0, 1); input = char.ToUpper(c) + input; } DisplayName = input; } } public static class ConfigurationManager { private static List<ConfigBuilder> menus = new List<ConfigBuilder>(); internal static event Action<ConfigBuilder[]> OnMenusChanged; internal static void RegisterConfiguraitonMenu(ConfigBuilder menu) { if (menus.Select((ConfigBuilder x) => x.GUID).Contains(menu.GUID)) { throw new DuplicateNameException("ConfigBuilder GUID (" + menu.GUID + ") already exists! Using two ConfiggableMenus with the same GUID is not allowed."); } menus.Add(menu); ConfigurationManager.OnMenusChanged?.Invoke(GetMenus()); } internal static ConfigBuilder[] GetMenus() { return menus.ToArray(); } internal static void SubMenuElementsChanged() { ConfigurationManager.OnMenusChanged?.Invoke(GetMenus()); } } public static class ConfigValidators { public static bool Clamp(float value, float min, float max) { return value > min && value < max; } public static bool Min(float value, float min) { return value > min; } public static bool Max(float value, float max) { return value < max; } public static bool Clamp(int value, int min, int max) { return value > min && value < max; } public static bool Min(int value, int min) { return value > min; } public static bool Max(int value, int max) { return value < max; } } public interface IConfigElement { internal void BindDescriptor(ConfiggableAttribute configgable); internal ConfiggableAttribute GetDescriptor(); void BuildElement(RectTransform rect); void OnMenuOpen(); void OnMenuClose(); internal void BindConfig(ConfigBuilder configBuilder); } internal static class ConstInfo { public const string GUID = "Hydraxous.ULTRAKILL.Configgy"; public const string NAME = "Configgy"; public const string VERSION = "1.0.4"; public const string GITHUB_URL = "https://github.com/Hydraxous/Configgy/"; public const string THUNDERSTORE_URL = "https://thunderstore.io/c/ultrakill/p/Hydraxous/Configgy/"; public const string GITHUB_VERSION_URL = "https://api.github.com/repos/Hydraxous/Configgy/tags"; } public class ConfiggyPersistent<T> : ConfigValueElement<T> { public ConfiggyPersistent(T defaultValue) : base(defaultValue) { } protected override void BuildElementCore(RectTransform rect) { } protected override void RefreshElementValueCore() { } } internal static class Paths { public static string ExecutionPath => Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); public static string GameFolder => Path.GetDirectoryName(Application.dataPath); public static string BepInExFolder => Path.Combine(GameFolder, "BepInEx"); public static string BepInExConfigFolder => Path.Combine(BepInExFolder, "config"); public static string DataFolder => Path.Combine(BepInExConfigFolder, "Configgy"); public static string LegacyDataFolder => Path.Combine(ExecutionPath, "Configs"); public static void CheckFolders() { if (!Directory.Exists(DataFolder)) { Directory.CreateDirectory(DataFolder); } } } [Serializable] public class SerializedConfiggable { [JsonProperty] private string value; [JsonIgnore] private object obj; [JsonIgnore] private Type type; [JsonProperty] public string key { get; } public SerializedConfiggable(string key, object value) { this.key = key; SetValue(value); } [JsonConstructor] protected SerializedConfiggable(string key, string jsonValue) { this.key = key; value = jsonValue; } public string GetSerialized() { return value; } public T GetValue<T>() { return JsonConvert.DeserializeObject<T>(value); } public void SetValue(object value) { obj = value; type = value.GetType(); this.value = JsonConvert.SerializeObject(value, type, (Formatting)1, (JsonSerializerSettings)null); } public bool IsValid() { if (string.IsNullOrEmpty(value)) { return false; } if (string.IsNullOrEmpty(key)) { return false; } return true; } } public static class Extensions { public static Transform[] GetChildren(this Transform tf) { int childCount = tf.childCount; Transform[] array = (Transform[])(object)new Transform[childCount]; for (int i = 0; i < childCount; i++) { array[i] = tf.GetChild(i); } return array; } public static T GetDefault<T>(this ConfigEntry<T> entry) { return (T)((ConfigEntryBase)entry).DefaultValue; } public static T GetTag<T>(this ConfigEntryBase entry) where T : class { object result; if (entry == null) { result = null; } else { ConfigDescription description = entry.Description; if (description == null) { result = null; } else { object[] tags = description.Tags; if (tags == null) { result = null; } else { IEnumerable<T> enumerable = tags.OfType<T>(); result = ((enumerable != null) ? enumerable.FirstOrDefault() : null); } } } return (T)result; } public static bool IsAcceptableValueList(this AcceptableValueBase domain) { if (domain == null) { return false; } if (!((object)domain).GetType().IsGenericType) { return false; } if (((object)domain).GetType().GetGenericTypeDefinition() != typeof(AcceptableValueList<>)) { return false; } return true; } } internal static class LegacyConfigPorter { public static void PortLegacyConfig(string guid) { } } public static class Pauser { private static GameState configState = new GameState("configgyPause"); private static List<GameObject> pauserObjects = new List<GameObject>(); private const string pauseKey = "ConfiggyPauser"; private static BehaviourRelay watcher; public static bool Paused => GameStateManager.Instance.IsStateActive("ConfiggyPauser"); public static void Pause(GameObject origin) { pauserObjects = pauserObjects.Where((GameObject x) => (Object)(object)x != (Object)null && x.activeInHierarchy).Distinct().ToList(); if (!pauserObjects.Contains(origin)) { pauserObjects.Add(origin); } CheckWatcher(); SetPaused(paused: true); } public static void Pause(params GameObject[] origins) { pauserObjects = pauserObjects.Where((GameObject x) => (Object)(object)x != (Object)null && x.activeInHierarchy).Distinct().ToList(); for (int i = 0; i < origins.Length; i++) { if (!pauserObjects.Contains(origins[i])) { pauserObjects.Add(origins[i]); } } CheckWatcher(); SetPaused(paused: true); } private static void CheckWatcher() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)watcher == (Object)null) { watcher = new GameObject("ConfiggyPauserWatcher").AddComponent<BehaviourRelay>(); ((Object)watcher).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)((Component)watcher).gameObject); ((MonoBehaviour)watcher).StartCoroutine(PauseWatcher()); } } private static void SetPaused(bool paused) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) if (paused != Paused) { configState = new GameState("ConfiggyPauser"); configState.cursorLock = (LockMode)2; configState.playerInputLock = (LockMode)1; configState.cameraInputLock = (LockMode)1; configState.priority = 20; Time.timeScale = (paused ? 0f : 1f); MonoSingleton<OptionsManager>.Instance.paused = paused; ((Behaviour)MonoSingleton<NewMovement>.Instance).enabled = !paused; ((Behaviour)MonoSingleton<CameraController>.Instance).enabled = !paused; MonoSingleton<GunControl>.Instance.activated = !paused; if (paused) { GameStateManager.Instance.RegisterState(configState); } else { GameStateManager.Instance.PopState("ConfiggyPauser"); } } } private static IEnumerator PauseWatcher() { while (true) { if (Paused && !RemainPaused()) { SetPaused(paused: false); } yield return null; } } private static bool RemainPaused() { for (int i = 0; i < pauserObjects.Count; i++) { if (!((Object)(object)pauserObjects[i] == (Object)null) && pauserObjects[i].activeInHierarchy) { return true; } } return false; } public static void Unpause(GameObject origin = null) { if ((Object)(object)origin != (Object)null && pauserObjects.Contains(origin)) { pauserObjects.Remove(origin); } pauserObjects = pauserObjects.Where((GameObject x) => (Object)(object)x != (Object)null && x.activeInHierarchy).ToList(); if (pauserObjects.Count <= 0) { SetPaused(paused: false); } } } [BepInPlugin("Hydraxous.ULTRAKILL.Configgy", "Configgy", "1.0.4")] [BepInProcess("ULTRAKILL.exe")] public class Plugin : BaseUnityPlugin { private Harmony harmony; private ConfigBuilder configgyConfig; public static bool UsingLatest = true; [Configgable("", null, 0, null)] private static ConfiggyPersistent<bool> savedBoolean = new ConfiggyPersistent<bool>(defaultValue: true); public static string LatestVersion { get; private set; } = "1.0.4"; private void Awake() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown PluginAssets.Initialize(); harmony = new Harmony("Hydraxous.ULTRAKILL.Configgy.harmony"); harmony.PatchAll(); Paths.CheckFolders(); configgyConfig = new ConfigBuilder("Hydraxous.ULTRAKILL.Configgy", "Configgy"); configgyConfig.BuildAll(); VersionCheck.CheckVersion("https://api.github.com/repos/Hydraxous/Configgy/tags", "1.0.4", delegate(bool r, string latest) { UsingLatest = r; if (!UsingLatest) { LatestVersion = latest; Debug.LogWarning((object)("New version of Configgy available. Current:(1.0.4) Latest: (" + LatestVersion + ")")); } }); SceneManager.sceneLoaded += SceneManager_sceneLoaded; ((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin Configgy is loaded!"); } private void Update() { if (Input.GetKeyDown((KeyCode)107)) { savedBoolean.SetValue(!savedBoolean.GetValue()); Debug.Log((object)savedBoolean.Value); } } private void SceneManager_sceneLoaded(Scene _, LoadSceneMode __) { if (!(SceneHelper.CurrentScene != "Main Menu")) { BepinAutoGenerator.Generate(); } } } public class ConfigButton : IConfigElement { public Action OnPress; private string label; private Button instancedButton; private Text buttonText; private ConfiggableAttribute descriptor; public Button GetButton() { return instancedButton; } public Text GetButtonLabel() { return buttonText; } public ConfigButton(Action onPress, string label = null) { OnPress = onPress; this.label = label; } public void BindDescriptor(ConfiggableAttribute descriptor) { this.descriptor = descriptor; } public ConfiggableAttribute GetDescriptor() { return descriptor; } public string GetLabel() { if (!string.IsNullOrEmpty(label)) { return label; } if (descriptor != null) { return descriptor.DisplayName; } return OnPress.Method.Name; } private void OnButtonPressed() { OnPress?.Invoke(); } public void SetLabel(string label) { this.label = label; if ((Object)(object)buttonText != (Object)null) { buttonText.text = GetLabel(); } } public void BuildElement(RectTransform rect) { DynUI.Frame(rect, delegate(Frame panel) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) panel.RectTransform.sizeDelta = new Vector2(panel.RectTransform.sizeDelta.x, 55f); DynUI.Button(panel.RectTransform, delegate(Button b) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown instancedButton = b; (buttonText = ((Component)b).GetComponentInChildren<Text>()).text = GetLabel(); RectTransform component = ((Component)b).GetComponent<RectTransform>(); DynUI.Layout.FillParent(component); ((UnityEvent)b.onClick).AddListener(new UnityAction(OnButtonPressed)); }); }); } public void OnMenuOpen() { } public void OnMenuClose() { } public void BindConfig(ConfigBuilder configBuilder) { } } public class ConfigCustomElement : IConfigElement { private Action<ConfiggableAttribute, RectTransform> onBuild; private ConfiggableAttribute configgable; protected ConfigBuilder config; public Action OnMenuClosed; public Action OnMenuOpened; public ConfigCustomElement(Action<ConfiggableAttribute, RectTransform> onBuild) { this.onBuild = onBuild; } public void BindDescriptor(ConfiggableAttribute configgable) { this.configgable = configgable; } public void BuildElement(RectTransform rect) { onBuild?.Invoke(configgable, rect); } public ConfiggableAttribute GetDescriptor() { return configgable; } public void OnMenuOpen() { OnMenuOpened?.Invoke(); } public void OnMenuClose() { OnMenuClosed?.Invoke(); } public void BindConfig(ConfigBuilder configBuilder) { config = configBuilder; } } public class ConfigDropdown<T> : ConfigValueElement<T> { protected int defaultIndex; protected int? currentIndex; protected Dropdown instancedDropdown; public string[] Names { get; private set; } public T[] Values { get; private set; } public ConfigDropdown(T[] values, string[] names = null, int defaultIndex = 0) : base(values[defaultIndex]) { Values = values; Names = CreateNames(values, names); this.defaultIndex = defaultIndex; OnValueChanged = (Action<T>)Delegate.Combine(OnValueChanged, (Action<T>)delegate { RefreshElementValue(); }); RefreshElementValue(); } public ConfigDropdown(T[] values, T defaultValue, string[] names = null) : this(values, names, Mathf.Max(0, Array.FindIndex(values, (T v) => defaultValue.Equals(v)))) { } public static ConfigDropdown<T> ForEnum(T defaultValue) { T[] values = Enum.GetValues(typeof(T)).Cast<T>().ToArray(); string[] names = Enum.GetNames(typeof(T)); return new ConfigDropdown<T>(values, defaultValue, names); } private string[] CreateNames(T[] values, string[] providedNames) { if (providedNames == null) { return values.Select((T x) => x.ToString()).ToArray(); } string[] array = new string[values.Length]; for (int i = 0; i < values.Length; i++) { array[i] = ((i < providedNames.Length) ? providedNames[i] : values[i].ToString()); } return array; } public void SetOptions(T[] values, string[] names = null, int newIndex = 0, int defaultIndex = 0) { int num = values.Length; if (defaultIndex >= num || defaultIndex < 0) { throw new IndexOutOfRangeException("Default index is out of bounds with provided values."); } if (newIndex >= num || newIndex < 0) { throw new IndexOutOfRangeException("Default index is out of bounds with provided values."); } Values = values; Names = CreateNames(values, names); this.defaultIndex = defaultIndex; SetIndex(newIndex); } protected override void LoadValueCore() { firstLoadDone = true; if (config.TryGetValueAtAddress<int>(descriptor.SerializationAddress, out var indexCore)) { try { SetIndexCore(indexCore); return; } catch (Exception ex) { Debug.LogException(ex); } } ResetValue(); SaveValue(); } protected override void SaveValueCore() { object obj = currentIndex; config.SetValueAtAddress(descriptor.SerializationAddress, obj); config.SaveDeferred(); base.IsDirty = false; } protected override void ResetValueCore() { SetIndexCore(defaultIndex); } protected override T GetValueCore() { return Values[GetCurrentIndex()]; } public string GetSelectedIndexName() { return Names[GetCurrentIndex()]; } public int GetCurrentIndex() { return GetCurrentIndexCore(); } protected virtual int GetCurrentIndexCore() { if (!currentIndex.HasValue) { LoadValue(); } return currentIndex.Value; } protected void SetDropdown(Dropdown dropdown) { ((UnityEvent<int>)(object)dropdown.onValueChanged).AddListener((UnityAction<int>)delegate(int v) { SetValueFromDropdown(dropdown, v); }); instancedDropdown = dropdown; RefreshElementValue(); } protected void SetValueFromDropdown(Dropdown source, int newValue) { if (!((Object)(object)source != (Object)(object)instancedDropdown)) { SetIndex(newValue); } } protected void RefreshValue() { SetValue(Values[GetCurrentIndex()]); } protected override void SetValueCore(T value) { if (!Values.Contains(value)) { throw new KeyNotFoundException("Unable to set Dropdown's value directly. It is not contained within the values. Use SetValuesAndNames and SetIndex."); } base.SetValueCore(value); } public void SetIndex(int index) { if (index >= Values.Length || index < 0) { throw new IndexOutOfRangeException("Index is out of range of Dropdown's values."); } SetIndexCore(index); } protected virtual void SetIndexCore(int index) { currentIndex = index; RefreshValue(); } protected override void BuildElementCore(RectTransform rect) { DynUI.ConfigUI.CreateElementSlot(rect, this, delegate(RectTransform r) { DynUI.Dropdown(r, SetDropdown); }); } protected override void RefreshElementValueCore() { if (!((Object)(object)instancedDropdown == (Object)null)) { instancedDropdown.ClearOptions(); instancedDropdown.options = ((IEnumerable<string>)Names).Select((Func<string, OptionData>)((string x) => new OptionData(x))).ToList(); instancedDropdown.SetValueWithoutNotify(GetCurrentIndex()); instancedDropdown.RefreshShownValue(); } } } public class ConfigInputField<T> : ConfigValueElement<T> { protected Func<T, bool> inputValidator; protected Func<string, (bool, T)> valueConverter; public Func<T, string> toStringOverride; protected InputField instancedField; public ConfigInputField(T defaultValue, Func<T, bool> inputValidator = null, Func<string, (bool, T)> typeConverter = null) : base(defaultValue) { valueConverter = typeConverter ?? new Func<string, (bool, T)>(ValidateInputSyntax); this.inputValidator = inputValidator ?? ((Func<T, bool>)((T v) => true)); toStringOverride = null; OnValueChanged = (Action<T>)Delegate.Combine(OnValueChanged, (Action<T>)delegate { RefreshElementValue(); }); RefreshElementValue(); } private (bool, T) ValidateInputSyntax(string inputValue) { (bool, T) result = default((bool, T)); result.Item1 = false; result.Item2 = default(T); try { TypeConverter converter = TypeDescriptor.GetConverter(typeof(T)); object obj = converter.ConvertFromString(inputValue); result.Item2 = (T)obj; result.Item1 = result.Item2 != null; } catch (Exception ex) { Debug.LogException(ex); } return result; } private void SetValueFromString(InputField source, string input) { if ((Object)(object)source != (Object)(object)instancedField) { return; } (bool, T) tuple; try { tuple = valueConverter(input); if (!tuple.Item1) { Debug.LogError((object)"Syntax for field invalid! Conversion failed!"); RefreshElementValue(); return; } } catch (Exception ex) { Debug.LogException(ex); RefreshElementValue(); return; } if (!inputValidator(tuple.Item2)) { Debug.LogError((object)"Value validation failure. Rejected."); RefreshElementValue(); } else { SetValue(tuple.Item2); } } protected void SetInputField(InputField inputField) { ((UnityEvent<string>)(object)inputField.onEndEdit).AddListener((UnityAction<string>)delegate(string s) { SetValueFromString(inputField, s); }); instancedField = inputField; RefreshElementValue(); } protected override void RefreshElementValueCore() { if (!((Object)(object)instancedField == (Object)null)) { T arg = GetValue(); string text = null; text = ((toStringOverride == null) ? arg.ToString() : toStringOverride(arg)); instancedField.SetTextWithoutNotify(text); } } protected override void BuildElementCore(RectTransform rect) { DynUI.ConfigUI.CreateElementSlot(rect, this, delegate(RectTransform r) { DynUI.InputField(r, SetInputField); }); } } public class ConfigKeybind : ConfigValueElement<KeyCode> { private Text keybindText; private Button keybindButton; private ConfigurationPage page; public bool IsBeingRebound { get; private set; } public event Action OnRebindStart; public event Action OnRebindEnd; public ConfigKeybind(KeyCode keyCode) : base(keyCode) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) OnValueChanged = (Action<KeyCode>)Delegate.Combine(OnValueChanged, (Action<KeyCode>)delegate { RefreshElementValue(); }); RefreshElementValue(); } protected override void BuildElementCore(RectTransform rect) { IsBeingRebound = false; page = ((Component)rect).GetComponentInParent<ConfigurationPage>(); DynUI.ConfigUI.CreateElementSlot(rect, this, delegate(RectTransform r) { DynUI.Button(r, delegate(Button b) { SetKeybindButton(b); }); }); } private void SetKeybindButton(Button button) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown keybindButton = button; keybindText = ((Component)button).GetComponentInChildren<Text>(); ((UnityEvent)keybindButton.onClick).AddListener(new UnityAction(StartRebinding)); } private void StartRebinding() { if ((Object)(object)page == (Object)null) { page = ((Component)keybindButton).GetComponentInParent<ConfigurationPage>(); } if ((Object)(object)page == (Object)null) { Debug.LogError((object)"Page could not be found?"); return; } keybindText.text = "<color=orange>???</color>"; ((Selectable)keybindButton).interactable = false; IsBeingRebound = true; page.preventClosing = true; ((MonoBehaviour)page).StartCoroutine(RebindProcess()); this.OnRebindStart?.Invoke(); } public bool IsPressed() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Invalid comparison between Unknown and I4 //IL_0021: Unknown result type (might be due to invalid IL or missing references) if (IsBeingRebound) { return false; } if ((int)base.Value == 0) { return false; } return Input.GetKey(base.Value); } public bool WasPeformed() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Invalid comparison between Unknown and I4 //IL_0021: Unknown result type (might be due to invalid IL or missing references) if (IsBeingRebound) { return false; } if ((int)base.Value == 0) { return false; } return Input.GetKeyDown(base.Value); } public bool WasReleased() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Invalid comparison between Unknown and I4 //IL_0021: Unknown result type (might be due to invalid IL or missing references) if (IsBeingRebound) { return false; } if ((int)base.Value == 0) { return false; } return Input.GetKeyUp(base.Value); } protected override void RefreshElementValueCore() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)keybindText == (Object)null)) { Text obj = keybindText; KeyCode val = GetValue(); obj.text = ((object)(KeyCode)(ref val)).ToString(); } } private void FinishRebind(KeyCode keycode) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) ((Selectable)keybindButton).interactable = true; page.preventClosing = false; IsBeingRebound = false; SetValue(keycode); this.OnRebindEnd?.Invoke(); } private IEnumerator RebindProcess() { float timer = 10f; IsBeingRebound = true; KeyCode currentKeyCode = base.Value; int counter = 0; yield return (object)new WaitForSecondsRealtime(0.18f); while (IsBeingRebound && timer > 0f) { yield return null; timer -= Time.deltaTime; Event current = Event.current; if ((int)current.type != 4 && (int)current.type != 5) { continue; } KeyCode keyCode = current.keyCode; KeyCode val = keyCode; KeyCode val2 = val; if ((int)val2 != 0) { if ((int)val2 == 27) { FinishRebind((KeyCode)0); } else { FinishRebind(current.keyCode); } yield break; } counter++; } FinishRebind(currentKeyCode); } } public class ConfigLabel : IConfigElement { private ConfiggableAttribute descriptor; private Text label; private string labelText; private float height; public ConfigLabel(string label, float height = 55f) { labelText = label; this.height = 55f; } public void SetHeight(float height) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) this.height = height; if (Object.op_Implicit((Object)(object)label)) { ((Component)label).GetComponent<RectTransform>().sizeDelta = new Vector2(0f, height); } } public Text GetLabel() { return label; } public string GetCurrentText() { return labelText; } public void SetText(string label) { labelText = label; if (Object.op_Implicit((Object)(object)this.label)) { this.label.text = label; } } void IConfigElement.BindConfig(ConfigBuilder configBuilder) { } void IConfigElement.BindDescriptor(ConfiggableAttribute configgable) { descriptor = configgable; } void IConfigElement.BuildElement(RectTransform rect) { DynUI.Label(rect, delegate(Text t) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) label = t; label.text = labelText; RectTransform component = ((Component)label).GetComponent<RectTransform>(); DynUI.Layout.CenterAnchor(component); component.sizeDelta = new Vector2(0f, height); }); } ConfiggableAttribute IConfigElement.GetDescriptor() { return descriptor; } void IConfigElement.OnMenuClose() { } void IConfigElement.OnMenuOpen() { } } public abstract class ConfigSlider<T> : ConfigValueElement<T> { protected Slider instancedSlider; protected Text outputText; public T Min { get; } public T Max { get; } public ConfigSlider(T defaultValue, T min, T max) : base(defaultValue) { Min = min; Max = max; } protected virtual void SetValueFromSlider(Slider origin, float sliderValue) { if (!((Object)(object)origin != (Object)(object)instancedSlider)) { SetValueFromSlider(sliderValue); } } protected abstract void ConfigureSliderRange(Slider slider); protected abstract void SetValueFromSlider(float value); protected void SetSlider(Slider slider) { ((UnityEvent<float>)(object)slider.onValueChanged).AddListener((UnityAction<float>)delegate(float v) { SetValueFromSlider(slider, v); }); ConfigureSliderRange(slider); instancedSlider = slider; RefreshElementValue(); } protected override void RefreshElementValueCore() { if (!((Object)(object)instancedSlider == (Object)null) && (Object)(object)outputText != (Object)null) { outputText.text = ToString(); } } protected override void BuildElementCore(RectTransform rect) { DynUI.ConfigUI.CreateElementSlot(rect, this, delegate(RectTransform r) { DynUI.Label(r, delegate(Text t) { outputText = t; }); DynUI.Slider(r, SetSlider); }); } } public class ConfigToggle : ConfigValueElement<bool> { protected Toggle instancedToggle; public ConfigToggle(bool defaultValue) : base(defaultValue) { OnValueChanged = (Action<bool>)Delegate.Combine(OnValueChanged, (Action<bool>)delegate { RefreshElementValue(); }); } protected override void RefreshElementValueCore() { if (!((Object)(object)instancedToggle == (Object)null)) { instancedToggle.SetIsOnWithoutNotify(GetValue()); } } protected void SetToggle(Toggle toggle) { ((UnityEvent<bool>)(object)toggle.onValueChanged).AddListener((UnityAction<bool>)delegate(bool v) { SetValueFromToggle(toggle, v); }); instancedToggle = toggle; RefreshElementValue(); } protected override void LoadValueCore() { base.LoadValueCore(); RefreshElementValue(); } protected void SetValueFromToggle(Toggle source, bool newValue) { if (!((Object)(object)source != (Object)(object)instancedToggle)) { SetValue(newValue); } } protected override void BuildElementCore(RectTransform rect) { DynUI.ConfigUI.CreateElementSlot(rect, this, delegate(RectTransform r) { DynUI.Toggle(r, SetToggle); }); } } public abstract class ConfigValueElement : IConfigElement { protected ConfiggableAttribute descriptor; protected ConfigBuilder config; protected bool firstLoadDone = false; private bool initialized => descriptor != null; public bool IsDirty { get; protected set; } public abstract Type ConfigValueType { get; } protected abstract void BuildElementCore(RectTransform rect); internal abstract void BindField(FieldInfo field); protected abstract void LoadValueCore(); protected abstract void SaveValueCore(); protected abstract void ResetValueCore(); protected abstract void RefreshElementValueCore(); public void LoadValue() { if (initialized) { LoadValueCore(); firstLoadDone = true; } } public void SaveValue() { SaveValueCore(); } public void ResetValue() { ResetValueCore(); } public void RefreshElementValue() { RefreshElementValueCore(); } public void BuildElement(RectTransform rect) { if (initialized) { BuildElementCore(rect); } } public void OnMenuOpen() { RefreshElementValue(); } public void OnMenuClose() { if (IsDirty) { SaveValue(); } } void IConfigElement.BindDescriptor(ConfiggableAttribute configgable) { descriptor = configgable; } ConfiggableAttribute IConfigElement.GetDescriptor() { return descriptor; } void IConfigElement.BindConfig(ConfigBuilder config) { this.config = config; } public static ConfigValueElement<T> Create<T>(T defaultValue) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) if (1 == 0) { } ConfigValueElement configValueElement; if (defaultValue is bool) { object obj = defaultValue; bool defaultValue2 = (bool)((obj is bool) ? obj : null); configValueElement = new ConfigToggle(defaultValue2); } else if (defaultValue is Vector2) { object obj2 = defaultValue; Vector2 defaultValue3 = (Vector2)((obj2 is Vector2) ? obj2 : null); configValueElement = new ConfigVector2(defaultValue3); } else if (defaultValue is Vector3) { object obj3 = defaultValue; Vector3 defaultValue4 = (Vector3)((obj3 is Vector3) ? obj3 : null); configValueElement = new ConfigVector3(defaultValue4); } else if (defaultValue is Quaternion) { object obj4 = defaultValue; Quaternion defaultValue5 = (Quaternion)((obj4 is Quaternion) ? obj4 : null); configValueElement = new ConfigQuaternion(defaultValue5); } else if (defaultValue is Color) { object obj5 = defaultValue; Color defaultValue6 = (Color)((obj5 is Color) ? obj5 : null); configValueElement = new ConfigColor(defaultValue6); } else if (!(defaultValue is KeyCode)) { configValueElement = ((defaultValue is Enum) ? ((ConfigValueElement<T>)ConfigDropdown<T>.ForEnum(defaultValue)) : ((ConfigValueElement<T>)((!(defaultValue is sbyte) && !(defaultValue is short) && !(defaultValue is int) && !(defaultValue is long) && !(defaultValue is byte) && !(defaultValue is ushort) && !(defaultValue is uint) && !(defaultValue is ulong) && !(defaultValue is float) && !(defaultValue is double) && !(defaultValue is char) && !(defaultValue is string)) ? null : new ConfigInputField<T>(defaultValue)))); } else { object obj6 = defaultValue; KeyCode keyCode = (KeyCode)((obj6 is KeyCode) ? obj6 : null); configValueElement = new ConfigKeybind(keyCode); } if (1 == 0) { } ConfigValueElement configValueElement2 = configValueElement; if (configValueElement2 == null) { return null; } return (ConfigValueElement<T>)configValueElement2; } } public abstract class ConfigValueElement<T> : ConfigValueElement { protected readonly T defaultValue; protected internal T? value; public Action<T> OnValueChanged; public sealed override Type ConfigValueType => typeof(T); public virtual T DefaultValue => defaultValue; public T Value => GetValue(); public ConfigValueElement(T defaultValue) { this.defaultValue = defaultValue; } protected override void LoadValueCore() { firstLoadDone = true; if (descriptor == null || config == null) { return; } if (config.TryGetValueAtAddress<T>(descriptor.SerializationAddress, out var val)) { try { SetValue(val); return; } catch (Exception ex) { Debug.LogException(ex); } } ResetValue(); } protected override void SaveValueCore() { object obj = GetValue(); config.SetValueAtAddress(descriptor.SerializationAddress, obj); config.SaveDeferred(); base.IsDirty = false; } public T GetValue() { return GetValueCore(); } protected virtual T GetValueCore() { if (value == null || !firstLoadDone) { LoadValue(); } return value; } public void SetValue(T value) { SetValueCore(value); base.IsDirty = true; } protected virtual void SetValueCore(T value) { this.value = value; OnValueChanged?.Invoke(value); } protected override void ResetValueCore() { SetValue(DefaultValue); } public override string ToString() { return GetValue().ToString(); } internal sealed override void BindField(FieldInfo field) { OnValueChanged = (Action<T>)Delegate.Combine(OnValueChanged, (Action<T>)delegate(T v) { field.SetValue(null, v); }); } } public class FloatSlider : ConfigSlider<float> { public FloatSlider(float defaultValue, float min, float max) : base(defaultValue, min, max) { } protected override void BuildElementCore(RectTransform rect) { base.BuildElementCore(rect); instancedSlider.wholeNumbers = false; OnValueChanged = (Action<float>)Delegate.Combine(OnValueChanged, (Action<float>)delegate { RefreshElementValue(); }); RefreshElementValue(); } protected override void ConfigureSliderRange(Slider slider) { slider.minValue = base.Min; slider.maxValue = base.Max; } protected override void LoadValueCore() { base.LoadValueCore(); RefreshElementValue(); } protected override void SetValueFromSlider(float value) { SetValue(value); } protected override void RefreshElementValueCore() { base.RefreshElementValueCore(); if (!((Object)(object)instancedSlider == (Object)null)) { instancedSlider.SetValueWithoutNotify(GetValue()); } } } public class IntegerSlider : ConfigSlider<int> { public IntegerSlider(int defaultValue, int min, int max) : base(defaultValue, min, max) { } protected override void BuildElementCore(RectTransform rect) { base.BuildElementCore(rect); instancedSlider.wholeNumbers = true; OnValueChanged = (Action<int>)Delegate.Combine(OnValueChanged, (Action<int>)delegate { RefreshElementValue(); }); RefreshElementValue(); } protected override void ConfigureSliderRange(Slider slider) { slider.minValue = base.Min; slider.maxValue = base.Max; } protected override void LoadValueCore() { base.LoadValueCore(); RefreshElementValue(); } protected override void SetValueFromSlider(float value) { SetValue((int)value); } protected override void RefreshElementValueCore() { base.RefreshElementValueCore(); if (!((Object)(object)instancedSlider == (Object)null)) { instancedSlider.SetValueWithoutNotify((float)GetValue()); } } } public class ConfigColor : ConfigValueElement<Color> { private SerializedColor serializedColor; private Slider[] sliders; private InputField hexInput; private Image colorDisplay; public ConfigColor(Color defaultValue) : base(defaultValue) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) OnValueChanged = (Action<Color>)Delegate.Combine(OnValueChanged, (Action<Color>)delegate { RefreshElementValue(); }); OnValueChanged = (Action<Color>)Delegate.Combine(OnValueChanged, new Action<Color>(UpdateColorDisplayColor)); serializedColor = new SerializedColor(defaultValue); sliders = (Slider[])(object)new Slider[4]; } protected override void BuildElementCore(RectTransform rect) { DynUI.ConfigUI.CreateElementSlot(rect, this, delegate(RectTransform r) { DynUI.InputField(r, SetInputField); int j; for (j = 0; j < sliders.Length; j++) { DynUI.Slider(r, delegate(Slider s) { SetSlider(s, j); }); } DynUI.ImageButton(r, delegate(Button b, Image i) { Object.Destroy((Object)(object)b); SetColorDisplay(i); }); }); } private void SetColorDisplay(Image image) { image.sprite = null; colorDisplay = image; } private void UpdateColorDisplayColor(Color color) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)colorDisplay == (Object)null)) { ((Graphic)colorDisplay).color = color; } } protected override void LoadValueCore() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) firstLoadDone = true; if (config.TryGetValueAtAddress<SerializedColor>(descriptor.SerializationAddress, out var serializedColor)) { try { SetValue(serializedColor.ToColor()); return; } catch (Exception ex) { Debug.LogException(ex); } } ResetValue(); } private string ToHex(Color color) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return ColorUtility.ToHtmlStringRGBA(color) ?? ""; } private bool TryParseHex(string hex, out Color color) { return ColorUtility.TryParseHtmlString(hex, ref color); } protected override void SaveValueCore() { object obj = serializedColor; config.SetValueAtAddress(descriptor.SerializationAddress, obj); config.SaveDeferred(); base.IsDirty = false; } private void SetInputField(InputField input) { if ((Object)(object)input == (Object)null) { return; } hexInput = input; ((UnityEvent<string>)(object)input.onEndEdit).AddListener((UnityAction<string>)delegate(string s) { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) if (!s.StartsWith("#")) { s = "#" + s; } if (TryParseHex(s, out var color)) { serializedColor = new SerializedColor(color); SetValue(color); } else { input.SetTextWithoutNotify(ToHex(serializedColor.ToColor())); } }); } private void SetSlider(Slider slider, int index) { sliders[index] = slider; ((UnityEvent<float>)(object)slider.onValueChanged).AddListener((UnityAction<float>)delegate(float v) { SetValueFromSlider(index, v); }); slider.minValue = 0f; slider.maxValue = 1f; slider.wholeNumbers = false; } private void SetValueFromSlider(int index, float value) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) serializedColor[index] = value; SetValue(serializedColor.ToColor()); } protected override void SetValueCore(Color value) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) base.value = value; serializedColor = new SerializedColor(value); OnValueChanged?.Invoke(value); } protected override void RefreshElementValueCore() { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) if (sliders == null) { return; } for (int i = 0; i < sliders.Length; i++) { if ((Object)(object)sliders[i] == (Object)null) { return; } sliders[i].SetValueWithoutNotify(serializedColor[i]); } hexInput.SetTextWithoutNotify(ToHex(serializedColor.ToColor())); UpdateColorDisplayColor(serializedColor.ToColor()); } } [Serializable] public struct SerializedColor { public float r; public float g; public float b; public float a; public float this[int index] { get { return index switch { 0 => r, 1 => g, 2 => b, 3 => a, _ => throw new IndexOutOfRangeException("Index is out of range of SerializedColor's values."), }; } set { switch (index) { case 0: r = value; break; case 1: g = value; break; case 2: b = value; break; case 3: a = value; break; default: throw new IndexOutOfRangeException("Index is out of range of SerializedColor's values."); } } } public SerializedColor(Color color) { //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) r = color.r; g = color.g; b = color.b; a = color.a; } public Color ToColor() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) return new Color(r, g, b, a); } } public class ConfigQuaternion : ConfigInputField<Quaternion> { private float[] serializedQuaternion; public ConfigQuaternion(Quaternion defaultValue, Func<Quaternion, bool> inputValidator = null) : base(defaultValue, inputValidator, (Func<string, (bool, Quaternion)>)null) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) serializedQuaternion = new float[4] { defaultValue.x, defaultValue.y, defaultValue.z, defaultValue.w }; valueConverter = delegate(string v) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) if (v == "0") { return (true, Quaternion.identity); } if (v.ToLower() == "identity") { return (true, Quaternion.identity); } string[] array = v.Split(new char[1] { ',' }); if (array.Length != 3) { return (false, Quaternion.identity); } float[] array2 = array.Select((string x) => float.Parse(x)).ToArray(); return (true, Quaternion.Euler(new Vector3(array2[0], array2[1], array2[2]))); }; toStringOverride = (Quaternion v) => $"{((Quaternion)(ref v)).eulerAngles.x},{((Quaternion)(ref v)).eulerAngles.y},{((Quaternion)(ref v)).eulerAngles.z}"; } protected override void LoadValueCore() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) firstLoadDone = true; if (config.TryGetValueAtAddress<float[]>(descriptor.SerializationAddress, out var array)) { try { SetValue(new Quaternion(array[0], array[1], array[2], array[3])); return; } catch (Exception ex) { Debug.LogException(ex); } } ResetValue(); } protected override void SetValueCore(Quaternion value) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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_0060: Unknown result type (might be due to invalid IL or missing references) base.value = value; if (serializedQuaternion == null) { serializedQuaternion = new float[2]; } serializedQuaternion[0] = value.x; serializedQuaternion[1] = value.y; serializedQuaternion[2] = value.z; serializedQuaternion[3] = value.w; OnValueChanged?.Invoke(value); } protected override void SaveValueCore() { if (serializedQuaternion == null) { serializedQuaternion = new float[2]; } object obj = serializedQuaternion; config.SetValueAtAddress(descriptor.SerializationAddress, obj); config.SaveDeferred(); base.IsDirty = false; } } public class ConfigVector2 : ConfigInputField<Vector2> { private float[] serializedVector2; public ConfigVector2(Vector2 defaultValue, Func<Vector2, bool> inputValidator = null) : base(defaultValue, inputValidator, (Func<string, (bool, Vector2)>)null) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) serializedVector2 = new float[2] { defaultValue.x, defaultValue.y }; valueConverter = delegate(string v) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) if (v == "0") { return (true, Vector2.zero); } string[] array = v.Split(new char[1] { ',' }); if (array.Length != 2) { return (false, Vector2.zero); } float[] array2 = array.Select((string x) => float.Parse(x)).ToArray(); return (true, new Vector2(array2[0], array2[1])); }; toStringOverride = (Vector2 v) => $"{v.x},{v.y}"; } protected override void LoadValueCore() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) firstLoadDone = true; if (config.TryGetValueAtAddress<float[]>(descriptor.SerializationAddress, out var array)) { try { SetValue(new Vector2(array[0], array[1])); return; } catch (Exception ex) { Debug.LogException(ex); } } ResetValue(); } protected override void SetValueCore(Vector2 value) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) base.value = value; if (serializedVector2 == null) { serializedVector2 = new float[2]; } serializedVector2[0] = value.x; serializedVector2[1] = value.y; OnValueChanged?.Invoke(value); } protected override void SaveValueCore() { if (serializedVector2 == null) { serializedVector2 = new float[2]; } object obj = serializedVector2; config.SetValueAtAddress(descriptor.SerializationAddress, obj); config.SaveDeferred(); base.IsDirty = false; } } public class ConfigVector3 : ConfigInputField<Vector3> { private float[] serializedVector3; public ConfigVector3(Vector3 defaultValue, Func<Vector3, bool> inputValidator = null) : base(defaultValue, inputValidator, (Func<string, (bool, Vector3)>)null) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) serializedVector3 = new float[3] { defaultValue.x, defaultValue.y, defaultValue.z }; valueConverter = delegate(string v) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) if (v == "0") { return (true, Vector3.zero); } string[] array = v.Split(new char[1] { ',' }); if (array.Length != 3) { return (false, Vector3.zero); } float[] array2 = array.Select((string x) => float.Parse(x)).ToArray(); return (true, new Vector3(array2[0], array2[1], array2[2])); }; toStringOverride = (Vector3 v) => $"{v.x},{v.y},{v.z}"; } protected override void LoadValueCore() { //IL_0030: Unknown result type (might be due to invalid IL or missing references) firstLoadDone = true; if (config.TryGetValueAtAddress<float[]>(descriptor.SerializationAddress, out var array)) { try { SetValue(new Vector3(array[0], array[1], array[1])); return; } catch (Exception ex) { Debug.LogException(ex); } } ResetValue(); } protected override void SetValueCore(Vector3 value) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) base.value = value; if (serializedVector3 == null) { serializedVector3 = new float[3]; } serializedVector3[0] = value.x; serializedVector3[1] = value.y; serializedVector3[2] = value.z; OnValueChanged?.Invoke(value); } protected override void SaveValueCore() { if (serializedVector3 == null) { serializedVector3 = new float[3]; } object obj = serializedVector3; config.SetValueAtAddress(descriptor.SerializationAddress, obj); config.SaveDeferred(); base.IsDirty = false; } } public static class ExampleConfig { } public static class ModalDialogue { public static void ShowSimple(string title, string message, Action<bool> onComplete, string confirm = "Yes", string deny = "No") { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ModalDialogueManager.Instance == (Object)null) { Debug.LogError((object)"No ModalDialogueManager found in scene."); return; } ModalDialogueEvent modalDialogueEvent = new ModalDialogueEvent(); modalDialogueEvent.Title = title; modalDialogueEvent.Message = message; modalDialogueEvent.Options = new DialogueBoxOption[2] { new DialogueBoxOption { Name = confirm, Color = Color.white, OnClick = delegate { onComplete?.Invoke(obj: true); } }, new DialogueBoxOption { Name = deny, Color = Color.white, OnClick = delegate { onComplete?.Invoke(obj: false); } } }; ModalDialogueManager.Instance.RaiseDialogue(modalDialogueEvent); } public static void ShowDialogue(ModalDialogueEvent modalDialogueEvent) { if ((Object)(object)ModalDialogueManager.Instance == (Object)null) { Debug.LogError((object)"No ModalDialogueManager found in scene."); } else { ModalDialogueManager.Instance.RaiseDialogue(modalDialogueEvent); } } public static void ShowComplex(string title, string message, params DialogueBoxOption[] options) { if ((Object)(object)ModalDialogueManager.Instance == (Object)null) { Debug.LogError((object)"No ModalDialogueManager found in scene."); return; } ModalDialogueManager.Instance.RaiseDialogue(new ModalDialogueEvent { Title = title, Message = message, Options = options }); } } public class ModalDialogueManager : MonoBehaviour { [SerializeField] private GameObject blocker; [SerializeField] private GameObject dialogueBox; [SerializeField] private Text titleText; [SerializeField] private Text messageText; [SerializeField] private RectTransform buttonContainer; private Queue<ModalDialogueEvent> dialogueEvent = new Queue<ModalDialogueEvent>(); private List<GameObject> spawnedButtons = new List<GameObject>(); private bool runningCoroutine = false; private bool inDialogue = false; internal static ModalDialogueManager Instance { get; private set; } private void Awake() { Instance = this; blocker.SetActive(false); dialogueBox.SetActive(false); ((MonoBehaviour)this).StartCoroutine(SlowUpdate()); } private IEnumerator SlowUpdate() { while (true) { ((Component)this).transform.SetAsLastSibling(); yield return (object)new WaitForSecondsRealtime(2f); } } internal void RaiseDialogue(ModalDialogueEvent modalDialogueEvent) { if (modalDialogueEvent == null) { throw new ArgumentNullException("modalDialogueEvent is null!"); } dialogueEvent.Enqueue(modalDialogueEvent); if (!runningCoroutine) { runningCoroutine = true; ((MonoBehaviour)this).StartCoroutine(DialogueCoroutine()); } } private void ShowDialogue(ModalDialogueEvent modalDialogueEvent) { //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Expected O, but got Unknown inDialogue = true; dialogueBox.SetActive(true); if (string.IsNullOrEmpty(modalDialogueEvent.Title)) { titleText.text = ""; } else { titleText.text = "-- " + modalDialogueEvent.Title + " --"; } messageText.text = modalDialogueEvent.Message; for (int i = 0; i < modalDialogueEvent.Options.Length; i++) { DialogueBoxOption option = modalDialogueEvent.Options[i]; GameObject val = Object.Instantiate<GameObject>(PluginAssets.ButtonPrefab, (Transform)(object)buttonContainer); Button component = val.GetComponent<Button>(); Text componentInChildren = val.GetComponentInChildren<Text>(); Image val2 = (from x in val.GetComponentsInChildren<Image>() where ((Object)x).name == "Border" select x).FirstOrDefault(); spawnedButtons.Add(val); ((Graphic)componentInChildren).color = option.Color; componentInChildren.text = option.Name; ((Graphic)val2).color = option.Color; ((UnityEvent)component.onClick).AddListener((UnityAction)delegate { EndDialogue(); option.OnClick?.Invoke(); }); } } private void EndDialogue() { inDialogue = false; dialogueBox.SetActive(false); for (int i = 0; i < spawnedButtons.Count; i++) { if (!((Object)(object)spawnedButtons[i] == (Object)null)) { GameObject val = spawnedButtons[i]; spawnedButtons[i] = null; Object.Destroy((Object)(object)val); } } spawnedButtons.Clear(); } private IEnumerator DialogueCoroutine() { blocker.SetActive(true); Pauser.Pause(blocker); while (dialogueEvent.Count > 0) { ModalDialogueEvent dialogue = dialogueEvent.Dequeue(); ShowDialogue(dialogue); while (inDialogue) { yield return null; } } blocker.SetActive(false); runningCoroutine = false; Pauser.Unpause(); } } public struct DialogueBoxOption { public string Name; public Action OnClick; public Color Color; } public class ModalDialogueEvent { public string Title; public string Message; public DialogueBoxOption[] Options; } public static class VersionCheck { private static MonoBehaviour _behaviour; private static MonoBehaviour behaviour { get { //IL_0016: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_behaviour == (Object)null) { _behaviour = (MonoBehaviour)(object)new GameObject("VersionChecker").AddComponent<BehaviourRelay>(); } return _behaviour; } } public static void CheckVersion(string githubURL, string runningVersionName, Action<bool, string> onCheckComplete = null) { behaviour.StartCoroutine(CheckLatestVersion(githubURL, runningVersionName, onCheckComplete)); } private static IEnumerator CheckLatestVersion(string githubURL, string runningVersionName, Action<bool, string> onCheckComplete = null) { bool usingLatest = true; string latestVersionName = "UNKNOWN"; UnityWebRequest webRequest = UnityWebRequest.Get(githubURL); try { yield return webRequest.SendWebRequest(); if (!webRequest.isNetworkError) { string page = webRequest.downloadHandler.text; try { latestVersionName = JArray.Parse(page)[0].Value<string>((object)"name"); usingLatest = latestVersionName == runningVersionName; } catch (Exception ex) { Exception e = ex; usingLatest = true; latestVersionName = runningVersionName; Debug.LogError((object)$"Error getting version info for {runningVersionName}. {e}"); } } } finally { ((IDisposable)webRequest)?.Dispose(); } onCheckComplete(usingLatest, latestVersionName); } } } namespace Configgy.UI { public class ConfigurationMenu : MonoBehaviour { [SerializeField] private RectTransform contentbody; private ConfigurationPage rootPage; private Dictionary<string, ConfigurationPage> pageManifest = new Dictionary<string, ConfigurationPage>(); private bool menuBuilt = false; [Configgable("", "Open Config Menu", 0, null)] private static ConfigKeybind cfgKey = new ConfigKeybind((KeyCode)92); [Configgable("", "Notify When Update Available", 0, null)] private static ConfigToggle notifyOnUpdateAvailable = new ConfigToggle(defaultValue: true); private GameObject[] menus; private ConfigurationPage lastOpenPage; private bool menuOpen = false; internal static bool openedOnce; private static event Action onGlobalOpen; private static event Action<string> onGlobalOpenAtPath; private static event Action onGlobalClose; private void Awake() { if (!menuBuilt) { BuildMenus(ConfigurationManager.GetMenus()); } onGlobalOpen += OpenMenu; onGlobalClose += CloseMenu; onGlobalOpenAtPath += OpenMenuAtPath; ConfigurationManager.OnMenusChanged += BuildMenus; } private void Update() { if (menuOpen) { CheckMenuOpen(); } else if (cfgKey.WasPeformed()) { OpenMenu(); } } private void CheckMenuOpen() { if (menus == null) { return; } for (int i = 0; i < menus.Length; i++) { if (!((Object)(object)menus[i] == (Object)null) && menus[i].activeInHierarchy) { return; } } Unpause(); } internal void Rebuild() { BuildMenus(ConfigurationManager.GetMenus()); } private void DestroyPages() { ConfigurationPage[] array = pageManifest.Values.ToArray(); foreach (ConfigurationPage configurationPage in array) { Object.Destroy((Object)(object)((Component)configurationPage).gameObject); } pageManifest.Clear(); menuBuilt = false; } private void BuildMenus(ConfigBuilder[] menus) { DestroyPages(); Debug.Log((object)$"Building Configgy Menus {menus.Length}"); NewPage(delegate(ConfigurationPage mainPage) { rootPage = mainPage; mainPage.SetHeader("Configuration"); mainPage.Close(); pageManifest.Add("", rootPage); }); foreach (ConfigBuilder item in menus.OrderBy((ConfigBuilder x) => x.DisplayName)) { IConfigElement[] configElements = item.GetConfigElements(); if (configElements == null) { Debug.LogError((object)("ConfigBuilder: " + item.GUID + " has null elements. It cannot be built.")); } else { BuildMenu(configElements); } } } private void BuildMenu(IConfigElement[] configElements) { foreach (IConfigElement item in configElements.OrderBy((IConfigElement x) => x.GetDescriptor().Path)) { BuildElement(item); } foreach (KeyValuePair<string, ConfigurationPage> item2 in pageManifest) { item2.Value.RebuildPage(); } menuBuilt = true; } private void BuildMenuTreeFromPath(string fullPath) { string[] path = fullPath.Split(new char[1] { '/' }); string currentPathAddress = ""; ConfigurationPage previousPage = null; int i; for (i = 0; i < path.Length; i++) { currentPathAddress += path[i]; if (!pageManifest.ContainsKey(currentPathAddress)) { if ((Object)(object)previousPage == (Object)null) { previousPage = rootPage; } NewPage(delegate(ConfigurationPage page) { ConfigurationPage closablePage = previousPage; ConfigButton configElement = new ConfigButton(delegate { closablePage.Close(); page.Open(); }, path[i]); closablePage.AddElement(configElement); page.SetHeader(path[i]); page.SetParent(closablePage); ((Object)((Component)page).gameObject).name = currentPathAddress; page.SetFooter(currentPathAddress); page.Close(); previousPage = page; pageManifest.Add(currentPathAddress, page); }); } else { previousPage = pageManifest[currentPathAddress]; } currentPathAddress += "/"; } } private void BuildElement(IConfigElement element) { ConfiggableAttribute descriptor = element.GetDescriptor(); string text = ""; if (descriptor != null && descriptor.Owner != null) { text = descriptor.Owner.DisplayName ?? ""; if (!string.IsNullOrEmpty(descriptor.Path)) { text = text + "/" + descriptor.Path; } } else { text = "/Other"; } BuildMenuTreeFromPath(text); pageManifest[text].AddElement(element); } private void NewPage(Action<ConfigurationPage> onInstance) { GameObject val = Object.Instantiate<GameObject>(PluginAssets.ConfigurationPage, (Transform)(object)contentbody); ConfigurationPage page = val.GetComponent<ConfigurationPage>(); BehaviourRelay behaviourRelay = val.AddComponent<BehaviourRelay>(); behaviourRelay.OnOnEnable = (Action<GameObject>)Delegate.Combine(behaviourRelay.OnOnEnable, (Action<GameObject>)delegate { lastOpenPage = page; }); onInstance?.Invoke(page); } public void OpenMenu() { if (menuOpen) { return; } menus = (from x in ((Component)this).transform.GetChildren() select ((Component)x).gameObject).ToArray(); Pauser.Pause(menus); if ((Object)(object)lastOpenPage != (Object)null) { lastOpenPage.Open(); } else { rootPage.Open(); } menuOpen = true; if (!openedOnce) { openedOnce = true; if (!Plugin.UsingLatest && notifyOnUpdateAvailable.Value) { ShowUpdatePrompt(); } } } public void OpenMenuAtPath(string path) { if (string.IsNullOrEmpty(path)) { OpenMenu(); return; } menus = (from x in ((Component)this).transform.GetChildren() select ((Component)x).gameObject).ToArray(); Pauser.Pause(menus); string text = path; while (!pageManifest.ContainsKey(text) && !string.IsNullOrEmpty(text) && text != "/") { text = Path.GetDirectoryName(text); } if (string.IsNullOrEmpty(text) || !pageManifest.ContainsKey(text)) { OpenMenu(); return; } pageManifest[text].Open(); menuOpen = true; if (!openedOnce) { openedOnce = true; if (!Plugin.UsingLatest && notifyOnUpdateAvailable.Value) { ShowUpdatePrompt(); } } } private void ShowUpdatePrompt() { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //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) ModalDialogueEvent modalDialogueEvent = new ModalDialogueEvent(); modalDialogueEvent.Title = "Outdated"; modalDialogueEvent.Message = "You are using an outdated version of Configgy: (<color=red>1.0.4</color>). Please update to the latest version from Github or Thunderstore: (<color=green>" + Plugin.LatestVersion + "</color>)"; modalDialogueEvent.Options = new DialogueBoxOption[3] { new DialogueBoxOption { Name = "Open Browser", Color = Color.white, OnClick = delegate { Application.OpenURL("https://github.com/Hydraxous/Configgy//releases/latest"); } }, new DialogueBoxOption { Name = "Later", Color = Color.white, OnClick = delegate { } }, new DialogueBoxOption { Name = "Don't Ask Again.", Color = Color.red, OnClick = delegate { notifyOnUpdateAvailable.SetValue(value: false); } } }; ModalDialogue.ShowDialogue(modalDialogueEvent); } public void CloseMenu() { if (menuOpen) { menus = (from x in ((Component)this).transform.GetChildren() select ((Component)x).gameObject).ToArray(); for (int i = 0; i < menus.Length; i++) { menus[i].SetActive(false); } } } public static void Open() { ConfigurationMenu.onGlobalOpen?.Invoke(); } public static void OpenAtPath(string path) { ConfigurationMenu.onGlobalOpenAtPath?.Invoke(path); } public static void Close() { ConfigurationMenu.onGlobalClose?.Invoke(); } private void Unpause() { Pauser.Unpause(); menuOpen = false; } private void OnDestroy() { ConfigurationManager.OnMenusChanged -= BuildMenus; onGlobalOpen -= OpenMenu; onGlobalClose -= CloseMenu; onGlobalOpenAtPath -= OpenMenuAtPath; } } public class ConfigurationPage : MonoBehaviour { [SerializeField] private Text header; [SerializeField] private Text footer; [SerializeField] private Button backButton; [SerializeField] private Button closeButton; [SerializeField] private RectTransform contentBody; private List<IConfigElement> elements = new List<IConfigElement>(); public bool preventClosing = false; private string footerText; public ConfigurationPage Parent { get; private set; } private void Start() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown ((UnityEvent)backButton.onClick).AddListener(new UnityAction(Back)); ((UnityEvent)closeButton.onClick).AddListener(new UnityAction(Close)); } private void Update() { if (Input.GetKeyDown((KeyCode)27)) { EscapePressed(); } if (Input.GetKeyDown((KeyCode)8)) { BackspacePressed(); } } private void EscapePressed() { if (!preventClosing) { Close(); } } private void BackspacePressed() { if (preventClosing) { return; } InputField[] componentsInChildren = ((Component)contentBody).GetComponentsInChildren<InputField>(true); foreach (InputField val in componentsInChildren) { if (val.isFocused) { return; } } Back(); } public void SetParent(ConfigurationPage page) { Parent = page; } public void SetHeader(string headerText) { header.text = "-- " + headerText + " --"; } public void SetFooter(string footerText) { this.footerText = footerText; footer.text = footerText.TrimEnd('/', '\n', '\r'); } public void AddElement(IConfigElement configElement) { elements.Add(configElement); } public void ClearElements() { elements.Clear(); DestroyAllElements(); } private void DestroyAllElements() { Transform[] children = ((Transform)(object)contentBody).GetChildren(); for (int i = 0; i < children.Length; i++) { Transform val = children[i]; children[i] = null; Object.Destroy((Object)(object)((Component)val).gameObject); } } public void Open() { ((Component)this).gameObject.SetActive(true); } public void Back() { if ((Object)(object)Parent != (Object)null) { Parent.Open(); } ((Component)this).gameObject.SetActive(false); } public void Close() { ((Component)this).gameObject.SetActive(false); } public void RebuildPage() { DestroyAllElements(); foreach (IConfigElement item in elements.OrderBy((IConfigElement x) => x.GetDescriptor()?.OrderInList)) { if (item == null) { Debug.LogError((object)$"Configgy: Null element in page {footer}"); continue; } try { item.BuildElement(contentBody); } catch (Exception ex) { Debug.LogException(ex); } } } private void OnEnable() { ((Component)backButton).gameObject.SetActive((Object)(object)Parent != (Object)null); foreach (IConfigElement item in elements.OrderBy((IConfigElement x) => x.GetDescriptor()?.OrderInList)) { item.OnMenuOpen(); } } private void OnDisable() { foreach (IConfigElement item in elements.OrderBy((IConfigElement x) => x.GetDescriptor()?.OrderInList)) { item.OnMenuClose(); } } } public static class DynUI { public static class ConfigUI { public static void CreateElementSlot<T>(RectTransform rect, ConfigValueElement<T> valueElement, Action<RectTransform> onInstance, Action<RectTransform> onButtonSlots = null) { ConfiggableAttribute configgable = ((IConfigElement)valueElement).GetDescriptor(); Frame(rect, delegate(Frame f) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) f.RectTransform.sizeDelta = new Vector2(f.RectTransform.sizeDelta.x, 55f); Div(f.Content, delegate(RectTransform operatorsDiv) { operatorsDiv.SetAnchors(0f, 0f, 0.2f, 1f); Layout.Fill(operatorsDiv); DynUI.Component<HorizontalLayoutGroup>((Transform)(object)operatorsDiv, (Action<HorizontalLayoutGroup>)delegate(HorizontalLayoutGroup hlg) { ((HorizontalOrVerticalLayoutGroup)hlg).childForceExpandHeight = true; ((HorizontalOrVerticalLayoutGroup)hlg).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)hlg).childControlHeight = false; ((HorizontalOrVerticalLayoutGroup)hlg).childControlWidth = false; ((LayoutGroup)hlg).childAlignment = (TextAnchor)3; }); ImageButton(operatorsDiv, delegate(Button button, Image icon) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown RectTransform component2 = ((Component)button).GetComponent<RectTransform>(); component2.sizeDelta = new Vector2(40f, 40f); icon.sprite = PluginAssets.Icon_Reset; ((UnityEvent)button.onClick).AddListener(new UnityAction(valueElement.ResetValue)); }); if (!string.IsNullOrEmpty(configgable.Description)) { GameObject newDescriptionBox = null; Description(rect, delegate(RectTransform r, Text desc) { newDescriptionBox = ((Component)r).gameObject; desc.text = configgable.Description; ((Component)r).gameObject.SetActive(false); }); UnityAction val = default(UnityAction); ImageButton(operatorsDiv, delegate(Button button, Image icon) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_004e: Expected O, but got Unknown RectTransform component = ((Component)button).GetComponent<RectTransform>(); component.sizeDelta = new Vector2(40f, 40f); icon.sprite = PluginAssets.Icon_Info; ButtonClickedEvent onClick = button.onClick; UnityAction obj = val; if (obj == null) { UnityAction val2 = delegate { newDescriptionBox.SetActive(!newDescriptionBox.activeInHierarchy); }; UnityAction val3 = val2; val = val2; obj = val3; } ((UnityEvent)onClick).AddListener(obj); }); } onButtonSlots?.Invoke(operatorsDiv); }); Div(f.Content, delegate(RectTransform elementsDiv) { elementsDiv.SetAnchors(0.2f, 0f, 1f, 1f); Layout.Fill(elementsDiv); DynUI.Component<HorizontalLayoutGroup>((Transform)(object)elementsDiv, (Action<HorizontalLayoutGroup>)delegate(HorizontalLayoutGroup hlg) { ((HorizontalOrVerticalLayoutGroup)hlg).childForceExpandHeight = true; ((HorizontalOrVerticalLayoutGroup)hlg).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)hlg).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)hlg).childControlWidth = true; ((LayoutGroup)hlg).childAlignment = (TextAnchor)5; }); Label(elementsDiv, delegate(Text t) { t.text = configgable.DisplayName; t.fontSize = 4; t.resizeTextMaxSize = 25; }); onInstance?.Invoke(elementsDiv); }); }); } } public static class Layout { public static void HalfTop(RectTransform rt) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) rt.anchorMin = new Vector2(0f, 0.5f); rt.anchorMax = new Vector2(1f, 1f); } public static void HalfBottom(RectTransform rt) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) rt.anchorMin = new Vector2(0f, 0f); rt.anchorMax = new Vector2(1f, 0.5f); } public static void HalfLeft(RectTransform rt) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) rt.anchorMin = new Vector2(0f, 0f); rt.anchorMax = new Vector2(0.5f, 1f); } public static void HalfRight(RectTransform rt) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) rt.anchorMin = new Vector2(0f, 0f); rt.anchorMax = new Vector2(0.5f, 1f); } public static void FillParent(RectTransform rt) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) rt.anchorMin = new Vector2(0f, 0f); rt.anchorMax = new Vector2(1f, 1f); Fill(rt); } public static void Fill(RectTransform rt) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) rt.offsetMax = new Vector2(0f, 0f); rt.offsetMin = new Vector2(0f, 0f); rt.sizeDelta = new Vector2(0f, 0f); } public static void Padding(RectTransform rt, float padding) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) rt.anchoredPosition = new Vector2(0f - padding * 2f, 0f - padding * 2f); } public static void CenterAnchor(RectTransform rt) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) rt.anchorMin = new Vector2(0.5f, 0.5f); rt.anchorMax = new Vector2(0.5f, 0.5f); } } public static void Frame(RectTransform rect, Action<Frame> onInstance) { Instantiate<Frame>(rect, PluginAssets.FramePrefab, onInstance); } public static void Button(RectTransform rect, Action<Button> onInstance) { Instantiate<Button>(rect, PluginAssets.ButtonPrefab, onInstance); } public static void ImageButton(RectTransform rect, Action<Button, Image> onInstance) { Action<Button> onInstance2 = delegate(Button b) { Image arg = (from x in ((Component)b).GetComponentsInChildren<Image>() where ((Object)x).name == "Icon" select x).FirstOrDefault(); onInstance?.Invoke(b, arg); }; Instantiate<Button>(rect, PluginAssets.ImageButtonPrefab, onInstance2); } public static void ScrollRect(RectTransform rect, Action<ScrollRect> onInstance) { Instantiate<ScrollRect>(rect, PluginAssets.ScrollRectPrefab, onInstance); } public static void Label(RectTransform rect, Action<Text> onInstance) { Instantiate<Text>(rect, PluginAssets.TextPrefab, onInstance); } public static void InputField(RectTransform rect, Action<InputField> onInstance) { Instantiate<InputField>(rect, PluginAssets.InputFieldPrefab, onInstance); } public static void Slider(RectTransform rect, Action<Slider> onInstance) { Instantiate<Slider>(rect, PluginAssets.SliderPrefab, onInstance); } public static void Toggle(RectTransform rect, Action<Toggle> onInstance) { Instantiate<Toggle>(rect, PluginAssets.TogglePrefab, onInstance); } public static void Dropdown(