Decompiled source of MrovLib v0.2.17

MrovLib.dll

Decompiled a week ago
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 HarmonyLib;
using LethalLevelLoader;
using Microsoft.CodeAnalysis;
using MrovLib.Compatibility;
using MrovLib.ContentType;
using MrovLib.Events;
using UnityEngine;

[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("DissonanceVoip")]
[assembly: IgnoresAccessChecksTo("Facepunch Transport for Netcode for GameObjects")]
[assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")]
[assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging.DocCodeExamples")]
[assembly: IgnoresAccessChecksTo("Unity.Burst")]
[assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")]
[assembly: IgnoresAccessChecksTo("Unity.Collections")]
[assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")]
[assembly: IgnoresAccessChecksTo("Unity.Jobs")]
[assembly: IgnoresAccessChecksTo("Unity.Mathematics")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.Common")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.MetricTypes")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStats")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Component")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Configuration")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Implementation")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsReporting")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkProfiler.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkSolutionInterface")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Components")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Networking.Transport")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Csg")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.KdTree")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Poly2Tri")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Stl")]
[assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Config.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Authentication")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Analytics")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Configuration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Device")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Networking")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Registration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Scheduler")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Telemetry")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Threading")]
[assembly: IgnoresAccessChecksTo("Unity.Services.QoS")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Relay")]
[assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")]
[assembly: IgnoresAccessChecksTo("Unity.Timeline")]
[assembly: IgnoresAccessChecksTo("Unity.VisualEffectGraph.Runtime")]
[assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UI")]
[assembly: AssemblyCompany("MrovLib")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Common methods for my mods.")]
[assembly: AssemblyFileVersion("0.2.17.0")]
[assembly: AssemblyInformationalVersion("0.2.17+36cc34a7bde68bd261c2803392eb4623b52184bb")]
[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[]>();
			list.Add(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; } = new List<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 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 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<TerminalKeyword> Verbs => Keywords.Where((TerminalKeyword k) => k.isVerb).ToList();

		internal static TerminalKeyword RouteKeyword => Verbs.Where((TerminalKeyword v) => ((Object)v).name == "Route").FirstOrDefault();

		internal static TerminalKeyword RouteInfoKeyword => Verbs.Where((TerminalKeyword v) => ((Object)v).name == "Info").FirstOrDefault();

		internal static TerminalKeyword RouteConfirmKeyword => Verbs.Where((TerminalKeyword v) => ((Object)v).name == "Confirm").FirstOrDefault();

		internal static TerminalKeyword RouteDenyKeyword => Verbs.Where((TerminalKeyword v) => ((Object)v).name == "Deny").FirstOrDefault();

		internal static TerminalKeyword MoonsKeyword => Keywords.Where((TerminalKeyword v) => ((Object)v).name == "Moons").FirstOrDefault();

		internal static TerminalKeyword ViewKeyword => Verbs.Where((TerminalKeyword v) => ((Object)v).name == "View").FirstOrDefault();

		internal static TerminalKeyword BuyKeyword => Verbs.Where((TerminalKeyword v) => ((Object)v).name == "Buy").FirstOrDefault();

		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.Where((BuyableThing b) => b.Name == item.itemName).FirstOrDefault();
		}

		public static BuyableThing GetBuyable(UnlockableItem unlockable)
		{
			return Buyables.Where((BuyableThing b) => b.Name == unlockable.unlockableName).FirstOrDefault();
		}

		public static BuyableThing GetBuyable(BuyableVehicle vehicle)
		{
			return Buyables.Where((BuyableThing b) => b.Name == vehicle.vehicleDisplayName).FirstOrDefault();
		}

		public static BuyableThing GetBuyable(string name)
		{
			return Buyables.Where((BuyableThing b) => b.Name.ToLowerInvariant() == name.ToLowerInvariant()).FirstOrDefault();
		}

		public static BuyableThing GetBuyable(TerminalNode node)
		{
			return Buyables.Where((BuyableThing b) => (Object)(object)b.Nodes.Node == (Object)(object)node || (Object)(object)b.Nodes.NodeConfirm == (Object)(object)node).FirstOrDefault();
		}

		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();
			Plugin.logger.LogDebug((object)"Terminal Start");
			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();
			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.logger.LogDebug((object)$"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.logger.LogDebug((object)("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}");
				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().FirstOrDefault(),
					NodeConfirm = list3.Distinct().ToList().LastOrDefault()
				};
				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.logger.LogDebug((object)("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.logger.LogDebug((object)("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()
					};
					Buyables.Add(new BuyableSuit(terminal, nodes3, unlockable));
				}
				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));
					}
				}
			}
			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);
			}
		}

		internal static bool CheckPossibleNodeNull(List<TerminalNode> possibleNodes)
		{
			List<TerminalNode> list = new List<TerminalNode>();
			for (int i = 0; i < possibleNodes.Count; i++)
			{
				Plugin.logger.LogDebug((object)$"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"
		};

		public static readonly string CompanyLevel = "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 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 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 void Populate()
		{
			Levels = StartOfRound.Instance.levels.ToList();
			CompanyMoon = ((IEnumerable<SelectableLevel>)Levels).FirstOrDefault((Func<SelectableLevel, bool>)((SelectableLevel level) => StringResolver.GetNumberlessName(level) == Defaults.CompanyLevel));
			SortedLevels = Levels.ToList();
			SortedLevels.Sort((SelectableLevel a, SelectableLevel b) => StringResolver.GetNumberlessName(a).CompareTo(StringResolver.GetNumberlessName(b)));
		}

		public static void Reset(StartOfRound startOfRound)
		{
			Plugin.LogDebug("LevelHelper.Reset called");
			Levels = null;
			SortedLevels = null;
			CompanyMoon = null;
		}
	}
	public class Logger
	{
		private ManualLogSource LogSource = Logger.CreateLogSource(name);

		private ConfigEntry<bool> ConfigEntry = enabled ?? Plugin.DebugLogging;

		public Logger(string name, ConfigEntry<bool> enabled = null)
		{
		}

		public void Log(LogLevel level, object data)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			if (ConfigEntry.Value)
			{
				LogSource.Log(level, data);
			}
		}

		public void LogInfo(object data)
		{
			Log((LogLevel)16, data);
		}

		public void LogWarning(object data)
		{
			Log((LogLevel)4, data);
		}

		public void LogError(object data)
		{
			Log((LogLevel)2, data);
		}

		public void LogDebug(object data)
		{
			Log((LogLevel)32, data);
		}

		public void LogFatal(object data)
		{
			Log((LogLevel)1, data);
		}

		public void LogMessage(object data)
		{
			Log((LogLevel)8, data);
		}
	}
	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.2.17")]
	[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<bool> DebugLogging;

		public static LLL LLL;

		public static WeatherTweaks WeatherTweaks;

		public static MapperRestoreCompat MapperRestoreCompat;

		public static ShipInventoryCompat ShipInventoryCompat;

		private void Awake()
		{
			logger = ((BaseUnityPlugin)this).Logger;
			harmony.PatchAll();
			LocalConfigManager.Init(((BaseUnityPlugin)this).Config);
			DebugLogger = new Logger("MrovLib", DebugLogging);
			LLL = new LLL("imabatby.lethallevelloader");
			WeatherTweaks = new WeatherTweaks("WeatherTweaks");
			MapperRestoreCompat = new MapperRestoreCompat("butterystancakes.lethalcompany.restoremapper");
			ShipInventoryCompat = new ShipInventoryCompat("ShipInventory");
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin MrovLib is loaded!");
			DebugLogger.LogWarning("Debug logs enabled!");
			EventManager.LobbyDisabled.AddListener(StringResolver.Reset);
			EventManager.LobbyDisabled.AddListener(LevelHelper.Reset);
		}

		internal static void LogDebug(string log)
		{
			DebugLogger.LogDebug(log);
		}
	}
	internal class LocalConfigManager : ConfigManager
	{
		public static ConfigEntry<bool> Debug { get; private set; }

		private LocalConfigManager(ConfigFile config)
			: base(config)
		{
			Debug = ConfigManager.configFile.Bind<bool>("General", "Debug", false, "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, ""));
		}

		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-Z]");
			return new string(regex.Replace(level.PlanetName, ""));
		}

		[Obsolete("Use ResolveStringToLevels instead")]
		public static SelectableLevel ResolveStringToLevel(string str)
		{
			return StringToLevel.GetValueOrDefault(str.ToLowerInvariant());
		}

		public static SelectableLevel[] ResolveStringToLevels(string str)
		{
			Plugin.DebugLogger.LogInfo("Resolving " + str + " into SelectableLevels");
			if (stringToLevelsCache.Contains(str))
			{
				return stringToLevelsCache.Get(str);
			}
			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 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 "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);
			SelectableLevel companyLevel = ((IEnumerable<SelectableLevel>)StartOfRound.Instance.levels).FirstOrDefault((Func<SelectableLevel, bool>)((SelectableLevel level) => GetNumberlessName(level).ToLowerInvariant() == Defaults.CompanyLevel.ToLowerInvariant()));
			return (placeholderType switch
			{
				PlaceholderStringType.All => StartOfRound.Instance.levels.Where((SelectableLevel level) => (Object)(object)level != (Object)(object)companyLevel).ToArray(), 
				PlaceholderStringType.Company => (IEnumerable<SelectableLevel>)(object)new SelectableLevel[1] { companyLevel }, 
				PlaceholderStringType.Vanilla => (from level in StartOfRound.Instance.levels
					where (Object)(object)level != (Object)(object)companyLevel
					where Defaults.IsVanillaLevel(level)
					select level).ToArray(), 
				PlaceholderStringType.Modded => (from level in StartOfRound.Instance.levels
					where (Object)(object)level != (Object)(object)companyLevel
					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 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;
					}
					throw new InvalidOperationException("Sum cannot be 0 or negative");
				}
				return num;
			}
		}

		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)
				{
					Plugin.DebugLogger.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.2.17";
	}
}
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!");
			}
		}
	}
	[HarmonyPatch(typeof(StartOfRound), "OnDisable")]
	internal class StartOfRoundPatch
	{
		private static void Postfix(StartOfRound __instance)
		{
			EventManager.LobbyDisabled.Invoke(__instance);
		}
	}
	[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.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);
			}
			base.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);
			}
			base.Name = name;
			ContentManager.Buyables.Add(this);
		}
	}
	public class BuyableCar : BuyableThing
	{
		public BuyableVehicle Vehicle;

		public BuyableCar(Terminal terminal, RelatedNodes nodes)
			: base(terminal, nodes)
		{
			Type = PurchaseType.Vehicle;
			Vehicle = ContentManager.Terminal.buyableVehicles[nodes.Node.buyVehicleIndex];
			base.Price = Vehicle.creditsWorth;
			base.Name = Vehicle.vehicleDisplayName;
			ContentManager.Vehicles.Add(this);
		}
	}
	public class BuyableDecoration : BuyableUnlockable
	{
		public UnlockableItem Decoration => Unlockable;

		public bool InRotation => ContentManager.Terminal.ShipDecorSelection.Contains(Nodes.Node);

		public BuyableDecoration(Terminal terminal, RelatedNodes nodes)
			: base(terminal, nodes)
		{
			Type = PurchaseType.Decoration;
			UnlockableItem unlockable = StartOfRound.Instance.unlockablesList.unlockables[Nodes.Node.shipUnlockableID];
			Unlockable = unlockable;
			base.Price = Decoration.shopSelectionNode.itemCost;
			base.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 BuyableItem(Terminal terminal, RelatedNodes nodes)
			: base(terminal, nodes)
		{
			Type = PurchaseType.Item;
			Item = terminal.buyableItemsList[nodes.Node.buyItemIndex];
			base.Price = Item.creditsWorth;
			base.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 string Name { get; set; }

		public 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 UnlockableItem Suit;

		public Material SuitMaterial;

		public bool IsUnlocked
		{
			get
			{
				if (!Suit.hasBeenUnlockedByPlayer)
				{
					return Suit.alreadyUnlocked;
				}
				return true;
			}
		}

		public bool InRotation => ContentManager.Terminal.ShipDecorSelection.Contains(Nodes.Node);

		public BuyableSuit(Terminal terminal, RelatedNodes nodes, UnlockableItem unlockable)
			: base(terminal, nodes)
		{
			Type = PurchaseType.Suit;
			Suit = unlockable;
			SuitMaterial = Suit.suitMaterial;
			base.Price = ((!((Object)(object)Suit.shopSelectionNode == (Object)null)) ? Suit.shopSelectionNode.itemCost : 0);
			base.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;
				}
			}
			base.Price = price;
			base.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 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)
		{
		}
	}
}