Please disclose if your mod was created primarily using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of LoadingTips v1.1.7
Enova.LoadingTips.dll
Decompiled 9 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using LethalConfig; using LethalConfig.ConfigItems; using LethalConfig.ConfigItems.Options; using LobbyCompatibility.Enums; using LobbyCompatibility.Features; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("AmazingAssets.TerrainToMesh")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("ClientNetworkTransform")] [assembly: IgnoresAccessChecksTo("com.olegknyazev.softmask")] [assembly: IgnoresAccessChecksTo("DissonanceVoip")] [assembly: IgnoresAccessChecksTo("EasyTextEffects")] [assembly: IgnoresAccessChecksTo("Facepunch Transport for Netcode for GameObjects")] [assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")] [assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")] [assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging")] [assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging.DocCodeExamples")] [assembly: IgnoresAccessChecksTo("Unity.Burst")] [assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")] [assembly: IgnoresAccessChecksTo("Unity.Collections")] [assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")] [assembly: IgnoresAccessChecksTo("Unity.InputSystem")] [assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")] [assembly: IgnoresAccessChecksTo("Unity.Jobs")] [assembly: IgnoresAccessChecksTo("Unity.Mathematics")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.Common")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.MetricTypes")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStats")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Component")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Configuration")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Implementation")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsReporting")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkProfiler.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkSolutionInterface")] [assembly: IgnoresAccessChecksTo("Unity.Netcode.Components")] [assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.Networking.Transport")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Csg")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.KdTree")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Poly2Tri")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Stl")] [assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Config.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")] [assembly: IgnoresAccessChecksTo("Unity.Services.Authentication")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Analytics")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Configuration")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Device")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments.Internal")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Internal")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Networking")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Registration")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Scheduler")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Telemetry")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Threading")] [assembly: IgnoresAccessChecksTo("Unity.Services.QoS")] [assembly: IgnoresAccessChecksTo("Unity.Services.Relay")] [assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")] [assembly: IgnoresAccessChecksTo("Unity.Timeline")] [assembly: IgnoresAccessChecksTo("Unity.VisualEffectGraph.Runtime")] [assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.UI")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Enova.LoadingTips")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.1.7.0")] [assembly: AssemblyInformationalVersion("1.1.7-dev.1+9bff3b9965b93ca0dc2f3008138084963c3ae307")] [assembly: AssemblyProduct("LoadingTips")] [assembly: AssemblyTitle("Enova.LoadingTips")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.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.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = 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 LoadingTips { [BepInPlugin("Enova.LoadingTips", "LoadingTips", "1.1.7")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class LoadingTips : BaseUnityPlugin { public static LoadingTips Instance { get; private set; } internal static ManualLogSource Logger { get; private set; } internal static Harmony? Harmony { get; set; } internal static LoadingTipsConfig Config { get; private set; } private void Awake() { Logger = ((BaseUnityPlugin)this).Logger; Instance = this; Config = new LoadingTipsConfig(((BaseUnityPlugin)this).Config); if (Chainloader.PluginInfos.ContainsKey("ainavt.lc.lethalconfig")) { Config.InitializeLethalConfig(); } if (Chainloader.PluginInfos.ContainsKey("BMX.LobbyCompatibility")) { InitializeLobbyCompatibility(); } Patch(); Logger.LogInfo((object)"Enova.LoadingTips v1.1.7 has loaded!"); } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] private static void InitializeLobbyCompatibility() { PluginHelper.RegisterPlugin("Enova.LoadingTips", new Version("1.1.7"), (CompatibilityLevel)0, (VersionStrictness)1); } internal static void Patch() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown if (Harmony == null) { Harmony = new Harmony("Enova.LoadingTips"); } Logger.LogDebug((object)"Patching..."); Harmony.PatchAll(); Logger.LogDebug((object)"Finished patching!"); } internal static void Unpatch() { Logger.LogDebug((object)"Unpatching..."); Harmony? harmony = Harmony; if (harmony != null) { harmony.UnpatchSelf(); } Logger.LogDebug((object)"Finished unpatching!"); } } internal class LoadingTipsConfig { private readonly List<string> _tips = new List<string>(); private readonly string _tipsPath = Path.Combine(Paths.ConfigPath, "LoadingTips.txt"); private const string _defaultTip = "Create tips by editing the LoadingTips.txt file in your BepInEx config directory."; public ConfigEntry<string> TipPrefix { get; } public ConfigEntry<bool> RandomizeTip { get; } public IReadOnlyList<string> Tips => _tips.AsReadOnly(); public LoadingTipsConfig(ConfigFile config) { TipPrefix = config.Bind<string>("General", "TipPrefix", string.Empty, "This text will precede all loading screen tips (e.g. TIP: My Tip Here)"); RandomizeTip = config.Bind<bool>("General", "RandomizeTip", true, "Whether to show a random tip from the list every time it is shown or show them sequentially."); LoadTips(); } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] internal void InitializeLethalConfig() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown TextInputFieldConfigItem val = new TextInputFieldConfigItem(TipPrefix, false); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)val); BoolCheckBoxConfigItem val2 = new BoolCheckBoxConfigItem(RandomizeTip, false); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)val2); GenericButtonConfigItem val3 = new GenericButtonConfigItem("General", "Reload Tips", "Reloads the tips from the txt file in BepInEx/config/LoadingTips.txt", "Reload", new GenericButtonHandler(LoadTips)); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)val3); } public void LoadTips() { _tips.Clear(); try { if (!File.Exists(_tipsPath)) { File.WriteAllText(_tipsPath, "Create tips by editing the LoadingTips.txt file in your BepInEx config directory.", Encoding.UTF8); } } catch (Exception arg) { LoadingTips.Logger.LogError((object)$"Failed to create tips file: {arg}"); return; } try { string[] source = File.ReadAllLines(_tipsPath); _tips.AddRange(from l in source select l.Trim().Split("##").First() .Replace("\\n", Environment.NewLine) into l where !string.IsNullOrWhiteSpace(l) select l); } catch (Exception arg2) { LoadingTips.Logger.LogError((object)$"Failed to read tips file: {arg2}"); } } } internal class LoadingTipScript : MonoBehaviour { private TextMeshProUGUI _text; private static int _tipIndex = -1; private void Awake() { _text = ((Component)this).GetComponent<TextMeshProUGUI>(); } private void OnEnable() { if (LoadingTips.Config.RandomizeTip.Value) { SetRandomTip(); } else { SetTip(_tipIndex++); } } public void SetRandomTip() { if (LoadingTips.Config.Tips.Count <= 0) { LoadingTips.Logger.LogError((object)"Tips are empty, can't set tip"); return; } int num = Random.Range(0, LoadingTips.Config.Tips.Count); while (LoadingTips.Config.Tips.Count > 1 && num == _tipIndex) { num = Random.Range(0, LoadingTips.Config.Tips.Count); } SetTip(num); _tipIndex = num; } public void SetTip(int tipIndex) { if (LoadingTips.Config.Tips.Count <= 0) { LoadingTips.Logger.LogError((object)"Tips are empty, can't set tip"); return; } tipIndex = Math.Clamp(tipIndex, 0, LoadingTips.Config.Tips.Count - 1); SetTip(LoadingTips.Config.Tips[tipIndex]); } public void SetTip(string tip) { ((TMP_Text)_text).text = LoadingTips.Config.TipPrefix.Value + tip; } } internal static class StringExtensions { private static bool IsInputStringShorter(string str, int length) { return str.Length < length; } public static ReadOnlySpan<char> UseAsSpan(this string str, int start, int length) { if (IsInputStringShorter(str, length - start)) { return str; } return str.AsSpan(start, length); } } public static class MyPluginInfo { public const string PLUGIN_GUID = "Enova.LoadingTips"; public const string PLUGIN_NAME = "LoadingTips"; public const string PLUGIN_VERSION = "1.1.7"; } } namespace LoadingTips.Patches { [HarmonyPatch(typeof(HUDManager))] [HarmonyWrapSafe] internal class LoadingTipsPatches { private static GameObject? _tipsObject; [HarmonyPatch("Start")] [HarmonyPostfix] public static void HudStart(HUDManager __instance) { InitializeText(((TMP_Text)__instance.loadingText).transform.parent); } [HarmonyPatch(typeof(TextMeshProUGUI), "OnEnable")] [HarmonyPostfix] public static void OnTextMeshEnabled(TextMeshProUGUI __instance) { if ((Object)(object)__instance == (Object)(object)HUDManager.Instance?.loadingText) { LoadingTextActiveChanged(active: true); } } [HarmonyPatch(typeof(TextMeshProUGUI), "OnDisable")] [HarmonyPostfix] public static void OnTextMeshDisabled(TextMeshProUGUI __instance) { if ((Object)(object)__instance == (Object)(object)HUDManager.Instance?.loadingText) { LoadingTextActiveChanged(active: false); } } private static void LoadingTextActiveChanged(bool active) { if (!((Object)(object)_tipsObject == (Object)null) && (!active || !StartOfRound.Instance.shipDoorsEnabled)) { _tipsObject.SetActive(active); ((Behaviour)HUDManager.Instance.loadingDarkenScreen).enabled = active; } } private static void InitializeText(Transform parent) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown //IL_0076: 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_00a0: 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_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) _tipsObject = new GameObject("LoadingTips", new Type[2] { typeof(TextMeshProUGUI), typeof(LoadingTipScript) }); _tipsObject.SetActive(false); _tipsObject.layer = LayerMask.NameToLayer("UI"); RectTransform component = _tipsObject.GetComponent<RectTransform>(); ((Transform)component).SetParent(parent); ((Transform)component).SetAsLastSibling(); ((Transform)component).localScale = new Vector3(1f, 1f, 1f); component.anchorMin = new Vector2(0.5f, 0.5f); component.anchorMax = new Vector2(0.5f, 0.5f); component.sizeDelta = new Vector2(500f, 100f); component.anchoredPosition3D = new Vector3(0f, -200f, 0f); TextMeshProUGUI component2 = _tipsObject.GetComponent<TextMeshProUGUI>(); ((TMP_Text)component2).font = ((TMP_Text)HUDManager.Instance.loadingText).font; ((TMP_Text)component2).font.fallbackFontAssetTable.Add(((TMP_Text)HUDManager.Instance.controlTipLines[0]).font); ((TMP_Text)component2).fontSize = 18f; ((TMP_Text)component2).horizontalAlignment = (HorizontalAlignmentOptions)2; ((TMP_Text)component2).enableWordWrapping = true; ((TMP_Text)component2).overflowMode = (TextOverflowModes)2; ((Graphic)component2).color = ((Graphic)HUDManager.Instance.loadingText).color; } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }