using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Shared;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("ModMenu")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ModMenu")]
[assembly: AssemblyTitle("ModMenu")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace Shared
{
internal static class LegacyConfig
{
internal static void Adopt(BaseUnityPlugin plugin)
{
try
{
string configFilePath = plugin.Config.ConfigFilePath;
string directoryName = Path.GetDirectoryName(configFilePath);
if (File.Exists(configFilePath) || directoryName == null || !Directory.Exists(directoryName))
{
return;
}
string fileName = Path.GetFileName(configFilePath);
if (fileName.StartsWith("crackmods"))
{
string text = "crack" + fileName.Substring("crackmods".Length);
string text2 = Directory.GetFiles(directoryName, "com.*." + text).FirstOrDefault();
if (text2 != null)
{
File.Move(text2, configFilePath);
plugin.Config.Reload();
}
}
}
catch (IOException)
{
}
}
}
}
namespace ModMenu
{
internal sealed class Attrs
{
public bool Hidden;
public bool ReadOnly;
public bool Advanced;
public bool HideDefault;
public bool Percent;
public int Order;
public string Name;
public string Category;
public string Description;
public object Default;
public Func<object, string> ObjToStr;
public Func<string, object> StrToObj;
public static Attrs Of(ConfigEntryBase entry)
{
Attrs attrs = new Attrs
{
Default = entry.DefaultValue
};
ConfigDescription description = entry.Description;
object[] array = ((description != null) ? description.Tags : null);
if (array == null)
{
return attrs;
}
object[] array2 = array;
foreach (object obj in array2)
{
if (obj == null)
{
continue;
}
if (!(obj is DisplayNameAttribute displayNameAttribute))
{
if (!(obj is CategoryAttribute categoryAttribute))
{
if (!(obj is DescriptionAttribute descriptionAttribute))
{
if (!(obj is DefaultValueAttribute defaultValueAttribute))
{
if (!(obj is ReadOnlyAttribute readOnlyAttribute))
{
if (!(obj is BrowsableAttribute browsableAttribute))
{
if (obj is string text)
{
switch (text)
{
case "ReadOnly":
attrs.ReadOnly = true;
break;
case "Browsable":
attrs.Hidden = false;
break;
case "Unbrowsable":
case "Hidden":
attrs.Hidden = true;
break;
case "Advanced":
attrs.Advanced = true;
break;
}
}
else if (obj.GetType().Name == "ConfigurationManagerAttributes")
{
attrs.Read(obj);
}
}
else
{
attrs.Hidden = !browsableAttribute.Browsable;
}
}
else
{
attrs.ReadOnly = readOnlyAttribute.IsReadOnly;
}
}
else
{
attrs.Default = defaultValueAttribute.Value;
}
}
else
{
attrs.Description = descriptionAttribute.Description;
}
}
else
{
attrs.Category = categoryAttribute.Category;
}
}
else
{
attrs.Name = displayNameAttribute.DisplayName;
}
}
return attrs;
}
private void Read(object tag)
{
if (Get(tag, "Browsable") is bool flag)
{
Hidden = !flag;
}
if (Get(tag, "ReadOnly") is bool readOnly)
{
ReadOnly = readOnly;
}
if (Get(tag, "IsAdvanced") is bool advanced)
{
Advanced = advanced;
}
if (Get(tag, "HideDefaultButton") is bool hideDefault)
{
HideDefault = hideDefault;
}
if (Get(tag, "ShowRangeAsPercent") is bool percent)
{
Percent = percent;
}
if (Get(tag, "Order") is int order)
{
Order = order;
}
if (Get(tag, "DispName") is string name)
{
Name = name;
}
if (Get(tag, "Category") is string category)
{
Category = category;
}
if (Get(tag, "Description") is string description)
{
Description = description;
}
Default = Get(tag, "DefaultValue") ?? Default;
ObjToStr = (Get(tag, "ObjToStr") as Func<object, string>) ?? ObjToStr;
StrToObj = (Get(tag, "StrToObj") as Func<string, object>) ?? StrToObj;
}
private static object Get(object o, string name)
{
Type type = o.GetType();
object obj = type.GetField(name)?.GetValue(o);
if (obj == null)
{
PropertyInfo? property = type.GetProperty(name);
if ((object)property == null)
{
return null;
}
obj = property.GetValue(o, null);
}
return obj;
}
public static bool HiddenPlugin(PluginInfo p)
{
if ((Object)(object)p.Instance != (Object)null)
{
return ((object)p.Instance).GetType().GetCustomAttributes(typeof(BrowsableAttribute), inherit: false).Cast<BrowsableAttribute>()
.Any((BrowsableAttribute b) => !b.Browsable);
}
return false;
}
}
internal sealed class ModsMenu : MonoBehaviour
{
private static readonly FieldRef<UIShatter, UnityEvent> ShatterEvent = AccessTools.FieldRefAccess<UIShatter, UnityEvent>("_onShatter");
private static readonly MethodInfo ShowPanel = AccessTools.Method(typeof(PanelMenu), "Show", (Type[])null, (Type[])null);
internal Rows Rows;
private RectTransform _mods;
private RectTransform _settings;
private TMP_Text _info;
private PluginInfo[] _plugins;
private int _picked;
private readonly List<TMP_Text> _modLabels = new List<TMP_Text>();
internal const string Intro = "Pick a mod to see its settings, then point at a setting to see what it does.\n\nChanges save right away. Some only take effect after a restart, and some are decided by the host in multiplayer.\n\nDISCORD opens the unofficial CRACK modding community in your browser.";
internal static void Attach(PanelMenu menu)
{
//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
//IL_00eb: Expected O, but got Unknown
//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
//IL_0107: Expected O, but got Unknown
try
{
CanvasGroup settings = Traverse.Create((object)menu).Field("_settingsPanel").GetValue<CanvasGroup>();
Traverse val = Traverse.Create((object)menu).Field("_panels");
if (!((Object)(object)settings == (Object)null) && val.GetValue<CanvasGroup[]>() != null)
{
GameObject val2 = Object.Instantiate<GameObject>(((Component)settings).gameObject, ((Component)settings).transform.parent, false);
((Object)val2).name = "PF_ModsMenu";
Object.DestroyImmediate((Object)(object)val2.GetComponent<SettingsPanel>());
CanvasGroup cg = val2.GetComponent<CanvasGroup>();
val.SetValue((object)val.GetValue<CanvasGroup[]>().Concat((IEnumerable<CanvasGroup>)(object)new CanvasGroup[1] { cg }).ToArray());
ModsMenu mods = val2.AddComponent<ModsMenu>();
mods.Build((UnityAction)delegate
{
ShowPanel.Invoke(menu, new object[1] { settings });
});
AddButton(((Component)settings).transform, (UnityAction)delegate
{
mods.Refresh();
ShowPanel.Invoke(menu, new object[1] { cg });
});
}
}
catch (Exception arg)
{
Plugin.Log.LogError((object)$"Couldn't add the Mods screen to {((object)menu).GetType().Name}: {arg}");
}
}
private static void AddButton(Transform settings, UnityAction open)
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Expected O, but got Unknown
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: 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_0067: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
Transform val = settings.Find("PF_MenuButton (2)");
if (!((Object)(object)val == (Object)null))
{
RectTransform val2 = (RectTransform)Object.Instantiate<GameObject>(((Component)val).gameObject, settings, false).transform;
((Object)val2).name = "PF_MenuButton (Mods)";
Vector2 anchoredPosition = val2.anchoredPosition;
Rect rect = val2.rect;
float num;
if (!(((Rect)(ref rect)).height > 1f))
{
num = 96f;
}
else
{
rect = val2.rect;
num = ((Rect)(ref rect)).height + 14f;
}
val2.anchoredPosition = anchoredPosition + new Vector2(0f, num);
Retarget(((Component)val2).gameObject, "MODS", open);
SetIcon((Transform)(object)val2, "wrench");
}
}
private static void SetIcon(Transform button, string sprite)
{
Transform obj = button.Find("Icon");
Image val = ((obj != null) ? ((Component)obj).GetComponent<Image>() : null);
Sprite val2 = ((IEnumerable<Sprite>)Resources.FindObjectsOfTypeAll<Sprite>()).FirstOrDefault((Func<Sprite, bool>)((Sprite x) => ((Object)x).name == sprite));
if ((Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null)
{
val.sprite = val2;
}
}
private void AddDiscordButton(Transform button)
{
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Expected O, but got Unknown
((Object)button).name = "PF_MenuButton (Discord)";
UIShatter shatter = ((Component)button).GetComponent<UIShatter>();
Retarget(((Component)button).gameObject, "DISCORD", (UnityAction)delegate
{
Plugin.Log.LogInfo((object)"Opening the community Discord invite");
Application.OpenURL("https://discord.gg/crack-modding");
((MonoBehaviour)this).StartCoroutine(Reassemble(shatter));
});
SetIcon(button, "globe");
}
private static IEnumerator Reassemble(UIShatter shatter)
{
yield return (object)new WaitForSecondsRealtime(0.8f);
if ((Object)(object)shatter != (Object)null)
{
shatter.Reassemble();
}
}
private static void Retarget(GameObject button, string label, UnityAction act)
{
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Expected O, but got Unknown
if (label != null)
{
SetText(button.transform.Find("Text"), label);
}
UIShatter component = button.GetComponent<UIShatter>();
UnityEvent val = new UnityEvent();
val.AddListener(act);
ShatterEvent.Invoke(component) = val;
}
internal static TMP_Text SetText(Transform t, string text)
{
if ((Object)(object)t == (Object)null)
{
return null;
}
LocalizedText component = ((Component)t).GetComponent<LocalizedText>();
if ((Object)(object)component != (Object)null)
{
Object.DestroyImmediate((Object)(object)component);
}
TMP_Text component2 = ((Component)t).GetComponent<TMP_Text>();
if ((Object)(object)component2 != (Object)null)
{
component2.text = text;
}
return component2;
}
private void Build(UnityAction back)
{
//IL_0165: Unknown result type (might be due to invalid IL or missing references)
//IL_016f: Expected O, but got Unknown
//IL_0180: Unknown result type (might be due to invalid IL or missing references)
//IL_018a: Expected O, but got Unknown
//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
//IL_01ab: Expected O, but got Unknown
Transform val = ((Component)this).transform.Find("General");
Transform val2 = ((Component)this).transform.Find("Video");
Transform val3 = ((Component)this).transform.Find("Audio");
Rows = new Rows(this, ((Component)this).transform, val2.Find("Content"), val.Find("Content"));
Transform[] array = (Transform[])(object)new Transform[3] { val, val2, val3 };
for (int i = 0; i < array.Length; i++)
{
foreach (Transform item in ((IEnumerable)array[i].Find("Content")).Cast<Transform>().ToList())
{
Object.DestroyImmediate((Object)(object)((Component)item).gameObject);
}
}
SetText(val.Find("Text (TMP)"), "MODS");
SetText(val2.Find("Text (TMP)"), "SETTINGS");
SetText(val3.Find("Text (TMP)"), "INFO");
Retarget(((Component)((Component)this).transform.Find("PF_MenuButton (1)")).gameObject, null, back);
Transform val4 = ((Component)this).transform.Find("PF_MenuButton (2)");
if ((Object)(object)val4 != (Object)null)
{
AddDiscordButton(val4);
}
_mods = Scrollable((RectTransform)val.Find("Content"));
_settings = Scrollable((RectTransform)val2.Find("Content"));
_info = Rows.InfoText((RectTransform)val3.Find("Content"));
ShowInfo("Pick a mod to see its settings, then point at a setting to see what it does.\n\nChanges save right away. Some only take effect after a restart, and some are decided by the host in multiplayer.\n\nDISCORD opens the unofficial CRACK modding community in your browser.");
}
internal void ShowInfo(string text)
{
if ((Object)(object)_info != (Object)null)
{
_info.text = text;
}
}
private static RectTransform Scrollable(RectTransform content)
{
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_0089: 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_00b6: Unknown result type (might be due to invalid IL or missing references)
//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
//IL_00e2: 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_00e8: Unknown result type (might be due to invalid IL or missing references)
//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
RectTransform component = new GameObject("Viewport", new Type[4]
{
typeof(RectTransform),
typeof(RectMask2D),
typeof(Image),
typeof(ScrollRect)
}).GetComponent<RectTransform>();
((Transform)component).SetParent(((Transform)content).parent, false);
component.anchorMin = content.anchorMin;
component.anchorMax = content.anchorMax;
component.pivot = content.pivot;
component.offsetMin = content.offsetMin;
component.offsetMax = content.offsetMax;
((Graphic)((Component)component).GetComponent<Image>()).color = Color.clear;
((Transform)content).SetParent((Transform)(object)component, false);
content.anchorMin = new Vector2(0f, 1f);
content.anchorMax = Vector2.one;
content.pivot = new Vector2(0.5f, 1f);
Vector2 offsetMin = (content.offsetMax = Vector2.zero);
content.offsetMin = offsetMin;
((Component)content).gameObject.AddComponent<ContentSizeFitter>().verticalFit = (FitMode)2;
ScrollRect component2 = ((Component)component).GetComponent<ScrollRect>();
component2.content = content;
component2.viewport = component;
component2.horizontal = false;
component2.movementType = (MovementType)2;
component2.scrollSensitivity = 40f;
return content;
}
internal void Refresh()
{
//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: Expected O, but got Unknown
_plugins = Chainloader.PluginInfos.Values.Where((PluginInfo p) => p != null && p.Metadata != null && !Attrs.HiddenPlugin(p)).OrderBy<PluginInfo, string>((PluginInfo p) => p.Metadata.Name, StringComparer.OrdinalIgnoreCase).ToArray();
Clear(_mods);
_modLabels.Clear();
for (int num = 0; num < _plugins.Length; num++)
{
int index = num;
_modLabels.Add(Rows.Mod(_mods, _plugins[num], (UnityAction)delegate
{
Pick(index);
}));
}
Pick(Mathf.Clamp(_picked, 0, Math.Max(0, _plugins.Length - 1)));
}
private void Pick(int index, bool keepScroll = false)
{
//IL_0016: 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_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_02af: Unknown result type (might be due to invalid IL or missing references)
Vector2 anchoredPosition = (keepScroll ? _settings.anchoredPosition : Vector2.zero);
_picked = index;
for (int i = 0; i < _modLabels.Count; i++)
{
_modLabels[i].alpha = ((i == index) ? 1f : 0.55f);
}
Clear(_settings);
ShowInfo("Pick a mod to see its settings, then point at a setting to see what it does.\n\nChanges save right away. Some only take effect after a restart, and some are decided by the host in multiplayer.\n\nDISCORD opens the unofficial CRACK modding community in your browser.");
if (index >= _plugins.Length)
{
return;
}
PluginInfo val = _plugins[index];
ConfigFile config = (((Object)(object)val.Instance != (Object)null) ? val.Instance.Config : null);
List<KeyValuePair<ConfigEntryBase, Attrs>> list = (from e in (config != null) ? config.Keys.Select((ConfigDefinition k) => config[k]) : Enumerable.Empty<ConfigEntryBase>()
select new KeyValuePair<ConfigEntryBase, Attrs>(e, Attrs.Of(e)) into e
where !e.Value.Hidden
select e).ToList();
if (list.Count == 0)
{
Rows.Header(_settings, "No settings");
}
if (list.Any((KeyValuePair<ConfigEntryBase, Attrs> e) => e.Value.Advanced))
{
Rows.Setting(_settings, (ConfigEntryBase)(object)Plugin.ShowAdvanced, Attrs.Of((ConfigEntryBase)(object)Plugin.ShowAdvanced));
if (!Plugin.ShowAdvanced.Value)
{
list.RemoveAll((KeyValuePair<ConfigEntryBase, Attrs> e) => e.Value.Advanced);
}
}
bool flag = list.Select(Section).Distinct().Count() > 1;
foreach (IGrouping<string, KeyValuePair<ConfigEntryBase, Attrs>> item in list.GroupBy(Section))
{
if (flag)
{
Rows.Header(_settings, item.Key);
}
foreach (KeyValuePair<ConfigEntryBase, Attrs> item2 in item.OrderByDescending((KeyValuePair<ConfigEntryBase, Attrs> e) => e.Value.Order))
{
Rows.Setting(_settings, item2.Key, item2.Value);
}
}
_settings.anchoredPosition = anchoredPosition;
static string Section(KeyValuePair<ConfigEntryBase, Attrs> e)
{
return e.Value.Category ?? e.Key.Definition.Section;
}
}
private void OnEnable()
{
Plugin.ShowAdvanced.SettingChanged += Repick;
}
private void OnDisable()
{
Plugin.ShowAdvanced.SettingChanged -= Repick;
}
private void Repick(object sender, EventArgs e)
{
if (_plugins != null)
{
Pick(_picked, keepScroll: true);
}
}
private static void Clear(RectTransform content)
{
foreach (Transform item in ((IEnumerable)content).Cast<Transform>().ToList())
{
item.SetParent((Transform)null, false);
Object.Destroy((Object)(object)((Component)item).gameObject);
}
}
}
internal sealed class Hint : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, ISelectHandler
{
internal ModsMenu Menu;
internal string Text;
public void OnPointerEnter(PointerEventData e)
{
Menu.ShowInfo(Text);
}
public void OnSelect(BaseEventData e)
{
Menu.ShowInfo(Text);
}
}
internal sealed class Click : MonoBehaviour, IPointerClickHandler, IEventSystemHandler
{
internal UnityAction Action;
public void OnPointerClick(PointerEventData e)
{
UnityAction action = Action;
if (action != null)
{
action.Invoke();
}
}
}
[BepInPlugin("crackmodsui.modmenu", "Mod Menu", "0.1.0")]
public class Plugin : BaseUnityPlugin
{
public const string Guid = "crackmodsui.modmenu";
public const string Name = "Mod Menu";
public const string Version = "0.1.0";
internal const string DiscordInvite = "https://discord.gg/crack-modding";
internal static ManualLogSource Log;
internal static ConfigEntry<bool> ShowAdvanced;
private void Awake()
{
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
LegacyConfig.Adopt((BaseUnityPlugin)(object)this);
Log = ((BaseUnityPlugin)this).Logger;
ShowAdvanced = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowAdvanced", false, "Also show settings that mods mark as advanced. These are usually for troubleshooting or fine-tuning, and most players can leave them alone.");
new Harmony("crackmodsui.modmenu").PatchAll(typeof(Plugin).Assembly);
Log.LogInfo((object)"Mod Menu 0.1.0 loaded");
}
}
[HarmonyPatch(typeof(MainMenuController), "Awake")]
internal static class MainMenuPatch
{
private static void Postfix(MainMenuController __instance)
{
ModsMenu.Attach((PanelMenu)(object)__instance);
}
}
[HarmonyPatch(typeof(GameMenu), "Awake")]
internal static class GameMenuPatch
{
private static void Postfix(GameMenu __instance)
{
ModsMenu.Attach((PanelMenu)(object)__instance);
}
}
internal sealed class Rows
{
private static readonly CultureInfo Inv = CultureInfo.InvariantCulture;
private readonly ModsMenu _menu;
private readonly GameObject _toggle;
private readonly GameObject _slider;
private readonly GameObject _dropdown;
private readonly GameObject _plain;
private readonly Dictionary<Transform, float> _widths = new Dictionary<Transform, float>();
public Rows(ModsMenu menu, Transform root, params Transform[] contents)
{
_menu = menu;
List<Transform> source = contents.SelectMany((Transform c) => ((IEnumerable)c).Cast<Transform>()).ToList();
foreach (Transform val in contents)
{
_widths[val] = (from Transform t in (IEnumerable)val
select ((RectTransform)t).sizeDelta.x).DefaultIfEmpty(800f).Max();
}
_toggle = Template(root, source.First((Transform t) => (Object)(object)Control<Toggle>(t) != (Object)null), "Toggle");
_slider = Template(root, source.First((Transform t) => (Object)(object)Control<Slider>(t) != (Object)null), "Slider");
_dropdown = Template(root, source.First((Transform t) => (Object)(object)Control<TMP_Dropdown>(t) != (Object)null), "Dropdown");
_plain = Template(root, _toggle.transform, "Plain");
Object.DestroyImmediate((Object)(object)((Component)Control<Toggle>(_plain.transform)).gameObject);
}
private static T Control<T>(Transform row) where T : Component
{
return (from Transform c in (IEnumerable)row
select ((Component)c).GetComponent<T>()).FirstOrDefault((T c) => (Object)(object)c != (Object)null);
}
private static GameObject Template(Transform root, Transform item, string kind)
{
GameObject obj = Object.Instantiate<GameObject>(((Component)item).gameObject, root, false);
((Object)obj).name = "Template " + kind;
obj.SetActive(false);
ModsMenu.SetText(obj.transform.Find("Label"), "");
return obj;
}
private GameObject Row(GameObject template, RectTransform content, string label, string hint)
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Expected O, but got Unknown
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: 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_0061: Unknown result type (might be due to invalid IL or missing references)
GameObject obj = Object.Instantiate<GameObject>(template, (Transform)(object)content, false);
obj.SetActive(true);
RectTransform val = (RectTransform)obj.transform;
val.sizeDelta = new Vector2(_widths.TryGetValue((Transform)(object)content, out var value) ? value : val.sizeDelta.x, val.sizeDelta.y);
Label(obj).text = label;
((Graphic)obj.AddComponent<Image>()).color = Color.clear;
Hint hint2 = obj.AddComponent<Hint>();
hint2.Menu = _menu;
hint2.Text = hint;
return obj;
}
private static TMP_Text Label(GameObject row)
{
return ((Component)row.transform.Find("Label")).GetComponent<TMP_Text>();
}
internal TMP_Text Mod(RectTransform content, PluginInfo p, UnityAction pick)
{
//IL_0093: Unknown result type (might be due to invalid IL or missing references)
//IL_0098: 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_009a: Unknown result type (might be due to invalid IL or missing references)
//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
string fileName = Path.GetFileName(p.Location);
GameObject val = Row(_plain, content, p.Metadata.Name, $"{p.Metadata.Name} {p.Metadata.Version}\n" + "<alpha=#99>" + p.Metadata.GUID + "\n" + fileName);
TMP_Text val2 = Label(val);
RectTransform val3 = (RectTransform)Object.Instantiate<GameObject>(((Component)val2).gameObject, val.transform, false).transform;
Vector2 val4 = default(Vector2);
((Vector2)(ref val4))..ctor(1f, 0.5f);
val3.pivot = val4;
Vector2 anchorMin = (val3.anchorMax = val4);
val3.anchorMin = anchorMin;
val3.anchoredPosition = new Vector2(-12f, 0f);
Rect rect = ((RectTransform)val2.transform).rect;
val3.sizeDelta = new Vector2(220f, ((Rect)(ref rect)).height);
TMP_Text component = ((Component)val3).GetComponent<TMP_Text>();
component.text = p.Metadata.Version.ToString();
component.alignment = (TextAlignmentOptions)4100;
component.alpha = 0.6f;
val.AddComponent<Click>().Action = pick;
return val2;
}
internal void Header(RectTransform content, string text)
{
Label(Row(_plain, content, text.ToUpperInvariant(), "Pick a mod to see its settings, then point at a setting to see what it does.\n\nChanges save right away. Some only take effect after a restart, and some are decided by the host in multiplayer.\n\nDISCORD opens the unofficial CRACK modding community in your browser.")).alpha = 0.6f;
}
internal TMP_Text InfoText(RectTransform content)
{
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: 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_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: 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_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
TMP_Text val = Label(_plain);
RectTransform val2 = (RectTransform)Object.Instantiate<GameObject>(((Component)val).gameObject, ((Transform)content).parent, false).transform;
((Object)val2).name = "Info";
val2.anchorMin = content.anchorMin;
val2.anchorMax = content.anchorMax;
val2.pivot = content.pivot;
val2.offsetMin = content.offsetMin + new Vector2(24f, 12f);
val2.offsetMax = content.offsetMax - new Vector2(24f, 0f);
TMP_Text component = ((Component)val2).GetComponent<TMP_Text>();
component.alignment = (TextAlignmentOptions)257;
component.textWrappingMode = (TextWrappingModes)1;
component.overflowMode = (TextOverflowModes)1;
component.enableAutoSizing = true;
component.fontSizeMin = 14f;
component.fontSizeMax = val.fontSize * 0.8f;
component.richText = true;
return component;
}
internal void Setting(RectTransform content, ConfigEntryBase entry, Attrs attrs)
{
string text = attrs.Name ?? Regex.Replace(entry.Definition.Key, "(?<=[a-z0-9])(?=[A-Z])", " ");
object obj = attrs.Description;
if (obj == null)
{
ConfigDescription description = entry.Description;
obj = ((description != null) ? description.Description : null);
}
string text2 = (string)obj;
object def;
bool flag = TryDefault(entry, attrs, out def);
string hint = text + "\n<alpha=#CC>" + text2 + (flag ? ("\n\n<alpha=#99>Default: " + Format(attrs, def)) : "");
Type settingType = entry.SettingType;
ConfigDescription description2 = entry.Description;
AcceptableValueBase val = ((description2 != null) ? description2.AcceptableValues : null);
Action sync = ((settingType == typeof(bool)) ? Toggle(content, entry, text, hint) : (settingType.IsEnum ? Choice(content, entry, text, hint, attrs, Enum.GetValues(settingType).Cast<object>().ToList()) : (IsList(val) ? Choice(content, entry, text, hint, attrs, ListOf(val)) : ((!IsNumber(settingType) || !IsRange(val)) ? Text(content, entry, text, hint, attrs) : Slide(content, entry, text, hint, attrs, val)))));
GameObject gameObject = ((Component)((Transform)content).GetChild(((Transform)content).childCount - 1)).gameObject;
RowSync rowSync = gameObject.AddComponent<RowSync>();
rowSync.Init(entry, sync);
if (attrs.ReadOnly)
{
Selectable[] componentsInChildren = gameObject.GetComponentsInChildren<Selectable>(true);
for (int i = 0; i < componentsInChildren.Length; i++)
{
componentsInChildren[i].interactable = false;
}
}
else
{
if (!flag || attrs.HideDefault)
{
return;
}
rowSync.AddReset(Label(gameObject), def, delegate
{
try
{
entry.BoxedValue = def;
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)$"{entry.Definition}: couldn't reset ({ex.Message})");
}
});
}
}
private static bool TryDefault(ConfigEntryBase entry, Attrs attrs, out object def)
{
def = attrs.Default;
Type settingType = entry.SettingType;
if (def == null)
{
return false;
}
if (settingType.IsInstanceOfType(def))
{
return true;
}
try
{
def = ((!settingType.IsEnum) ? Convert.ChangeType(def, settingType, Inv) : ((def is string value) ? Enum.Parse(settingType, value) : Enum.ToObject(settingType, def)));
return true;
}
catch (Exception)
{
return false;
}
}
private static string Format(Attrs attrs, object v)
{
if (attrs.ObjToStr != null)
{
try
{
return attrs.ObjToStr(v);
}
catch (Exception)
{
}
}
return Show(v);
}
private Action Toggle(RectTransform content, ConfigEntryBase entry, string name, string hint)
{
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Expected O, but got Unknown
Toggle t = Control<Toggle>(Row(_toggle, content, name, hint).transform);
t.onValueChanged = new ToggleEvent();
Action obj = delegate
{
t.SetIsOnWithoutNotify((bool)entry.BoxedValue);
};
obj();
((UnityEvent<bool>)(object)t.onValueChanged).AddListener((UnityAction<bool>)delegate(bool v)
{
entry.BoxedValue = v;
});
return obj;
}
private Action Choice(RectTransform content, ConfigEntryBase entry, string name, string hint, Attrs attrs, List<object> values)
{
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Expected O, but got Unknown
TMP_Dropdown d = Control<TMP_Dropdown>(Row(_dropdown, content, name, hint).transform);
d.onValueChanged = new DropdownEvent();
d.ClearOptions();
d.AddOptions(values.Select((object v) => Format(attrs, v)).ToList());
Action obj = delegate
{
d.SetValueWithoutNotify(Math.Max(0, values.FindIndex((object v) => object.Equals(v, entry.BoxedValue))));
d.RefreshShownValue();
};
obj();
((UnityEvent<int>)(object)d.onValueChanged).AddListener((UnityAction<int>)delegate(int i)
{
entry.BoxedValue = values[i];
});
return obj;
}
private Action Slide(RectTransform content, ConfigEntryBase entry, string name, string hint, Attrs attrs, AcceptableValueBase range)
{
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_0070: Expected O, but got Unknown
GameObject val = Row(_slider, content, name, hint);
Slider s = Control<Slider>(val.transform);
TMP_Text label = Label(val);
Type type = entry.SettingType;
s.onValueChanged = new SliderEvent();
s.wholeNumbers = type != typeof(float) && type != typeof(double) && type != typeof(decimal);
s.minValue = Convert.ToSingle(((object)range).GetType().GetProperty("MinValue").GetValue(range), Inv);
s.maxValue = Convert.ToSingle(((object)range).GetType().GetProperty("MaxValue").GetValue(range), Inv);
Func<object, string> show = (object v) => (attrs.Percent && !(s.maxValue <= s.minValue)) ? (Mathf.RoundToInt((Convert.ToSingle(v, Inv) - s.minValue) / (s.maxValue - s.minValue) * 100f) + "%") : Format(attrs, v);
Action obj = delegate
{
s.SetValueWithoutNotify(Convert.ToSingle(entry.BoxedValue, Inv));
label.text = Named(name, show(entry.BoxedValue));
};
obj();
((UnityEvent<float>)(object)s.onValueChanged).AddListener((UnityAction<float>)delegate(float v)
{
entry.BoxedValue = Convert.ChangeType(s.wholeNumbers ? Math.Round(v) : ((double)v), type, Inv);
label.text = Named(name, show(entry.BoxedValue));
});
return obj;
}
private Action Text(RectTransform content, ConfigEntryBase entry, string name, string hint, Attrs attrs)
{
//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
//IL_0106: Unknown result type (might be due to invalid IL or missing references)
//IL_011b: Unknown result type (might be due to invalid IL or missing references)
//IL_012b: Unknown result type (might be due to invalid IL or missing references)
//IL_0130: Unknown result type (might be due to invalid IL or missing references)
//IL_0138: Unknown result type (might be due to invalid IL or missing references)
//IL_0139: Unknown result type (might be due to invalid IL or missing references)
//IL_0143: Unknown result type (might be due to invalid IL or missing references)
//IL_0144: Unknown result type (might be due to invalid IL or missing references)
//IL_014e: Unknown result type (might be due to invalid IL or missing references)
//IL_014f: Unknown result type (might be due to invalid IL or missing references)
//IL_0154: Unknown result type (might be due to invalid IL or missing references)
//IL_0155: Unknown result type (might be due to invalid IL or missing references)
//IL_015c: Unknown result type (might be due to invalid IL or missing references)
//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
TMP_Dropdown obj = Control<TMP_Dropdown>(Row(_dropdown, content, name, hint).transform);
GameObject gameObject = ((Component)obj).gameObject;
TMP_Text component = ((Component)gameObject.transform.Find("Label")).GetComponent<TMP_Text>();
Object.DestroyImmediate((Object)(object)obj);
string[] array = new string[2] { "Arrow", "Template" };
foreach (string text in array)
{
Transform val = gameObject.transform.Find(text);
if ((Object)(object)val != (Object)null)
{
Object.DestroyImmediate((Object)(object)((Component)val).gameObject);
}
}
RectTransform component2 = new GameObject("Text Area", new Type[2]
{
typeof(RectTransform),
typeof(RectMask2D)
}).GetComponent<RectTransform>();
((Transform)component2).SetParent(gameObject.transform, false);
component2.anchorMin = Vector2.zero;
component2.anchorMax = Vector2.one;
component2.offsetMin = new Vector2(14f, 4f);
component2.offsetMax = new Vector2(-14f, -4f);
RectTransform val2 = (RectTransform)component.transform;
((Transform)val2).SetParent((Transform)(object)component2, false);
val2.anchorMin = Vector2.zero;
val2.anchorMax = Vector2.one;
Vector2 offsetMin = (val2.offsetMax = Vector2.zero);
val2.offsetMin = offsetMin;
bool custom = attrs.ObjToStr != null && attrs.StrToObj != null;
Func<string> current = () => (!custom) ? entry.GetSerializedValue() : Format(attrs, entry.BoxedValue);
gameObject.SetActive(false);
TMP_InputField input = gameObject.AddComponent<TMP_InputField>();
input.textViewport = component2;
input.textComponent = component;
((Selectable)input).targetGraphic = (Graphic)(object)gameObject.GetComponent<Image>();
input.fontAsset = component.font;
input.pointSize = component.fontSize;
input.caretColor = ((Graphic)component).color;
input.lineType = (LineType)0;
input.SetTextWithoutNotify(current());
component.text = current();
gameObject.SetActive(true);
((UnityEvent<string>)(object)input.onEndEdit).AddListener((UnityAction<string>)delegate(string s)
{
try
{
if (custom)
{
entry.BoxedValue = attrs.StrToObj(s);
}
else
{
entry.SetSerializedValue(s);
}
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)$"{entry.Definition}: typed value rejected ({ex.GetType().Name})");
}
input.SetTextWithoutNotify(current());
});
return delegate
{
if (!input.isFocused)
{
input.SetTextWithoutNotify(current());
}
};
}
private static string Named(string name, string value)
{
return name + " <alpha=#99>" + value;
}
private static string Show(object v)
{
if (!(v is float num))
{
if (!(v is double num2))
{
return Convert.ToString(v, Inv);
}
return num2.ToString("0.##", Inv);
}
return num.ToString("0.##", Inv);
}
private static bool IsNumber(Type t)
{
if (!(t == typeof(int)) && !(t == typeof(float)) && !(t == typeof(double)) && !(t == typeof(long)) && !(t == typeof(short)) && !(t == typeof(byte)) && !(t == typeof(uint)) && !(t == typeof(ulong)))
{
return t == typeof(decimal);
}
return true;
}
private static bool IsGeneric(AcceptableValueBase a, Type def)
{
if (a != null && ((object)a).GetType().IsGenericType)
{
return ((object)a).GetType().GetGenericTypeDefinition() == def;
}
return false;
}
private static bool IsRange(AcceptableValueBase a)
{
return IsGeneric(a, typeof(AcceptableValueRange<>));
}
private static bool IsList(AcceptableValueBase a)
{
return IsGeneric(a, typeof(AcceptableValueList<>));
}
private static List<object> ListOf(AcceptableValueBase a)
{
return ((IEnumerable)((object)a).GetType().GetProperty("AcceptableValues").GetValue(a)).Cast<object>().ToList();
}
}
internal sealed class RowSync : MonoBehaviour
{
private ConfigEntryBase _entry;
private Action _sync;
private object _last;
private object _default;
private TMP_Text _label;
private TMP_Text _reset;
private string _placedFor;
internal void Init(ConfigEntryBase entry, Action sync)
{
_entry = entry;
_sync = sync;
_last = entry.BoxedValue;
}
internal void AddReset(TMP_Text label, object def, Action reset)
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Expected O, but got Unknown
//IL_004a: 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_0051: 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)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
_label = label;
_default = def;
RectTransform val = (RectTransform)Object.Instantiate<GameObject>(((Component)label).gameObject, label.transform, false).transform;
((Object)val).name = "Reset";
Vector2 val2 = default(Vector2);
((Vector2)(ref val2))..ctor(0f, 0.5f);
val.pivot = val2;
Vector2 anchorMin = (val.anchorMax = val2);
val.anchorMin = anchorMin;
_reset = ((Component)val).GetComponent<TMP_Text>();
_reset.text = "RESET";
_reset.enableAutoSizing = false;
_reset.fontSize = label.fontSize * 0.7f;
_reset.textWrappingMode = (TextWrappingModes)0;
_reset.alignment = (TextAlignmentOptions)4097;
((Graphic)_reset).raycastTarget = true;
float num = _reset.preferredWidth + 8f;
Rect rect = label.rectTransform.rect;
val.sizeDelta = new Vector2(num, ((Rect)(ref rect)).height);
((Component)val).gameObject.SetActive(false);
ResetLink resetLink = ((Component)val).gameObject.AddComponent<ResetLink>();
resetLink.Text = _reset;
resetLink.Action = reset;
}
private void Update()
{
if (_entry == null)
{
return;
}
object boxedValue = _entry.BoxedValue;
if (!object.Equals(boxedValue, _last))
{
_last = boxedValue;
try
{
_sync();
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)$"{_entry.Definition}: couldn't show the new value ({ex.Message})");
}
}
if (!((Object)(object)_reset == (Object)null))
{
bool flag = !object.Equals(boxedValue, _default);
if (((Component)_reset).gameObject.activeSelf != flag)
{
((Component)_reset).gameObject.SetActive(flag);
}
if (flag && _label.text != _placedFor)
{
Place();
}
}
}
private void Place()
{
//IL_002d: 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_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
_placedFor = _label.text;
RectTransform rectTransform = _reset.rectTransform;
Rect rect = _label.rectTransform.rect;
float num = Mathf.Max(0f, ((Rect)(ref rect)).width - rectTransform.sizeDelta.x);
rectTransform.anchoredPosition = new Vector2(Mathf.Min(_label.preferredWidth + 18f, num), 0f);
}
}
internal sealed class ResetLink : MonoBehaviour, IPointerClickHandler, IEventSystemHandler, IPointerEnterHandler, IPointerExitHandler
{
private const float Idle = 0.45f;
internal TMP_Text Text;
internal Action Action;
private void OnEnable()
{
Text.alpha = 0.45f;
}
public void OnPointerEnter(PointerEventData e)
{
Text.alpha = 1f;
}
public void OnPointerExit(PointerEventData e)
{
Text.alpha = 0.45f;
}
public void OnPointerClick(PointerEventData e)
{
Action?.Invoke();
}
}
}