Please disclose if any significant portion of your mod was created 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 MrovLib v0.4.2
MrovLib.dll
Decompiled 2 months agousing System; using System.Collections.Generic; using System.Data; 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 System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using Dawn; using HarmonyLib; using LethalLevelLoader; using Microsoft.CodeAnalysis; using MrovLib.Compatibility; using MrovLib.ContentType; using MrovLib.Events; using MrovLib.Patches; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [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.Components")] [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: AssemblyCompany("MrovLib")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Common methods for my mods.")] [assembly: AssemblyFileVersion("0.4.2.0")] [assembly: AssemblyInformationalVersion("0.4.2+883d5f367e75a987d9aa0937161847ee297a070e")] [assembly: AssemblyProduct("MrovLib")] [assembly: AssemblyTitle("MrovLib")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.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.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ConsoleTables { public class ConsoleTable { public static readonly HashSet<Type> NumericTypes = new HashSet<Type> { typeof(int), typeof(double), typeof(decimal), typeof(long), typeof(short), typeof(sbyte), typeof(byte), typeof(ulong), typeof(ushort), typeof(uint), typeof(float) }; public IList<object> Columns { get; } public IList<object[]> Rows { get; } public ConsoleTableOptions Options { get; } public Type[] ColumnTypes { get; private set; } public IList<string> Formats { get; private set; } public ConsoleTable(params string[] columns) : this(new ConsoleTableOptions { Columns = new List<string>(columns) }) { } public ConsoleTable(ConsoleTableOptions options) { Options = options ?? throw new ArgumentNullException("options"); Rows = new List<object[]>(); Columns = new List<object>(options.Columns); } public ConsoleTable AddColumn(IEnumerable<string> names) { foreach (string name in names) { Columns.Add(name); } return this; } public ConsoleTable AddRow(params object[] values) { if (values == null) { throw new ArgumentNullException("values"); } if (!Columns.Any()) { throw new Exception("Please set the columns first"); } if (Columns.Count != values.Length) { throw new Exception($"The number columns in the row ({Columns.Count}) does not match the values ({values.Length})"); } Rows.Add(values); return this; } public ConsoleTable Configure(Action<ConsoleTableOptions> action) { action(Options); return this; } public static ConsoleTable FromDictionary(Dictionary<string, Dictionary<string, object>> values) { ConsoleTable consoleTable = new ConsoleTable(); List<string> list = values.SelectMany((KeyValuePair<string, Dictionary<string, object>> x) => x.Value.Keys).Distinct().ToList(); list.Insert(0, ""); consoleTable.AddColumn(list); foreach (KeyValuePair<string, Dictionary<string, object>> value2 in values) { List<object> list2 = new List<object> { value2.Key }; foreach (string item in list.Skip(1)) { list2.Add(value2.Value.TryGetValue(item, out var value) ? value : ""); } consoleTable.AddRow(list2.Cast<object>().ToArray()); } return consoleTable; } public static ConsoleTable From<T>(IEnumerable<T> values) { ConsoleTable consoleTable = new ConsoleTable { ColumnTypes = GetColumnsType<T>().ToArray() }; List<string> columns = GetColumns<T>().ToList(); consoleTable.AddColumn(columns); foreach (IEnumerable<object> item in values.Select((T value) => columns.Select((string column) => GetColumnValue<T>(value, column)))) { consoleTable.AddRow(item.ToArray()); } return consoleTable; } public static ConsoleTable From(DataTable dataTable) { ConsoleTable consoleTable = new ConsoleTable(); List<string> names = (from DataColumn x in dataTable.Columns select x.ColumnName).ToList(); consoleTable.AddColumn(names); foreach (DataRow row in dataTable.Rows) { string[] array = row.ItemArray.Select((object x) => (!(x is byte[] inArray)) ? x.ToString() : Convert.ToBase64String(inArray)).ToArray(); object[] values = array; consoleTable.AddRow(values); } return consoleTable; } public override string ToString() { StringBuilder stringBuilder = new StringBuilder(); List<int> columnLengths = ColumnLengths(); List<string> columnAlignment = Enumerable.Range(0, Columns.Count).Select(GetNumberAlignment).ToList(); string format = (from i in Enumerable.Range(0, Columns.Count) select " | {" + i + "," + columnAlignment[i] + columnLengths[i] + "}").Aggregate((string s, string a) => s + a) + " |"; SetFormats(ColumnLengths(), columnAlignment); int val = Math.Max(0, Rows.Any() ? Rows.Max((object[] row) => string.Format(format, row).Length) : 0); string text = string.Format(Formats[0], Columns.ToArray()); int num = Math.Max(val, text.Length); List<string> list = Rows.Select((object[] row, int i) => string.Format(Formats[i + 1], row)).ToList(); string value = " " + string.Join("", Enumerable.Repeat("-", num - 1)) + " "; stringBuilder.AppendLine(value); stringBuilder.AppendLine(text); foreach (string item in list) { stringBuilder.AppendLine(value); stringBuilder.AppendLine(item); } stringBuilder.AppendLine(value); if (Options.EnableCount) { stringBuilder.AppendLine(""); stringBuilder.AppendFormat(" Count: {0}", Rows.Count); } return stringBuilder.ToString(); } private void SetFormats(List<int> columnLengths, List<string> columnAlignment) { List<object[]> list = new List<object[]> { Columns.ToArray() }; list.AddRange(Rows); Formats = list.Select((object[] d) => Enumerable.Range(0, Columns.Count).Select(delegate(int i) { string text = d[i]?.ToString() ?? ""; int num = columnLengths[i] - (GetTextWidth(text) - text.Length); return " | {" + i + "," + columnAlignment[i] + num + "}"; }).Aggregate((string s, string a) => s + a) + " |").ToList(); } public static int GetTextWidth(string value) { return value?.ToCharArray().Sum((char c) => (c <= '\u007f') ? 1 : 2) ?? 0; } public string ToMarkDownString() { return ToMarkDownString('|'); } private string ToMarkDownString(char delimiter) { StringBuilder builder = new StringBuilder(); List<int> columnLengths = ColumnLengths(); Format(columnLengths, delimiter); string text = string.Format(Formats[0].TrimStart(), Columns.ToArray()); List<string> list = Rows.Select((object[] row, int i) => string.Format(Formats[i + 1].TrimStart(), row)).ToList(); string value = Regex.Replace(text, "[^|]", "-"); builder.AppendLine(text); builder.AppendLine(value); list.ForEach(delegate(string row) { builder.AppendLine(row); }); return builder.ToString(); } public string ToMinimalString() { return ToMarkDownString('\0'); } public string ToStringAlternative() { StringBuilder stringBuilder = new StringBuilder(); string text = string.Format(Formats[0].TrimStart(), Columns.ToArray()); List<string> list = Rows.Select((object[] row, int i) => string.Format(Formats[i + 1].TrimStart(), row)).ToList(); string text2 = Regex.Replace(text, "[^| ]", "-"); string value = text2.Replace("|", "+"); stringBuilder.AppendLine(value); stringBuilder.AppendLine(text); foreach (string item in list) { stringBuilder.AppendLine(value); stringBuilder.AppendLine(item); } stringBuilder.AppendLine(value); return stringBuilder.ToString(); } public string ToStringCustomDecoration(bool header = false, bool divider = false, bool separator = false) { StringBuilder builder = new StringBuilder(); List<int> columnLengths = ColumnLengths(); Format(columnLengths, '\0'); string text = string.Format(Formats[0].TrimStart(), Columns.ToArray()); List<string> list = Rows.Select((object[] row, int i) => string.Format(separator ? Formats[i + 1].TrimStart() : Formats[i + 1].TrimStart().Replace("|", ""), row)).ToList(); string text2 = Regex.Replace(text, "[^|]", "-"); if (header) { builder.AppendLine(text.Replace("|", separator ? "|" : "")); } if (divider) { if (separator) { builder.AppendLine(text2); } else { builder.AppendLine(Regex.Replace(text2, "[|-]", "")); } } list.ForEach(delegate(string row) { builder.AppendLine(row); }); return builder.ToString(); } private string Format(List<int> columnLengths, char delimiter = '|') { List<string> columnAlignment = Enumerable.Range(0, Columns.Count).Select(GetNumberAlignment).ToList(); SetFormats(columnLengths, columnAlignment); string delimiterStr = ((delimiter == '\0') ? string.Empty : delimiter.ToString()); return ((from i in Enumerable.Range(0, Columns.Count) select " " + delimiterStr + " {" + i + "," + columnAlignment[i] + columnLengths[i] + "}").Aggregate((string s, string a) => s + a) + " " + delimiterStr).Trim(); } private string GetNumberAlignment(int i) { if (Options.NumberAlignment != Alignment.Right || ColumnTypes == null || !NumericTypes.Contains(ColumnTypes[i])) { return "-"; } return ""; } private List<int> ColumnLengths() { return Columns.Select((object t, int i) => (from x in Rows.Select((object[] x) => x[i]).Union(new object[1] { Columns[i] }) where x != null select x.ToString().ToCharArray().Sum((char c) => (c <= '\u007f') ? 1 : 2)).Max()).ToList(); } public void Write(Format format = ConsoleTables.Format.Default) { SetFormats(ColumnLengths(), Enumerable.Range(0, Columns.Count).Select(GetNumberAlignment).ToList()); switch (format) { case ConsoleTables.Format.Default: Options.OutputTo.WriteLine(ToString()); break; case ConsoleTables.Format.MarkDown: Options.OutputTo.WriteLine(ToMarkDownString()); break; case ConsoleTables.Format.Alternative: Options.OutputTo.WriteLine(ToStringAlternative()); break; case ConsoleTables.Format.Minimal: Options.OutputTo.WriteLine(ToMinimalString()); break; default: throw new ArgumentOutOfRangeException("format", format, null); } } private static IEnumerable<string> GetColumns<T>() { return (from x in typeof(T).GetProperties() select x.Name).ToArray(); } private static object GetColumnValue<T>(object target, string column) { return typeof(T).GetProperty(column)?.GetValue(target, null); } private static IEnumerable<Type> GetColumnsType<T>() { return (from x in typeof(T).GetProperties() select x.PropertyType).ToArray(); } } public class ConsoleTableOptions { public IEnumerable<string> Columns { get; set; } = Array.Empty<string>(); public bool EnableCount { get; set; } = true; public Alignment NumberAlignment { get; set; } public TextWriter OutputTo { get; set; } = Console.Out; } public enum Format { Default, MarkDown, Alternative, Minimal } public enum Alignment { Left, Right } } namespace MrovLib { public abstract class AssetBundleLoaderManager { internal DirectoryInfo pluginsFolder = new DirectoryInfo(Assembly.GetExecutingAssembly().Location).Parent.Parent; internal Logger Logger = new Logger("AssetBundleLoader", LoggingType.Debug); public virtual List<string> BundleExtensions { get; internal set; } = new List<string>(1) { "mrovbundle" }; public virtual List<string> BundleBlacklist { get; internal set; } = new List<string>(); public Dictionary<string, AssetBundle> LoadedBundles { get; internal set; } = new Dictionary<string, AssetBundle>(); public Dictionary<Type, AssetBundleLoader> AssetBundleLoadersByType { get; internal set; } = new Dictionary<Type, AssetBundleLoader>(); public Dictionary<AssetBundle, int> LoadedAssetsCount { get; internal set; } = new Dictionary<AssetBundle, int>(); public List<T> GetLoadedAssets<T>() where T : Object { if (AssetBundleLoadersByType.TryGetValue(typeof(T), out var value) && value is AssetBundleLoader<T> assetBundleLoader) { return assetBundleLoader.LoadedAssets; } return new List<T>(); } public void LoadAllBundles() { string bundlesPath = pluginsFolder.FullName; Logger.LogDebug("Loading asset bundles from: " + bundlesPath); if (!Directory.Exists(bundlesPath)) { Logger.LogWarning("AssetBundles folder not found: " + bundlesPath); return; } BundleExtensions.ForEach(delegate(string ext) { LoadAllBundlesInFolder(bundlesPath, ext); }); Logger.LogCustom(string.Format("Loaded {0} asset bundles: [{1}]", LoadedBundles.Count, string.Join(", ", LoadedBundles.Keys)), (LogLevel)16, LoggingType.Basic); } private void LoadAllBundlesInFolder(string bundlesPath, string bundleExtension) { string[] files = Directory.GetFiles(bundlesPath, "*." + bundleExtension, SearchOption.AllDirectories); Logger.LogInfo($"Found {files.Length} asset bundles with extension {bundleExtension}"); string[] array = files; foreach (string text in array) { string fileName = Path.GetFileName(text); LoadBundle(text, fileName); } } private void LoadBundle(string bundlePath, string bundleName) { try { AssetBundle bundle = AssetBundle.LoadFromFile(bundlePath); if ((Object)(object)bundle == (Object)null) { Logger.LogError("Failed to load asset bundle: " + bundleName); return; } if (BundleBlacklist.Contains(((Object)bundle).name.Replace(".weatherbundle", ""))) { Logger.LogWarning("Asset bundle " + ((Object)bundle).name + " is blacklisted, skipping loading!"); bundle.UnloadAsync(true); return; } LoadedBundles[bundleName] = bundle; Logger.LogInfo("Loaded asset bundle: " + bundleName); AssetBundleLoadersByType.Keys.ToList().ForEach(delegate(Type LoaderType) { AssetBundleLoader assetBundleLoader = AssetBundleLoadersByType[LoaderType]; Logger.LogCustom($"Loading assets of type {assetBundleLoader} from bundle {bundleName}", (LogLevel)32, LoggingType.Developer); assetBundleLoader.LoadFromBundle(bundle); }); } catch (Exception ex) { Logger.LogError("Error loading bundle " + bundleName + ": " + ex.Message); Logger.LogCustom(ex.StackTrace ?? "", (LogLevel)2, LoggingType.Debug); } } public virtual void ConvertLoadedAssets() { throw new NotImplementedException(); } } public abstract class AssetBundleLoader { public virtual void LoadFromBundle(AssetBundle bundle) { throw new NotImplementedException(); } } public class AssetBundleLoader<T> : AssetBundleLoader where T : Object { public Type AssetType => typeof(T); public List<T> LoadedAssets { get; private set; } = new List<T>(); public override void LoadFromBundle(AssetBundle bundle) { LoadedAssets.AddRange(LoadContentFromBundle(bundle)); } public virtual List<T> LoadContentFromBundle(AssetBundle bundle) { return bundle.LoadAllAssets<T>().ToList(); } public void Reset() { LoadedAssets = new List<T>(); } public override string ToString() { return typeof(T).Name; } } public abstract class ConfigHandler<T, CT> { public virtual ConfigEntry<CT> ConfigEntry { get; set; } public virtual CT DefaultValue { get; set; } public abstract T Value { get; } } public class ConfigManager { public static ConfigFile configFile; public static ConfigManager Instance { get; internal set; } public virtual void Init(ConfigFile config) { Instance = new ConfigManager(config); } public ConfigManager(ConfigFile config) { configFile = config; } } public static class ContentManager { internal static Terminal Terminal; internal static List<TerminalNode> Nodes = new List<TerminalNode>(); internal static List<TerminalKeyword> Keywords = new List<TerminalKeyword>(); public static List<BuyableThing> Buyables = new List<BuyableThing>(); public static List<Creature> Creatures = new List<Creature>(); public static List<Route> Routes = new List<Route>(); public static List<Scrap> Scraps = new List<Scrap>(); public static RouteDictionary RouteDictionary = new RouteDictionary(); internal static List<UnlockableSuit> UnlockableSuits = new List<UnlockableSuit>(); internal static List<TerminalKeyword> Verbs => Keywords.Where((TerminalKeyword k) => k.isVerb).ToList(); internal static Dictionary<TerminalKeyword, TerminalKeyword> DefaultVerbs => Keywords.Distinct().ToDictionary((TerminalKeyword v) => v, (TerminalKeyword v) => v.defaultVerb); internal static TerminalKeyword RouteKeyword => ((IEnumerable<TerminalKeyword>)Verbs).FirstOrDefault((Func<TerminalKeyword, bool>)((TerminalKeyword v) => ((Object)v).name == "Route")); internal static TerminalKeyword RouteInfoKeyword => ((IEnumerable<TerminalKeyword>)Verbs).FirstOrDefault((Func<TerminalKeyword, bool>)((TerminalKeyword v) => ((Object)v).name == "Info")); internal static TerminalKeyword RouteConfirmKeyword => ((IEnumerable<TerminalKeyword>)Verbs).FirstOrDefault((Func<TerminalKeyword, bool>)((TerminalKeyword v) => ((Object)v).name == "Confirm")); internal static TerminalKeyword RouteDenyKeyword => ((IEnumerable<TerminalKeyword>)Verbs).FirstOrDefault((Func<TerminalKeyword, bool>)((TerminalKeyword v) => ((Object)v).name == "Deny")); internal static TerminalKeyword MoonsKeyword => ((IEnumerable<TerminalKeyword>)Keywords).FirstOrDefault((Func<TerminalKeyword, bool>)((TerminalKeyword v) => ((Object)v).name == "Moons")); internal static TerminalKeyword ViewKeyword => ((IEnumerable<TerminalKeyword>)Verbs).FirstOrDefault((Func<TerminalKeyword, bool>)((TerminalKeyword v) => ((Object)v).name == "View")); internal static TerminalKeyword BuyKeyword => ((IEnumerable<TerminalKeyword>)Verbs).FirstOrDefault((Func<TerminalKeyword, bool>)((TerminalKeyword v) => ((Object)v).name == "Buy")); internal static TerminalNode CancelRouteNode { get { TerminalKeyword routeKeyword = RouteKeyword; if (routeKeyword == null) { return null; } return routeKeyword.compatibleNouns[0].result.terminalOptions[0].result; } } internal static TerminalNode CancelPurchaseNode { get { TerminalKeyword buyKeyword = BuyKeyword; if (buyKeyword == null) { return null; } return buyKeyword.compatibleNouns[0].result.terminalOptions[1].result; } } public static List<BuyableItem> Items => (from b in Buyables where b.Type == PurchaseType.Item select b into buyable select buyable as BuyableItem).ToList(); public static List<BuyableDecoration> Decorations => (from b in Buyables where b.Type == PurchaseType.Decoration select b into buyable select buyable as BuyableDecoration).ToList(); public static List<BuyableUnlockable> Unlockables => (from b in Buyables where b.Type == PurchaseType.Unlockable select b into buyable select buyable as BuyableUnlockable).ToList(); public static List<BuyableSuit> Suits => (from b in Buyables where b.Type == PurchaseType.Suit select b into buyable select buyable as BuyableSuit).ToList(); public static List<BuyableCar> Vehicles => (from b in Buyables where b.Type == PurchaseType.Vehicle select b into buyable select buyable as BuyableCar).ToList(); public static List<BuyableBundle> Bundles => (from b in Buyables where b.Type == PurchaseType.Bundle select b into buyable select buyable as BuyableBundle).ToList(); public static BuyableThing GetBuyable(Item item) { return Buyables.FirstOrDefault((BuyableThing b) => b.Name == item.itemName); } public static BuyableThing GetBuyable(UnlockableItem unlockable) { return Buyables.FirstOrDefault((BuyableThing b) => b.Name == unlockable.unlockableName); } public static BuyableThing GetBuyable(BuyableVehicle vehicle) { return Buyables.FirstOrDefault((BuyableThing b) => b.Name == vehicle.vehicleDisplayName); } public static BuyableThing GetBuyable(string name) { return Buyables.FirstOrDefault((BuyableThing b) => b.Name.ToLowerInvariant() == name.ToLowerInvariant()); } public static BuyableThing GetBuyable(TerminalNode node) { return Buyables.FirstOrDefault((BuyableThing b) => (Object)(object)b.Nodes.Node == (Object)(object)node || (Object)(object)b.Nodes.NodeConfirm == (Object)(object)node); } public static void AddTerminalKeywords(List<TerminalKeyword> keywords) { List<TerminalKeyword> list = Terminal.terminalNodes.allKeywords.ToList(); list.AddRange(keywords); Terminal.terminalNodes.allKeywords = list.ToArray(); Keywords = Terminal.terminalNodes.allKeywords.ToList(); } public static void AddTerminalNodes(List<TerminalNode> nodes) { List<TerminalNode> list = Terminal.terminalNodes.terminalNodes.ToList(); list.AddRange(nodes); Terminal.terminalNodes.terminalNodes = list; Nodes = list; } internal static void Clear() { Nodes.Clear(); Keywords.Clear(); Terminal = null; Buyables.Clear(); Creatures.Clear(); Routes.Clear(); Scraps.Clear(); RouteDictionary.Clear(); } public static void Init(Terminal terminal) { Clear(); Terminal = terminal; List<TerminalNode> list = Resources.FindObjectsOfTypeAll<TerminalNode>().ToList(); if (!Plugin.MapperRestoreCompat.IsModPresent) { Plugin.logger.LogDebug((object)"Forcefully removing Mapper nodes"); list.RemoveAll((TerminalNode node) => ((Object)node).name.ToLower().Contains("mapper")); } if (Plugin.ShipInventoryCompat.IsModPresent) { Plugin.logger.LogDebug((object)"Forcefully removing InventoryBuy node"); list.RemoveAll((TerminalNode node) => ((Object)node).name.ToLower() == "InventoryBuy".ToLower()); } Nodes = list; Keywords = terminal.terminalNodes.allKeywords.ToList(); UnlockableSuits = Object.FindObjectsOfType<UnlockableSuit>(true).ToList(); List<SelectableLevel> gameLevels = SharedMethods.GetGameLevels(); int i; for (i = 0; i < gameLevels.Count; i++) { SelectableLevel level = gameLevels[i]; List<TerminalNode> list2 = list.Where((TerminalNode x) => x.buyRerouteToMoon == i || x.displayPlanetInfo == i).Distinct().ToList(); if (Plugin.LLL.IsModPresent && list2.Count > 2) { List<TerminalNode> LLLNodes = SharedMethods.GetLevelTerminalNodes(level); list2.RemoveAll((TerminalNode node) => !LLLNodes.Contains(node)); } for (int j = 0; j < list2.Count; j++) { Plugin.DebugLogger.LogDebug($"Node: {list2[j]}"); _ = (Object)(object)list2[j] == (Object)null; } RelatedNodes nodes = new RelatedNodes { Node = list2.Where((TerminalNode node) => node.buyRerouteToMoon == -2).Distinct().ToList() .FirstOrDefault(), NodeConfirm = list2.Where((TerminalNode node) => node.buyRerouteToMoon != -2).Distinct().ToList() .LastOrDefault() }; Routes.Add(new Route(level, nodes)); } List<Item> buyableItems = terminal.buyableItemsList.ToList(); for (int k = 0; k < buyableItems.Count; k++) { Item item = buyableItems[k]; Plugin.DebugLogger.LogDebug("Item: " + item.itemName); Plugin.DebugLogger.LogDebug($"Item index: {buyableItems.IndexOf(item)}"); Plugin.DebugLogger.LogDebug($"Is terminal null: {(Object)(object)terminal == (Object)null}"); List<TerminalNode> list3 = list.Where((TerminalNode x) => x.buyItemIndex == buyableItems.IndexOf(item)).ToList(); Plugin.DebugLogger.LogDebug($"Possible nodes count: {list3.Count}"); if (list3.Count == 0) { Plugin.DebugLogger.LogWarning("No possible terminal nodes found for item " + item.itemName + " - skipping!"); continue; } for (int l = 0; l < list3.Count; l++) { Plugin.DebugLogger.LogDebug($"Node: {list3[l]}"); _ = (Object)(object)list3[l] == (Object)null; } RelatedNodes nodes2 = new RelatedNodes { Node = list3.Distinct().ToList().First((TerminalNode node) => node.isConfirmationNode), NodeConfirm = list3.Distinct().ToList().First((TerminalNode node) => !node.isConfirmationNode) }; Buyables.Add(new BuyableItem(terminal, nodes2)); } List<UnlockableItem> unlockables = StartOfRound.Instance.unlockablesList.unlockables.ToList(); for (int m = 0; m < unlockables.Count; m++) { UnlockableItem unlockable = unlockables[m]; Plugin.DebugLogger.LogDebug("Unlockable: " + unlockable.unlockableName); List<TerminalNode> list4 = list.Where((TerminalNode x) => x.shipUnlockableID == unlockables.IndexOf(unlockable)).Distinct().ToList(); if ((Object)(object)unlockable.suitMaterial != (Object)null) { Plugin.DebugLogger.LogDebug("Suit material: " + ((Object)unlockable.suitMaterial).name); RelatedNodes nodes3 = new RelatedNodes { Node = list4.Where((TerminalNode node) => !node.buyUnlockable).Distinct().ToList() .FirstOrDefault(), NodeConfirm = list4.Where((TerminalNode node) => node.buyUnlockable).Distinct().ToList() .LastOrDefault() }; if (Suits.Any((BuyableSuit buyable) => (Object)(object)buyable.SuitMaterial == (Object)(object)unlockable.suitMaterial)) { Plugin.DebugLogger.LogWarning("Suit " + unlockable.unlockableName + " already exists in the buyables list - skipping!"); continue; } Buyables.Add(new BuyableSuit(terminal, nodes3, unlockable) { UnlockableSuit = ((IEnumerable<UnlockableSuit>)UnlockableSuits).FirstOrDefault((Func<UnlockableSuit, bool>)((UnlockableSuit s) => (Object)(object)s.suitMaterial == (Object)(object)unlockable.suitMaterial)) }); } else { if (CheckPossibleNodeNull(list4)) { continue; } RelatedNodes relatedNodes = new RelatedNodes { Node = list4.Where((TerminalNode node) => !node.buyUnlockable).Distinct().ToList() .FirstOrDefault(), NodeConfirm = list4.Where((TerminalNode node) => node.buyUnlockable).Distinct().ToList() .LastOrDefault() }; if (!((Object)(object)relatedNodes.Node == (Object)null) && !((Object)(object)relatedNodes.NodeConfirm == (Object)null)) { if ((Object)(object)unlockable.shopSelectionNode != (Object)null && !unlockable.alwaysInStock) { Buyables.Add(new BuyableDecoration(terminal, relatedNodes)); } else { Buyables.Add(new BuyableUnlockable(terminal, relatedNodes)); } } } } List<BuyableVehicle> buyableVehicles = terminal.buyableVehicles.ToList(); for (int n = 0; n < buyableVehicles.Count; n++) { BuyableVehicle vehicle = buyableVehicles[n]; Plugin.DebugLogger.LogDebug("Vehicle: " + vehicle.vehicleDisplayName); List<TerminalNode> list5 = list.Where((TerminalNode x) => x.buyVehicleIndex == buyableVehicles.IndexOf(vehicle)).Distinct().ToList(); if (!CheckPossibleNodeNull(list5)) { RelatedNodes relatedNodes2 = new RelatedNodes { Node = list5.Where((TerminalNode node) => node.isConfirmationNode).Distinct().ToList() .FirstOrDefault(), NodeConfirm = list5.Where((TerminalNode node) => !node.isConfirmationNode).Distinct().ToList() .LastOrDefault() }; if (!((Object)(object)relatedNodes2.Node == (Object)null) && !((Object)(object)relatedNodes2.NodeConfirm == (Object)null)) { Buyables.Add(new BuyableCar(terminal, relatedNodes2)); } } } if (Plugin.ItemWeightsCompat.IsModPresent) { Plugin.logger.LogDebug((object)"Forcefully updating Cruiser nodes"); try { for (int num = 0; num < Vehicles.Count; num++) { BuyableCar buyableCar = Vehicles[num]; Terminal.LoadNewNodeIfAffordable(buyableCar.Nodes.Node); } } catch (Exception ex) { Plugin.logger.LogWarning((object)("Error while updating Cruiser nodes: " + ex.Message)); } } RouteDictionary.PopulateDictionary(Routes); List<Item> list6 = StartOfRound.Instance.allItemsList.itemsList.Distinct().ToList(); foreach (Item item3 in list6) { new Scrap(item3); } List<TerminalNode> enemyFiles = Terminal.enemyFiles; foreach (TerminalNode item4 in enemyFiles) { Regex regex = new Regex("s$"); Creature item2 = new Creature { Name = regex.Replace(item4.creatureName, ""), InfoNode = item4 }; Creatures.Add(item2); } EventManager.ContentManagerReady.Invoke(); } internal static bool CheckPossibleNodeNull(List<TerminalNode> possibleNodes) { List<TerminalNode> list = new List<TerminalNode>(); for (int i = 0; i < possibleNodes.Count; i++) { Plugin.DebugLogger.LogDebug($"Node: {possibleNodes[i]}"); if (!((Object)(object)possibleNodes[i] == (Object)null) && possibleNodes[i].itemCost > 0) { list.Add(possibleNodes[i]); } } return possibleNodes == list; } } public class Defaults { public static readonly List<string> VanillaLevels = new List<string>(13) { "Gordion", "Experimentation", "Assurance", "Vow", "March", "Offense", "Adamance", "Rend", "Dine", "Titan", "Liquidation", "Embrion", "Artifice" }; [Obsolete("Use CompanyMoons instead!!!")] public static readonly string CompanyLevel = "Gordion"; public static string CompanyVanillaMoon = "Gordion"; public static readonly List<LevelWeatherType> VanillaWeathers = new List<LevelWeatherType>(7) { (LevelWeatherType)(-1), (LevelWeatherType)0, (LevelWeatherType)3, (LevelWeatherType)1, (LevelWeatherType)2, (LevelWeatherType)4, (LevelWeatherType)5 }; public static List<SelectableLevel> CompanyMoons => LevelHelper.CompanyMoons; public static List<string> CompanyMoonNames => CompanyMoons.Select((SelectableLevel moon) => StringResolver.GetAlphanumericName(moon)).ToList(); public static bool IsVanillaLevel(SelectableLevel level) { return VanillaLevels.Select((string l) => l.ToLowerInvariant()).Contains(StringResolver.GetNumberlessName(level).ToLowerInvariant()); } } public static class EventManager { public static CustomEvent<Terminal> TerminalStart = new CustomEvent<Terminal>(); public static CustomEvent<StartOfRound> LobbyDisabled = new CustomEvent<StartOfRound>(); public static CustomEvent LaunchOptionsLoaded = new CustomEvent(); public static CustomEvent MainMenuLoaded = new CustomEvent(); public static CustomEvent<string> SceneLoaded = new CustomEvent<string>(); public static CustomEvent ContentManagerReady = new CustomEvent(); } public static class LevelHelper { public static List<SelectableLevel> Levels { get; private set; } public static List<SelectableLevel> SortedLevels { get; private set; } public static SelectableLevel CompanyMoon { get; private set; } public static List<SelectableLevel> CompanyMoons { get; private set; } public static string LongestPlanetName { get; private set; } public static void Populate() { Levels = StartOfRound.Instance.levels.ToList(); CompanyMoons = Levels.Where((SelectableLevel level) => !level.planetHasTime && !level.spawnEnemiesAndScrap).ToList(); CompanyMoon = CompanyMoons.FirstOrDefault(); SortedLevels = Levels.ToList(); SortedLevels.Sort((SelectableLevel a, SelectableLevel b) => StringResolver.GetNumberlessName(a).CompareTo(StringResolver.GetNumberlessName(b))); LongestPlanetName = (from level in Levels select StringResolver.GetNumberlessName(level) into name orderby name.Length descending select name).FirstOrDefault(); } public static SelectableLevel GetRandomLevel() { if (Levels == null || Levels.Count == 0) { Plugin.logger.LogError((object)"Levels list is null or empty, cannot get a random level."); return null; } int index = new Random().Next(Levels.Count); return Levels[index]; } public static bool IsVanillaLevel(SelectableLevel level) { return Defaults.IsVanillaLevel(level); } public static void Reset(StartOfRound startOfRound) { Plugin.LogDebug("LevelHelper.Reset called"); Levels = null; SortedLevels = null; CompanyMoon = null; } } public static class LevenshteinDistance { public static int Calculate(string source1, string source2) { int length = source1.Length; int length2 = source2.Length; int[,] array = new int[length + 1, length2 + 1]; if (length == 0) { return length2; } if (length2 == 0) { return length; } int num = 0; while (num <= length) { array[num, 0] = num++; } int num2 = 0; while (num2 <= length2) { array[0, num2] = num2++; } for (int i = 1; i <= length; i++) { for (int j = 1; j <= length2; j++) { int num3 = ((source2[j - 1] != source1[i - 1]) ? 1 : 0); array[i, j] = Math.Min(Math.Min(array[i - 1, j] + 1, array[i, j - 1] + 1), array[i - 1, j - 1] + num3); } } return array[length, length2]; } } public enum LoggingType { Basic, Debug, Developer } public class Logger { public ManualLogSource _logSource = Logger.CreateLogSource("MrovLib"); public virtual string _name { get; set; } public virtual string ModName { get; set; } = "MrovLib"; public virtual ManualLogSource LogSource { get { return _logSource; } set { _logSource = value; } } private LoggingType _defaultLoggingType { get; set; } public Logger(string SourceName, LoggingType defaultLoggingType = LoggingType.Basic) { _defaultLoggingType = defaultLoggingType; _name = ((SourceName == ModName) ? "" : SourceName); } [Obsolete("Use Logger(string SourceName, LoggingType defaultLoggingType) instead.")] public Logger(string name) : this(name, LoggingType.Debug) { } [Obsolete("Use Logger(string SourceName, LoggingType defaultLoggingType) instead.")] public Logger(string name, ConfigEntry<bool> enabled = null) : this(name, LoggingType.Debug) { } public virtual bool ShouldLog(LoggingType type) { return LocalConfigManager.Debug.Value >= type; } public void LogCustom(string data, LogLevel level, LoggingType type) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (ShouldLog(type)) { LogSource.Log(level, (object)("[" + _name + "] " + data)); } } public void Log(LogLevel level, string data) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (ShouldLog(_defaultLoggingType)) { LogSource.Log(level, (object)("[" + _name + "] " + data)); } } public void LogInfo(string data) { Log((LogLevel)16, data); } public void LogWarning(string data) { Log((LogLevel)4, data); } public void LogError(string data) { Log((LogLevel)2, data); } public void LogDebug(string data) { Log((LogLevel)32, data); } public void LogFatal(string data) { Log((LogLevel)1, data); } public void LogMessage(string data) { Log((LogLevel)8, data); } [Obsolete("Use LogInfo(string data) instead.")] public void LogInfo(object data) { Log((LogLevel)16, data.ToString()); } [Obsolete("Use LogWarning(string data) instead.")] public void LogWarning(object data) { Log((LogLevel)4, data.ToString()); } [Obsolete("Use LogError(string data) instead.")] public void LogError(object data) { Log((LogLevel)2, data.ToString()); } [Obsolete("Use LogDebug(string data) instead.")] public void LogDebug(object data) { Log((LogLevel)32, data.ToString()); } [Obsolete("Use LogFatal(string data) instead.")] public void LogFatal(object data) { Log((LogLevel)1, data.ToString()); } [Obsolete("Use LogMessage(string data) instead.")] public void LogMessage(object data) { Log((LogLevel)8, data.ToString()); } } public static class PlanetChecker { public static List<string> duplicates = new List<string>(); public static bool ContainsRepeats => duplicates.Count > 0; public static void CheckRepeatingPlanetNames() { SelectableLevel[] levels = StartOfRound.Instance.levels; ResolverCache<bool> resolverCache = new ResolverCache<bool>(); SelectableLevel[] array = levels; foreach (SelectableLevel val in array) { if (resolverCache.Contains(val.PlanetName)) { Plugin.logger.LogWarning((object)("Duplicate planet name: " + val.PlanetName)); duplicates.Add(val.PlanetName); } resolverCache.Add(val.PlanetName, value: true); } } } [BepInPlugin("MrovLib", "MrovLib", "0.4.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { internal static ManualLogSource logger; internal static Logger DebugLogger; internal static Harmony harmony = new Harmony("MrovLib"); internal static ConfigEntry<LoggingType> DebugLogging; public static LLL LLL; public static DawnLib DawnLibCompat; public static WeatherTweaks WeatherTweaks; public static MapperRestoreCompat MapperRestoreCompat; public static ShipInventoryCompat ShipInventoryCompat; public static ItemWeightsCompat ItemWeightsCompat; private void Awake() { logger = ((BaseUnityPlugin)this).Logger; harmony.PatchAll(); SceneManager.sceneLoaded += SceneManagerPatches.OnSceneLoaded; LocalConfigManager.Init(((BaseUnityPlugin)this).Config); DebugLogger = new Logger("Debug", LoggingType.Debug); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin MrovLib is loaded!"); DebugLogger.LogWarning("Debug logs enabled!"); EventManager.LobbyDisabled.AddListener(StringResolver.Reset); EventManager.LobbyDisabled.AddListener(LevelHelper.Reset); EventManager.MainMenuLoaded.AddListener(StartCompats); } internal static void LogDebug(string log) { DebugLogger.LogDebug(log); } public void StartCompats() { logger.LogDebug((object)"Starting compatibility patches..."); LLL = new LLL("imabatby.lethallevelloader"); DawnLibCompat = new DawnLib("com.github.teamxiaolan.dawnlib"); WeatherTweaks = new WeatherTweaks("WeatherTweaks"); MapperRestoreCompat = new MapperRestoreCompat("butterystancakes.lethalcompany.restoremapper"); ShipInventoryCompat = new ShipInventoryCompat("ShipInventory"); ItemWeightsCompat = new ItemWeightsCompat("DarthLilo.ItemWeights"); } } internal class LocalConfigManager : ConfigManager { public static ConfigEntry<LoggingType> Debug { get; private set; } private LocalConfigManager(ConfigFile config) : base(config) { Debug = ConfigManager.configFile.Bind<LoggingType>("General", "Logging levels", LoggingType.Basic, "Enable debug logging"); Plugin.DebugLogging = Debug; } public new static void Init(ConfigFile config) { ConfigManager.Instance = new LocalConfigManager(config); } } public class ResolverCache<T> { private Dictionary<string, T> _cache = new Dictionary<string, T>(); public void Add(string key, T value) { if (key == null) { throw new ArgumentNullException("key"); } if (_cache.ContainsKey(key)) { _cache[key] = value; } else { _cache.Add(key, value); } } public T Get(string key) { if (_cache.TryGetValue(key, out var value)) { return value; } return default(T); } public bool Contains(string key) { return _cache.ContainsKey(key); } public void Reset() { _cache.Clear(); } } public class RouteDictionary { public Dictionary<SelectableLevel, Route> Routes = new Dictionary<SelectableLevel, Route>(); public void AddRoute(Route route) { Routes.Add(route.Level, route); } public void PopulateDictionary(List<Route> routes) { foreach (Route route in routes) { AddRoute(route); } } public Route GetRoute(SelectableLevel level) { return Routes[level]; } public void Clear() { Routes.Clear(); } } public class SharedMethods { public static string GetWeather(SelectableLevel level) { string text = (Plugin.WeatherTweaks.IsModPresent ? WeatherTweaks.CurrentWeather(level) : ((!Plugin.LLL.IsModPresent) ? ((object)(LevelWeatherType)(ref level.currentWeather)).ToString() : LLL.GetWeather(level))); Plugin.LogDebug("Weather: " + text); if (!(text == "None")) { return text; } return ""; } public static string GetNumberlessPlanetName(SelectableLevel level) { return new string(level.PlanetName.SkipWhile((char c) => !char.IsLetter(c)).ToArray()); } public static string GetAlphanumericName(SelectableLevel level) { Regex regex = new Regex("^[0-9]+|[-_/\\\\\\ ]"); return new string(regex.Replace(level.PlanetName, "").AsSpan()); } public static List<GrabbableObject> GetShipObjects() { GameObject val = GameObject.Find("/Environment/HangarShip"); return val.GetComponentsInChildren<GrabbableObject>().ToList(); } public static List<SelectableLevel> GetGameLevels() { Plugin.DebugLogger.LogDebug("GetGameLevels called"); if (Plugin.LLL.IsModPresent) { Plugin.DebugLogger.LogDebug("LLL present"); return LLL.GetLevels(); } Plugin.DebugLogger.LogDebug("No LLL present"); return LevelHelper.Levels; } public static bool IsMoonHiddenLLL(SelectableLevel level) { if (Plugin.LLL.IsModPresent) { return LLL.IsMoonHidden(level); } return false; } public static bool IsMoonLockedLLL(SelectableLevel level) { if (Plugin.LLL.IsModPresent) { return LLL.IsMooonLocked(level); } return false; } public static List<TerminalNode> GetLevelTerminalNodes(SelectableLevel level) { if (Plugin.LLL.IsModPresent) { return LLL.GetLevelTerminalNodes(level); } return new List<TerminalNode>(); } public static object GetLLLMoonsCataloguePage() { if (Plugin.LLL.IsModPresent) { return LLL.GetMoonsCataloguePage(); } return null; } public static List<SelectableLevel> GetLevelsFromLLLTag(string tag) { if (Plugin.LLL.IsModPresent) { return LLL.GetLevelsWithTag(tag); } return new List<SelectableLevel>(); } public static LevelWeatherType GetLevelWeather(SelectableLevel level) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return level.currentWeather; } } public enum PlaceholderStringType { All, Company, Modded, Vanilla } public class StringResolver { private static Dictionary<string, SelectableLevel> _levelsDictionary = null; private static ResolverCache<SelectableLevel[]> stringToLevelsCache = new ResolverCache<SelectableLevel[]>(); public static Dictionary<string, SelectableLevel> StringToLevel { get { if (_levelsDictionary != null) { return _levelsDictionary; } Dictionary<string, SelectableLevel> Levels = new Dictionary<string, SelectableLevel>(); StartOfRound.Instance.levels.ToList().ForEach(delegate(SelectableLevel level) { Levels.TryAdd(GetNumberlessName(level).ToLowerInvariant(), level); Levels.TryAdd(GetAlphanumericName(level).ToLowerInvariant(), level); Levels.TryAdd(level.sceneName.ToLowerInvariant(), level); Levels.TryAdd(level.PlanetName.ToLowerInvariant(), level); Levels.TryAdd(((Object)level).name.ToLowerInvariant(), level); }); _levelsDictionary = Levels; return Levels; } set { _levelsDictionary = value; } } public static string[] ConvertStringToArray(string str) { return (from s in str.Split(';') where !string.IsNullOrWhiteSpace(s) select s.Trim()).ToArray(); } public static string GetNumberlessName(SelectableLevel level) { return new string(level.PlanetName.SkipWhile((char c) => !char.IsLetter(c)).ToArray()); } public static string GetAlphanumericName(SelectableLevel level) { Regex regex = new Regex("^[0-9]+ |[^a-zA-Z0-9]"); return new string(regex.Replace(level.PlanetName, "").AsSpan()); } [Obsolete("Use ResolveStringToLevels instead")] public static SelectableLevel ResolveStringToLevel(string str) { return StringToLevel.GetValueOrDefault(str.ToLowerInvariant()); } public static SelectableLevel[] ResolveStringToLevels(string str) { if (stringToLevelsCache.Contains(str)) { return stringToLevelsCache.Get(str); } Plugin.DebugLogger.LogInfo("Resolving " + str + " into SelectableLevels"); string[] array = ConvertStringToArray(str); List<SelectableLevel> list = new List<SelectableLevel>(); List<SelectableLevel> remove = new List<SelectableLevel>(); if (array.Count() == 0) { return Array.Empty<SelectableLevel>(); } string[] array2 = array; foreach (string text in array2) { if (text.StartsWith("!")) { Plugin.LogDebug("String " + text + " will be removed from final consideration!"); remove.AddRange(ResolveStringToLevels(text.Substring(1))); } if (text.StartsWith("£")) { Plugin.LogDebug("String " + text + " is a DawnLib NamespacedKey"); if (!Plugin.DawnLibCompat.IsModPresent) { Plugin.LogDebug("DawnLib is not present, skipping"); continue; } List<SelectableLevel> levelsFromTags = Plugin.DawnLibCompat.GetLevelsFromTags(text.Substring(1)); Plugin.LogDebug("String " + text + " resolved to selectable levels: " + string.Join(',', levelsFromTags.Select((SelectableLevel l) => l.PlanetName))); list.AddRange(levelsFromTags); continue; } if (text.StartsWith("$")) { Plugin.LogDebug("String " + text + " is a LLL ContentTag"); if (!Plugin.LLL.IsModPresent) { Plugin.LogDebug("LLL is not present, skipping"); continue; } List<SelectableLevel> levelsWithTag = LLL.GetLevelsWithTag(text.Substring(1)); Plugin.LogDebug("String " + text + " resolved to selectable levels: " + string.Join(',', levelsWithTag.Select((SelectableLevel l) => l.PlanetName))); list.AddRange(levelsWithTag); continue; } switch (text.ToLowerInvariant()) { case "all": case "company": case "modded": case "custom": case "vanilla": { SelectableLevel[] array3 = ResolveStringPlaceholderLevels(text); Plugin.LogDebug("String " + text + " resolved to selectable levels: " + string.Join(',', array3.Select((SelectableLevel l) => l.PlanetName))); list.AddRange(array3); continue; } } SelectableLevel valueOrDefault = StringToLevel.GetValueOrDefault(text.ToLowerInvariant()); if (!((Object)(object)valueOrDefault == (Object)null)) { Plugin.LogDebug($"String {text} resolved to selectable level: {valueOrDefault}"); if (!list.Contains(valueOrDefault)) { list.Add(valueOrDefault); } } } SelectableLevel[] array4 = (from listItem in list where (Object)(object)listItem != (Object)null where !remove.Contains(listItem) select listItem).ToArray(); stringToLevelsCache.Add(str, array4); Plugin.DebugLogger.LogInfo("Resolved " + str + " into " + string.Join(',', array4.Select((SelectableLevel l) => l.PlanetName))); return array4; } public static PlaceholderStringType GetPlaceholderType(string input) { return input.ToLowerInvariant() switch { "all" => PlaceholderStringType.All, "company" => PlaceholderStringType.Company, "modded" => PlaceholderStringType.Modded, "custom" => PlaceholderStringType.Modded, "vanilla" => PlaceholderStringType.Vanilla, _ => PlaceholderStringType.All, }; } public static SelectableLevel[] ResolveStringPlaceholderLevels(string input) { PlaceholderStringType placeholderType = GetPlaceholderType(input); List<SelectableLevel> companyLevels = LevelHelper.CompanyMoons; Plugin.logger.LogInfo((object)("Resolving placeholder " + input + " into SelectableLevels")); Plugin.logger.LogWarning((object)("Company levels: " + string.Join(',', companyLevels.Select((SelectableLevel l) => l.PlanetName)))); return (placeholderType switch { PlaceholderStringType.All => StartOfRound.Instance.levels.Where((SelectableLevel level) => Object.op_Implicit((Object)(object)level) != companyLevels.Contains(level)).ToArray(), PlaceholderStringType.Company => companyLevels.ToArray(), PlaceholderStringType.Vanilla => (from level in StartOfRound.Instance.levels where companyLevels.Contains(level) where Defaults.IsVanillaLevel(level) select level).ToArray(), PlaceholderStringType.Modded => (from level in StartOfRound.Instance.levels where Object.op_Implicit((Object)(object)level) != companyLevels.Contains(level) where !Defaults.IsVanillaLevel(level) select level).ToArray(), _ => Array.Empty<SelectableLevel>(), }).ToArray(); } public static void Reset(StartOfRound startOfRound) { Plugin.LogDebug("StringResolver.Reset called"); StringToLevel = null; stringToLevelsCache.Reset(); } } public class WeightHandler<T> { private Dictionary<T, int> dictionary = new Dictionary<T, int>(); public virtual Logger logger => Plugin.DebugLogger; public int Count { get { int count = dictionary.Count; if (count == 0) { throw new InvalidOperationException("Dictionary is empty - nothing to pick from!"); } return count; } } public int Sum { get { int num = 0; foreach (int value in dictionary.Values) { num += value; } if (num <= 0) { if (Count == 1) { return 1; } logger.LogError("Weights sum to 0 or negative: [" + string.Join(", ", dictionary.Select((KeyValuePair<T, int> kv) => kv.Key?.ToString() + "=" + kv.Value)) + "]"); throw new InvalidOperationException("Sum cannot be 0 or negative"); } return num; } } public List<T> Keys => dictionary.Keys.ToList(); public List<int> Values => dictionary.Values.ToList(); public void Add(T key, int value) { if (key == null) { throw new ArgumentNullException("key"); } if (Comparer<int>.Default.Compare(value, 0) < 0) { throw new ArgumentOutOfRangeException("value", "Value cannot be negative"); } if (dictionary.TryGetValue(key, out var value2)) { if (Comparer<int>.Default.Compare(value, value2) > 0) { dictionary[key] = value; } } else { dictionary.Add(key, value); } } public void Set(T key, int value) { if (key == null) { throw new ArgumentNullException("key"); } if (Comparer<int>.Default.Compare(value, 0) < 0) { throw new ArgumentOutOfRangeException("value", "Value cannot be negative"); } if (dictionary.TryGetValue(key, out var _)) { dictionary[key] = value; } else { dictionary.Add(key, value); } } public void Remove(T key) { if (key == null) { throw new ArgumentNullException("key"); } dictionary.Remove(key); } public int Get(T key) { if (key == null) { throw new ArgumentNullException("key"); } if (!dictionary.TryGetValue(key, out var value)) { return 0; } return value; } public int RandomIndex() { Random random = new Random(); return random.Next(0, Sum); } public T Random() { int num = RandomIndex(); int num2 = 0; foreach (KeyValuePair<T, int> item in dictionary.OrderByDescending((KeyValuePair<T, int> v) => v.Value)) { num2 += item.Value; if (num <= num2) { logger.LogWarning($"Picked {item.Key} with a roll of {num} out of {Sum}"); return item.Key; } } return dictionary.Keys.FirstOrDefault(); } } public static class PluginInfo { public const string PLUGIN_GUID = "MrovLib"; public const string PLUGIN_NAME = "MrovLib"; public const string PLUGIN_VERSION = "0.4.2"; } } namespace MrovLib.Patches { [HarmonyPatch(typeof(HangarShipDoor), "Start")] internal class HangarShipDoorPatch { private static void Postfix(HangarShipDoor __instance) { PlanetChecker.CheckRepeatingPlanetNames(); if (PlanetChecker.ContainsRepeats) { Plugin.logger.LogFatal((object)"Duplicate planet names detected - this will cause issues with the game!"); } } } internal static class SceneManagerPatches { private static bool WasLoadedBefore; internal static void OnSceneLoaded(Scene scene, LoadSceneMode mode) { string name = ((Scene)(ref scene)).name; if (name == "InitSceneLaunchOptions") { EventManager.LaunchOptionsLoaded.Invoke(); } if (name == "MainMenu") { if (WasLoadedBefore) { return; } EventManager.MainMenuLoaded.Invoke(); WasLoadedBefore = true; } EventManager.SceneLoaded.Invoke(name); } } [HarmonyPatch(typeof(StartOfRound), "OnDisable")] internal class StartOfRoundPatch { private static void Postfix(StartOfRound __instance) { EventManager.LobbyDisabled.Invoke(__instance); } } [HarmonyPatch(typeof(Terminal), "ParseWord")] [HarmonyAfter(new string[] { "imabatby.lethallevelloader" })] internal static class TerminalParseWord { internal static TerminalKeyword lastParsedVerbKeyword; [HarmonyPostfix] internal static void TerminalParseWord_Postfix(Terminal __instance, ref TerminalKeyword __result, string playerWord) { if ((Object)(object)__result != (Object)null) { TerminalKeyword val = TryFindAlternativeNoun(__instance, __result, playerWord); if ((Object)(object)val != (Object)null) { __result = val; } } } internal static bool ValidateNounKeyword(TerminalKeyword verbKeyword, TerminalKeyword nounKeyword) { for (int i = 0; i < verbKeyword.compatibleNouns.Length; i++) { if ((Object)(object)verbKeyword.compatibleNouns[i].noun == (Object)(object)nounKeyword) { return true; } } return false; } internal static TerminalKeyword TryFindAlternativeNoun(Terminal terminal, TerminalKeyword foundKeyword, string playerInput) { if ((((Object)(object)foundKeyword != (Object)null) & !terminal.hasGottenVerb) && foundKeyword.isVerb) { lastParsedVerbKeyword = foundKeyword; } if ((Object)(object)foundKeyword != (Object)null && !foundKeyword.isVerb && terminal.hasGottenVerb && (Object)(object)lastParsedVerbKeyword != (Object)null) { if (!ValidateNounKeyword(lastParsedVerbKeyword, foundKeyword)) { TerminalKeyword[] allKeywords = ContentManager.Terminal.terminalNodes.allKeywords; foreach (TerminalKeyword val in allKeywords) { if (!val.isVerb && (Object)(object)val != (Object)(object)foundKeyword && val.word == playerInput && ValidateNounKeyword(lastParsedVerbKeyword, val)) { lastParsedVerbKeyword = null; return val; } } } } return foundKeyword; } } [HarmonyPatch(typeof(Terminal), "Start")] internal class TerminalStart { [HarmonyPriority(800)] [HarmonyPostfix] private static void RunMeFirst(Terminal __instance) { LevelHelper.Populate(); ContentManager.Init(__instance); } private static void Postfix(Terminal __instance) { EventManager.TerminalStart.Invoke(__instance); } } } namespace MrovLib.Events { public class CustomEvent<T> { public delegate void ParameterEvent(T param); public bool HasListeners => Listeners != 0; public int Listeners { get; internal set; } private event ParameterEvent onParameterEvent; public void Invoke(T param) { this.onParameterEvent?.Invoke(param); } public void AddListener(ParameterEvent listener) { onParameterEvent += listener; Listeners++; } public void RemoveListener(ParameterEvent listener) { onParameterEvent -= listener; Listeners--; } } public class CustomEvent { public delegate void Event(); public bool HasListeners => Listeners != 0; public int Listeners { get; internal set; } private event Event onEvent; public void Invoke() { this.onEvent?.Invoke(); } public void AddListener(Event listener) { onEvent += listener; Listeners++; } public void RemoveListener(Event listener) { onEvent -= listener; Listeners--; } } } namespace MrovLib.Definitions { public abstract class CommandNode { public string Name = Name.ToLowerInvariant(); public CommandType Type = CommandType.SubCommand; public string CommandArgument; private List<CommandNode> _subcommands = new List<CommandNode>(); public virtual List<CommandNode> Subcommands { get { if (Type == CommandType.SubCommand) { return new List<CommandNode>(); } return _subcommands; } set { _subcommands = value; } } protected CommandNode(string Name) { } public override string ToString() { return Name; } } public enum CommandType { Command, SubCommand } public class ContentTypeResolver<ResolveType> { internal static Dictionary<string, ResolveType> _dictionary = new Dictionary<string, ResolveType>(); internal static ResolverCache<ResolveType[]> _cache = new ResolverCache<ResolveType[]>(); public Dictionary<string, ResolveType> StringToType { get { if (_dictionary != null) { return _dictionary; } _dictionary = CreateTypeDictionary(); return _dictionary; } set { _dictionary = value; } } public virtual Dictionary<string, ResolveType> CreateTypeDictionary() { return new Dictionary<string, ResolveType>(); } public virtual ResolveType[] Resolve(string input) { if (_cache.Contains(input)) { return _cache.Get(input); } List<ResolveType> list = new List<ResolveType>(); List<ResolveType> list2 = new List<ResolveType>(); string[] array = StringResolver.ConvertStringToArray(input); string[] array2 = array; foreach (string text in array2) { if (text.StartsWith("!")) { Plugin.LogDebug("String " + text + " will be removed from final consideration!"); list2.AddRange(Resolve(text.Substring(1))); } ResolveType valueOrDefault = _dictionary.GetValueOrDefault(text.ToLowerInvariant()); if (text != null) { Plugin.LogDebug($"String {text} resolved to: {valueOrDefault}"); if (!list.Contains(valueOrDefault)) { list.Add(valueOrDefault); } } } return list.ToArray(); } public virtual void Reset() { _dictionary.Clear(); _cache.Reset(); } } } namespace MrovLib.ContentType { public class BuyableBundle : BuyableThing { public List<BuyableThing> Contents = new List<BuyableThing>(); public new int Price => Contents.Sum((BuyableThing c) => c.Price); public BuyableBundle(Terminal terminal, RelatedNodes nodes, string name, List<Item> items = null, List<UnlockableItem> unlockables = null) : base(terminal, nodes) { Type = PurchaseType.Bundle; foreach (Item item in items) { BuyableThing buyable = ContentManager.GetBuyable(item); Contents.Add(buyable); } foreach (UnlockableItem unlockable in unlockables) { BuyableThing buyable2 = ContentManager.GetBuyable(unlockable); Contents.Add(buyable2); } Name = name; ContentManager.Buyables.Add(this); } public BuyableBundle(Terminal terminal, RelatedNodes nodes, string name, string[] items) : base(terminal, nodes) { Type = PurchaseType.Bundle; foreach (string name2 in items) { BuyableThing buyable = ContentManager.GetBuyable(name2); Contents.Add(buyable); } Name = name; ContentManager.Buyables.Add(this); } } public class BuyableCar : BuyableThing { public BuyableVehicle Vehicle; public override int Price { get { return base.Price; } set { base.Price = value; Nodes.Node.itemCost = value; } } public BuyableCar(Terminal terminal, RelatedNodes nodes) : base(terminal, nodes) { Type = PurchaseType.Vehicle; Vehicle = ContentManager.Terminal.buyableVehicles[nodes.Node.buyVehicleIndex]; Price = Nodes.Node.itemCost; Name = Vehicle.vehicleDisplayName; ContentManager.Vehicles.Add(this); } } public class BuyableDecoration : BuyableUnlockable { public UnlockableItem Decoration => Unlockable; public override int Price { get { return base.Price; } set { base.Price = value; Decoration.shopSelectionNode.itemCost = value; } } public bool InRotation { get { if (!ContentManager.Terminal.ShipDecorSelection.Contains(Nodes.Node)) { return ContentManager.Terminal.ShipDecorSelection.Any((TerminalNode node) => ((Object)node).name == ((Object)Nodes.Node).name); } return true; } } public BuyableDecoration(Terminal terminal, RelatedNodes nodes) : base(terminal, nodes) { Type = PurchaseType.Decoration; UnlockableItem unlockable = StartOfRound.Instance.unlockablesList.unlockables[Nodes.Node.shipUnlockableID]; Unlockable = unlockable; Price = Decoration.shopSelectionNode.itemCost; Name = Decoration.unlockableName; } } public class BuyableItem : BuyableThing { public Item Item; private int PercentOff { get { return ContentManager.Terminal.itemSalesPercentages[Nodes.Node.buyItemIndex]; } set { ContentManager.Terminal.itemSalesPercentages[Nodes.Node.buyItemIndex] = value; } } public int Discount { get { if (PercentOff == 100) { return 0; } return 100 - PercentOff; } } public float DiscountPercentage => (float)PercentOff / 100f; public override int Price { get { return base.Price; } set { base.Price = value; Item.creditsWorth = value; } } public BuyableItem(Terminal terminal, RelatedNodes nodes) : base(terminal, nodes) { Type = PurchaseType.Item; Item = terminal.buyableItemsList[nodes.Node.buyItemIndex]; Price = Item.creditsWorth; Name = Item.itemName; } } public enum PurchaseType { Item, Unlockable, Decoration, Suit, Vehicle, Route, Bundle } public class RelatedNodes { public TerminalNode Node; public TerminalNode NodeConfirm; } public interface IBuyable { string Name { get; } int Price { get; } } public class BuyableThing : IBuyable { public PurchaseType Type; public RelatedNodes Nodes; public virtual string Name { get; set; } public virtual int Price { get; set; } public BuyableThing(Terminal terminal, RelatedNodes nodes) { Plugin.DebugLogger.LogWarning($"BuyableThing constructor: {terminal}, {nodes}; type: {Type}"); Nodes = nodes; } public override string ToString() { return Name ?? ""; } } public class BuyableSuit : BuyableThing { public UnlockableSuit UnlockableSuit; public UnlockableItem Suit; public Material SuitMaterial; public override int Price { get { return base.Price; } set { base.Price = value; if ((Object)(object)Suit.shopSelectionNode != (Object)null) { Suit.shopSelectionNode.itemCost = value; } } } public bool IsUnlocked { get { if (!Suit.hasBeenUnlockedByPlayer) { return Suit.alreadyUnlocked; } return true; } } public bool InRotation { get { if ((Object)(object)Nodes.Node == (Object)null) { return false; } if (!ContentManager.Terminal.ShipDecorSelection.Contains(Nodes.Node)) { return ContentManager.Terminal.ShipDecorSelection.Any((TerminalNode node) => ((Object)node).name == ((Object)Nodes.Node).name); } return true; } } public BuyableSuit(Terminal terminal, RelatedNodes nodes, UnlockableItem unlockable) : base(terminal, nodes) { Type = PurchaseType.Suit; Suit = unlockable; SuitMaterial = Suit.suitMaterial; Price = ((!((Object)(object)Suit.shopSelectionNode == (Object)null)) ? Suit.shopSelectionNode.itemCost : 0); Name = Suit.unlockableName ?? ((Object)Suit.suitMaterial).name; } } public class BuyableUnlockable : BuyableThing { public UnlockableItem Unlockable; public bool IsUnlocked { get { if (!Unlockable.hasBeenUnlockedByPlayer) { return Unlockable.alreadyUnlocked; } return true; } } public bool IsInStorage => Unlockable.inStorage; public BuyableUnlockable(Terminal terminal, RelatedNodes nodes) : base(terminal, nodes) { Type = PurchaseType.Unlockable; Unlockable = StartOfRound.Instance.unlockablesList.unlockables[Nodes.Node.shipUnlockableID]; int price = 0; if ((Object)(object)Nodes.Node != (Object)null) { if (Nodes.Node.itemCost <= 0) { Plugin.DebugLogger.LogDebug("Unlockable " + Unlockable.unlockableName + " does not have an upgrade price"); price = Nodes.Node.itemCost; } else { price = Nodes.Node.itemCost; } } Price = price; Name = Unlockable.unlockableName; } } public class Creature { public string Name { get; set; } public TerminalNode InfoNode { get; set; } public bool Discovered => ContentManager.Terminal.scannedEnemyIDs.Contains(InfoNode.creatureFileID); public override string ToString() { return Name; } } public class Route : IBuyable { public SelectableLevel Level; public RelatedNodes Nodes; public string Name { get; set; } public int Price { get { if (!((Object)(object)Nodes.Node != (Object)null)) { return 0; } return Nodes.Node.itemCost; } } public Route(SelectableLevel level, RelatedNodes nodes) { Level = level; Nodes = nodes; Name = SharedMethods.GetNumberlessPlanetName(level); Plugin.DebugLogger.LogWarning($"Route constructor: {level}; {nodes.Node}, {nodes.NodeConfirm}"); } public override string ToString() { return Name ?? ""; } } public class Scrap { public Item Item { get; set; } public string Name => Item.itemName; public float Weight => Item.weight; public bool Conductive => Item.isConductiveMetal; public int ValueMin => Item.minValue; public int ValueMax => Item.maxValue; public bool HasBattery => Item.requiresBattery; public Scrap(Item item) { Plugin.DebugLogger.LogWarning("Scrap constructor: " + item.itemName); Item = item; ContentManager.Scraps.Add(this); } public override string ToString() { return Name; } } } namespace MrovLib.Compatibility { public class CompatibilityBase { private bool? _enabled; public string ModGUID { get; internal set; } public string ModVersion { get; internal set; } public bool IsModPresent { get { if (!_enabled.HasValue) { _enabled = Chainloader.PluginInfos.ContainsKey(ModGUID); } if (ModVersion != null && _enabled.Value && Chainloader.PluginInfos.TryGetValue(ModGUID, out var value)) { if (value.Metadata.Version.Major != new Version(ModVersion).Major) { _enabled = false; } else { _enabled = value.Metadata.Version >= new Version(ModVersion); } } return _enabled.Value; } } public Assembly GetModAssembly { get { if (!IsModPresent) { return null; } return ((object)Chainloader.PluginInfos[ModGUID].Instance).GetType().Assembly; } } public CompatibilityBase(string guid, string version = null) { ModGUID = guid; ModVersion = version; _enabled = null; Plugin.DebugLogger.LogInfo("CompatibilityBase Constructor called, GUID: " + ModGUID + ", Version: " + ModVersion); } } public class DawnLib : CompatibilityBase { public DawnLib(string guid, string version = null) : base(guid, version) { } public List<SelectableLevel> GetLevelsFromTags(string inputTag) { return LevelHelper.Levels.Where((SelectableLevel level) => ((DawnBaseInfo<DawnMoonInfo>)(object)SelectableLevelExtensions.GetDawnInfo(level)).AllTags().Any((NamespacedKey tag) => tag.Key.ToLower().Equals(inputTag.ToLower(), StringComparison.OrdinalIgnoreCase))).ToList(); } } public class ItemWeightsCompat : CompatibilityBase { public ItemWeightsCompat(string guid, string version = null) : base(guid, version) { } } public class LLL : CompatibilityBase { public LLL(string guid, string version = null) : base(guid, version) { } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] public static string GetWeather(SelectableLevel level) { ExtendedLevel val = ((IEnumerable<ExtendedLevel>)PatchedContent.ExtendedLevels).FirstOrDefault((Func<ExtendedLevel, bool>)((ExtendedLevel x) => (Object)(object)x.SelectableLevel == (Object)(object)level)); return TerminalManager.GetWeatherConditions(val).ToString().Replace("(", "") .Replace(")", ""); } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] public static List<SelectableLevel> GetLevels() { return PatchedContent.SelectableLevels; } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] public static bool IsMoonHidden(SelectableLevel level) { ExtendedLevel val = ((IEnumerable<ExtendedLevel>)PatchedContent.ExtendedLevels).FirstOrDefault((Func<ExtendedLevel, bool>)((ExtendedLevel x) => (Object)(object)x.SelectableLevel == (Object)(object)level)); return val.IsRouteHidden; } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] public static bool IsMooonLocked(SelectableLevel level) { ExtendedLevel val = ((IEnumerable<ExtendedLevel>)PatchedContent.ExtendedLevels).FirstOrDefault((Func<ExtendedLevel, bool>)((ExtendedLevel x) => (Object)(object)x.SelectableLevel == (Object)(object)level)); return val.IsRouteLocked; } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] public static List<TerminalNode> GetLevelTerminalNodes(SelectableLevel level) { ExtendedLevel val = ((IEnumerable<ExtendedLevel>)PatchedContent.ExtendedLevels).FirstOrDefault((Func<ExtendedLevel, bool>)((ExtendedLevel x) => (Object)(object)x.SelectableLevel == (Object)(object)level)); return new List<TerminalNode>(3) { val.RouteNode, val.RouteConfirmNode, val.InfoNode }; } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] public static MoonsCataloguePage GetMoonsCataloguePage() { return TerminalManager.currentMoonsCataloguePage; } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] public static List<SelectableLevel> GetLevelsWithTag(string tag) { List<ExtendedContent> allExtendedContentsByTag = ContentTagManager.GetAllExtendedContentsByTag(tag); List<SelectableLevel> list = new List<SelectableLevel>(); foreach (ExtendedContent item in allExtendedContentsByTag) { ExtendedLevel val = (ExtendedLevel)(object)((item is ExtendedLevel) ? item : null); if (val != null) { list.Add(val.SelectableLevel); } } return list; } } public class MapperRestoreCompat : CompatibilityBase { public MapperRestoreCompat(string guid, string version = null) : base(guid, version) { } } public class ShipInventoryCompat : CompatibilityBase { public ShipInventoryCompat(string guid, string version = null) : base(guid, version) { } } public class WeatherTweaks : CompatibilityBase { internal static MethodInfo GetPlanetCurrentWeather; public WeatherTweaks(string guid, string version = null) : base(guid, version) { } public static void GetMethodType() { Assembly getModAssembly = Plugin.WeatherTweaks.GetModAssembly; Type type = getModAssembly.GetType(Plugin.WeatherTweaks.ModGUID + ".Variables"); if (type != null) { Plugin.logger.LogInfo((object)$"Type {type} found"); GetPlanetCurrentWeather = type.GetMethod("GetPlanetCurrentWeather", BindingFlags.Static | BindingFlags.Public); if (GetPlanetCurrentWeather != null) { Plugin.logger.LogInfo((object)$"Method {GetPlanetCurrentWeather} found - BetaWeatherTweaks"); return; } Plugin.logger.LogError((object)$"Method {GetPlanetCurrentWeather} not found"); GetPlanetCurrentWeather = type.GetMethod("GetPlanetCurrentWeather", BindingFlags.Static | BindingFlags.NonPublic); if (GetPlanetCurrentWeather != null) { Plugin.logger.LogInfo((object)$"Method {GetPlanetCurrentWeather} found"); } else { Plugin.logger.LogError((object)$"Method {GetPlanetCurrentWeather} not found"); } } else { Plugin.LogDebug("Type " + Plugin.WeatherTweaks.ModGUID + ".Variables not found"); } } public static string CurrentWeather(SelectableLevel level) { if (Plugin.WeatherTweaks.IsModPresent && GetPlanetCurrentWeather == null) { GetMethodType(); } if (GetPlanetCurrentWeather != null) { return (string)GetPlanetCurrentWeather.Invoke(null, new object[2] { level, true }); } Plugin.logger.LogError((object)"GetPlanetCurrentWeather method not found"); return ""; } } } namespace MrovLib.API { [Obsolete] public class SharedMethods { public static string GetWeather(SelectableLevel level) { return MrovLib.SharedMethods.GetWeather(level); } public static string GetNumberlessPlanetName(SelectableLevel level) { return MrovLib.SharedMethods.GetNumberlessPlanetName(level); } public static List<GrabbableObject> GetShipObjects() { return MrovLib.SharedMethods.GetShipObjects(); } public static List<SelectableLevel> GetGameLevels() { return MrovLib.SharedMethods.GetGameLevels(); } public static bool IsMoonHiddenLLL(SelectableLevel level) { return MrovLib.SharedMethods.IsMoonHiddenLLL(level); } public static bool IsMoonLockedLLL(SelectableLevel level) { return MrovLib.SharedMethods.IsMoonLockedLLL(level); } public static List<TerminalNode> GetLevelTerminalNodes(SelectableLevel level) { return MrovLib.SharedMethods.GetLevelTerminalNodes(level); } public static object GetLLLMoonsCataloguePage() { return MrovLib.SharedMethods.GetLLLMoonsCataloguePage(); } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }