using 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("DunGen")] [assembly: IgnoresAccessChecksTo("DunGen.Integration.ASPP")] [assembly: IgnoresAccessChecksTo("DunGen.Integration.UnityNav")] [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("Unity.XR.CoreUtils")] [assembly: IgnoresAccessChecksTo("Unity.XR.Management")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.ConformanceAutomation")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.MetaQuestSupport")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.MockRuntime")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.OculusQuestSupport")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.RuntimeDebugger")] [assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.SpatialTracking")] [assembly: IgnoresAccessChecksTo("UnityEngine.UI")] [assembly: IgnoresAccessChecksTo("UnityEngine.XR.LegacyInputHelpers")] [assembly: AssemblyCompany("MrovLib")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Common methods for my mods.")] [assembly: AssemblyFileVersion("0.4.3.0")] [assembly: AssemblyInformationalVersion("0.4.3+8bc60a5f05b1369f5eb9ec44a68a9f5f65e4aa55")] [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 NumericTypes = new HashSet { typeof(int), typeof(double), typeof(decimal), typeof(long), typeof(short), typeof(sbyte), typeof(byte), typeof(ulong), typeof(ushort), typeof(uint), typeof(float) }; public IList Columns { get; } public IList Rows { get; } public ConsoleTableOptions Options { get; } public Type[] ColumnTypes { get; private set; } public IList Formats { get; private set; } public ConsoleTable(params string[] columns) : this(new ConsoleTableOptions { Columns = new List(columns) }) { } public ConsoleTable(ConsoleTableOptions options) { Options = options ?? throw new ArgumentNullException("options"); Rows = new List(); Columns = new List(options.Columns); } public ConsoleTable AddColumn(IEnumerable 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 action) { action(Options); return this; } public static ConsoleTable FromDictionary(Dictionary> values) { ConsoleTable consoleTable = new ConsoleTable(); List list = values.SelectMany((KeyValuePair> x) => x.Value.Keys).Distinct().ToList(); list.Insert(0, ""); consoleTable.AddColumn(list); foreach (KeyValuePair> value2 in values) { List list2 = new List { value2.Key }; foreach (string item in list.Skip(1)) { list2.Add(value2.Value.TryGetValue(item, out var value) ? value : ""); } consoleTable.AddRow(list2.Cast().ToArray()); } return consoleTable; } public static ConsoleTable From(IEnumerable values) { ConsoleTable consoleTable = new ConsoleTable { ColumnTypes = GetColumnsType().ToArray() }; List columns = GetColumns().ToList(); consoleTable.AddColumn(columns); foreach (IEnumerable item in values.Select((T value) => columns.Select((string column) => GetColumnValue(value, column)))) { consoleTable.AddRow(item.ToArray()); } return consoleTable; } public static ConsoleTable From(DataTable dataTable) { ConsoleTable consoleTable = new ConsoleTable(); List 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 columnLengths = ColumnLengths(); List 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 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 columnLengths, List columnAlignment) { List list = new List { 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 columnLengths = ColumnLengths(); Format(columnLengths, delimiter); string text = string.Format(Formats[0].TrimStart(), Columns.ToArray()); List 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 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 columnLengths = ColumnLengths(); Format(columnLengths, '\0'); string text = string.Format(Formats[0].TrimStart(), Columns.ToArray()); List 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 columnLengths, char delimiter = '|') { List 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 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 GetColumns() { return (from x in typeof(T).GetProperties() select x.Name).ToArray(); } private static object GetColumnValue(object target, string column) { return typeof(T).GetProperty(column)?.GetValue(target, null); } private static IEnumerable GetColumnsType() { return (from x in typeof(T).GetProperties() select x.PropertyType).ToArray(); } } public class ConsoleTableOptions { public IEnumerable Columns { get; set; } = Array.Empty(); 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 BundleExtensions { get; internal set; } = new List(1) { "mrovbundle" }; public virtual List BundleBlacklist { get; internal set; } = new List(); public Dictionary LoadedBundles { get; internal set; } = new Dictionary(); public Dictionary AssetBundleLoadersByType { get; internal set; } = new Dictionary(); public Dictionary LoadedAssetsCount { get; internal set; } = new Dictionary(); public List GetLoadedAssets() where T : Object { if (AssetBundleLoadersByType.TryGetValue(typeof(T), out var value) && value is AssetBundleLoader assetBundleLoader) { return assetBundleLoader.LoadedAssets; } return new List(); } 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 : AssetBundleLoader where T : Object { public Type AssetType => typeof(T); public List LoadedAssets { get; private set; } = new List(); public override void LoadFromBundle(AssetBundle bundle) { LoadedAssets.AddRange(LoadContentFromBundle(bundle)); } public virtual List LoadContentFromBundle(AssetBundle bundle) { return bundle.LoadAllAssets().ToList(); } public void Reset() { LoadedAssets = new List(); } public override string ToString() { return typeof(T).Name; } } public class CompatibilityHandler { private bool? _enabled; public string ModGUID { get; internal set; } public string ModVersion { get; internal set; } private bool MatchExactVersion { get; set; } = true; public bool IsModPresent { get { Plugin.LogDebug($"IsModPresent called, GUID: {ModGUID}, Enabled: {_enabled}, Version: {ModVersion}"); if (!_enabled.HasValue) { _enabled = Chainloader.PluginInfos.ContainsKey(ModGUID); Plugin.DebugLogger.LogInfo($"Mod presence checked: {_enabled}"); } if (ModVersion != null && _enabled.Value && Chainloader.PluginInfos.TryGetValue(ModGUID, out var value)) { Plugin.LogDebug($"Checking version {value.Metadata.Version} against {ModVersion}"); if (value.Metadata.Version.Major != new Version(ModVersion).Major) { _enabled = false; } else if (MatchExactVersion) { _enabled = value.Metadata.Version == new Version(ModVersion); } 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 CompatibilityHandler(string guid, string version = null, bool matchExactVersion = false) { ModGUID = guid; ModVersion = version; _enabled = null; MatchExactVersion = matchExactVersion; Plugin.DebugLogger.LogInfo($"CompatibilityHandler Constructor called, GUID: {ModGUID}, Version: {ModVersion} (exact? {matchExactVersion})"); EventManager.MainMenuLoaded.AddListener(CheckIfModIsPresentAndInit); } internal void CheckIfModIsPresentAndInit() { if (!IsModPresent) { Plugin.DebugLogger.LogWarning("Mod " + ModGUID + " is not present. Skipping initialization logic."); } else { Init(); } } public virtual void Init() { Plugin.DebugLogger.LogInfo("Mod " + ModGUID + " is present!"); } public void SetToMatchExactVersion(bool setting) { MatchExactVersion = setting; _enabled = null; Plugin.DebugLogger.LogInfo($"SetToMatchExactVersion called, setting: {setting}"); } } public abstract class ConfigHandler { public virtual ConfigEntry 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 Nodes = new List(); internal static List Keywords = new List(); public static List Buyables = new List(); public static List Creatures = new List(); public static List Routes = new List(); public static List Scraps = new List(); public static RouteDictionary RouteDictionary = new RouteDictionary(); internal static List UnlockableSuits = new List(); internal static List Verbs => Keywords.Where((TerminalKeyword k) => k.isVerb).ToList(); internal static Dictionary DefaultVerbs => Keywords.Distinct().ToDictionary((TerminalKeyword v) => v, (TerminalKeyword v) => v.defaultVerb); internal static TerminalKeyword RouteKeyword => ((IEnumerable)Verbs).FirstOrDefault((Func)((TerminalKeyword v) => ((Object)v).name == "Route")); internal static TerminalKeyword RouteInfoKeyword => ((IEnumerable)Verbs).FirstOrDefault((Func)((TerminalKeyword v) => ((Object)v).name == "Info")); internal static TerminalKeyword RouteConfirmKeyword => ((IEnumerable)Verbs).FirstOrDefault((Func)((TerminalKeyword v) => ((Object)v).name == "Confirm")); internal static TerminalKeyword RouteDenyKeyword => ((IEnumerable)Verbs).FirstOrDefault((Func)((TerminalKeyword v) => ((Object)v).name == "Deny")); internal static TerminalKeyword MoonsKeyword => ((IEnumerable)Keywords).FirstOrDefault((Func)((TerminalKeyword v) => ((Object)v).name == "Moons")); internal static TerminalKeyword ViewKeyword => ((IEnumerable)Verbs).FirstOrDefault((Func)((TerminalKeyword v) => ((Object)v).name == "View")); internal static TerminalKeyword BuyKeyword => ((IEnumerable)Verbs).FirstOrDefault((Func)((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 Items => (from b in Buyables where b.Type == PurchaseType.Item select b into buyable select buyable as BuyableItem).ToList(); public static List Decorations => (from b in Buyables where b.Type == PurchaseType.Decoration select b into buyable select buyable as BuyableDecoration).ToList(); public static List Unlockables => (from b in Buyables where b.Type == PurchaseType.Unlockable select b into buyable select buyable as BuyableUnlockable).ToList(); public static List Suits => (from b in Buyables where b.Type == PurchaseType.Suit select b into buyable select buyable as BuyableSuit).ToList(); public static List Vehicles => (from b in Buyables where b.Type == PurchaseType.Vehicle select b into buyable select buyable as BuyableCar).ToList(); public static List 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 keywords) { List list = Terminal.terminalNodes.allKeywords.ToList(); list.AddRange(keywords); Terminal.terminalNodes.allKeywords = list.ToArray(); Keywords = Terminal.terminalNodes.allKeywords.ToList(); } public static void AddTerminalNodes(List nodes) { List 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 list = Resources.FindObjectsOfTypeAll().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(true).ToList(); List gameLevels = SharedMethods.GetGameLevels(); int i; for (i = 0; i < gameLevels.Count; i++) { SelectableLevel level = gameLevels[i]; List list2 = list.Where((TerminalNode x) => x.buyRerouteToMoon == i || x.displayPlanetInfo == i).Distinct().ToList(); if (Plugin.LLL.IsModPresent && list2.Count > 2) { List 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 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 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 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 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)UnlockableSuits).FirstOrDefault((Func)((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 buyableVehicles = terminal.buyableVehicles.ToList(); for (int n = 0; n < buyableVehicles.Count; n++) { BuyableVehicle vehicle = buyableVehicles[n]; Plugin.DebugLogger.LogDebug("Vehicle: " + vehicle.vehicleDisplayName); List 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 list6 = StartOfRound.Instance.allItemsList.itemsList.Distinct().ToList(); foreach (Item item3 in list6) { new Scrap(item3); } List 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 possibleNodes) { List list = new List(); 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 VanillaLevels = new List(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 VanillaWeathers = new List(7) { (LevelWeatherType)(-1), (LevelWeatherType)0, (LevelWeatherType)3, (LevelWeatherType)1, (LevelWeatherType)2, (LevelWeatherType)4, (LevelWeatherType)5 }; public static List CompanyMoons => LevelHelper.CompanyMoons; public static List 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 TerminalStart = new CustomEvent(); public static CustomEvent LobbyDisabled = new CustomEvent(); public static CustomEvent LaunchOptionsLoaded = new CustomEvent(); public static CustomEvent MainMenuLoaded = new CustomEvent(); public static CustomEvent SceneLoaded = new CustomEvent(); public static CustomEvent ContentManagerReady = new CustomEvent(); } public static class LevelHelper { public static List Levels { get; private set; } public static List SortedLevels { get; private set; } public static SelectableLevel CompanyMoon { get; private set; } public static List 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 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 duplicates = new List(); public static bool ContainsRepeats => duplicates.Count > 0; public static void CheckRepeatingPlanetNames() { SelectableLevel[] levels = StartOfRound.Instance.levels; ResolverCache resolverCache = new ResolverCache(); 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.3")] [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 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 Debug { get; private set; } private LocalConfigManager(ConfigFile config) : base(config) { Debug = ConfigManager.configFile.Bind("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 { private Dictionary _cache = new Dictionary(); 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 Routes = new Dictionary(); public void AddRoute(Route route) { Routes.Add(route.Level, route); } public void PopulateDictionary(List 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 GetShipObjects() { GameObject val = GameObject.Find("/Environment/HangarShip"); return val.GetComponentsInChildren().ToList(); } public static List 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 GetLevelTerminalNodes(SelectableLevel level) { if (Plugin.LLL.IsModPresent) { return LLL.GetLevelTerminalNodes(level); } return new List(); } public static object GetLLLMoonsCataloguePage() { if (Plugin.LLL.IsModPresent) { return LLL.GetMoonsCataloguePage(); } return null; } public static List GetLevelsFromLLLTag(string tag) { if (Plugin.LLL.IsModPresent) { return LLL.GetLevelsWithTag(tag); } return new List(); } 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 _levelsDictionary = null; private static ResolverCache stringToLevelsCache = new ResolverCache(); public static Dictionary StringToLevel { get { if (_levelsDictionary != null) { return _levelsDictionary; } Dictionary Levels = new Dictionary(); 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 list = new List(); List remove = new List(); if (array.Count() == 0) { return Array.Empty(); } 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 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 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 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(), }).ToArray(); } public static void Reset(StartOfRound startOfRound) { Plugin.LogDebug("StringResolver.Reset called"); StringToLevel = null; stringToLevelsCache.Reset(); } } public class WeightHandler { private Dictionary dictionary = new Dictionary(); 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 kv) => kv.Key?.ToString() + "=" + kv.Value)) + "]"); throw new InvalidOperationException("Sum cannot be 0 or negative"); } return num; } } public List Keys => dictionary.Keys.ToList(); public List Values => dictionary.Values.ToList(); public void Add(T key, int value) { if (key == null) { throw new ArgumentNullException("key"); } if (Comparer.Default.Compare(value, 0) < 0) { throw new ArgumentOutOfRangeException("value", "Value cannot be negative"); } if (dictionary.TryGetValue(key, out var value2)) { if (Comparer.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.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 item in dictionary.OrderByDescending((KeyValuePair 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.3"; } } 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 { 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 _subcommands = new List(); public virtual List Subcommands { get { if (Type == CommandType.SubCommand) { return new List(); } return _subcommands; } set { _subcommands = value; } } protected CommandNode(string Name) { } public override string ToString() { return Name; } } public enum CommandType { Command, SubCommand } public class ContentTypeResolver { internal static Dictionary _dictionary = new Dictionary(); internal static ResolverCache _cache = new ResolverCache(); public Dictionary StringToType { get { if (_dictionary != null) { return _dictionary; } _dictionary = CreateTypeDictionary(); return _dictionary; } set { _dictionary = value; } } public virtual Dictionary CreateTypeDictionary() { return new Dictionary(); } public virtual ResolveType[] Resolve(string input) { if (_cache.Contains(input)) { return _cache.Get(input); } List list = new List(); List list2 = new List(); 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 Contents = new List(); public new int Price => Contents.Sum((BuyableThing c) => c.Price); public BuyableBundle(Terminal terminal, RelatedNodes nodes, string name, List items = null, List 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 { [Obsolete("CompatibilityBase is deprecated, use CompatibilityHandler instead for better version handling and main menu loading.")] public class CompatibilityBase { private bool? _enabled; public string ModGUID { get; internal set; } public string ModVersion { get; internal set; } private bool MatchExactVersion { get; set; } = true; public bool IsModPresent { get { Plugin.LogDebug($"IsModPresent called, GUID: {ModGUID}, Enabled: {_enabled}, Version: {ModVersion}"); if (!_enabled.HasValue) { _enabled = Chainloader.PluginInfos.ContainsKey(ModGUID); Plugin.DebugLogger.LogInfo($"Mod presence checked: {_enabled}"); } if (ModVersion != null && _enabled.Value && Chainloader.PluginInfos.TryGetValue(ModGUID, out var value)) { Plugin.LogDebug($"Checking version {value.Metadata.Version} against {ModVersion}"); if (value.Metadata.Version.Major != new Version(ModVersion).Major) { _enabled = false; } else if (MatchExactVersion) { _enabled = value.Metadata.Version == new Version(ModVersion); } 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 void SetToMatchExactVersion(bool setting) { MatchExactVersion = setting; _enabled = null; Plugin.DebugLogger.LogInfo($"SetToMatchExactVersion called, setting: {setting}"); } } public class DawnLib : CompatibilityBase { public DawnLib(string guid, string version = null) : base(guid, version) { } public List GetLevelsFromTags(string inputTag) { return LevelHelper.Levels.Where((SelectableLevel level) => ((DawnBaseInfo)(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)PatchedContent.ExtendedLevels).FirstOrDefault((Func)((ExtendedLevel x) => (Object)(object)x.SelectableLevel == (Object)(object)level)); return TerminalManager.GetWeatherConditions(val).ToString().Replace("(", "") .Replace(")", ""); } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] public static List GetLevels() { return PatchedContent.SelectableLevels; } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] public static bool IsMoonHidden(SelectableLevel level) { ExtendedLevel val = ((IEnumerable)PatchedContent.ExtendedLevels).FirstOrDefault((Func)((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)PatchedContent.ExtendedLevels).FirstOrDefault((Func)((ExtendedLevel x) => (Object)(object)x.SelectableLevel == (Object)(object)level)); return val.IsRouteLocked; } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] public static List GetLevelTerminalNodes(SelectableLevel level) { ExtendedLevel val = ((IEnumerable)PatchedContent.ExtendedLevels).FirstOrDefault((Func)((ExtendedLevel x) => (Object)(object)x.SelectableLevel == (Object)(object)level)); return new List(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 GetLevelsWithTag(string tag) { List allExtendedContentsByTag = ContentTagManager.GetAllExtendedContentsByTag(tag); List list = new List(); 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 GetShipObjects() { return MrovLib.SharedMethods.GetShipObjects(); } public static List 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 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) { } } }