Decompiled source of MoCore v2.0.2

BepInEx/plugins/MoSadie-MoCore/com.mosadie.mocore.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Net.Http;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using RegionVo;
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: AssemblyCompany("com.mosadie.mocore")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("2.0.2.0")]
[assembly: AssemblyInformationalVersion("2.0.2-alpha.0.2+314e20e4147fb7d8362afa510f7f4810735ad2e0")]
[assembly: AssemblyProduct("MoCore")]
[assembly: AssemblyTitle("com.mosadie.mocore")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.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 MoCore
{
	internal class HTTPServerThread
	{
		private HttpListener httpListener;

		private Thread thread;

		internal HTTPServerThread(int port)
		{
			httpListener = new HttpListener();
			httpListener.Prefixes.Add($"http://+:{port}/");
		}

		internal void StartListening()
		{
			try
			{
				if (thread != null)
				{
					MoCore.Log.LogError((object)"HTTP server thread is already running.");
					return;
				}
				thread = new Thread((ThreadStart)delegate
				{
					StartThread(httpListener);
				});
				thread.Start();
			}
			catch (Exception ex)
			{
				MoCore.Log.LogError((object)("Failed to start HTTP server thread: " + ex.Message));
			}
		}

		internal void StopListening()
		{
			try
			{
				if (httpListener == null || thread == null)
				{
					MoCore.Log.LogError((object)"HTTP server thread is not running.");
				}
				else
				{
					httpListener.Stop();
				}
			}
			catch (Exception ex)
			{
				MoCore.Log.LogError((object)("Failed to stop HTTP server thread: " + ex.Message));
			}
		}

		private void StartThread(HttpListener httpListener)
		{
			try
			{
				httpListener.Start();
				MoCore.Log.LogInfo((object)"HTTP server started.");
				while (httpListener.IsListening)
				{
					HttpListenerContext context = httpListener.GetContext();
					HttpListenerRequest request = context.Request;
					HttpListenerResponse httpListenerResponse = context.Response;
					string text = request.Url.AbsolutePath.Trim('/');
					string text2 = text.Split('/')[0];
					MoCore.Log.LogInfo((object)("HTTP request received: Prefix:" + text2 + " " + text));
					Dictionary<string, IMoHttpHandler> httpHandlers = MoCore.GetHttpHandlers();
					if (httpHandlers.ContainsKey(text2))
					{
						IMoHttpHandler moHttpHandler = httpHandlers[text2];
						MoCore.Log.LogInfo((object)("HTTP request handled by " + moHttpHandler.GetPrefix()));
						httpListenerResponse = moHttpHandler.HandleRequest(request, httpListenerResponse);
					}
					else
					{
						MoCore.Log.LogDebug((object)"HTTP request not handled");
						httpListenerResponse.StatusCode = 404;
						byte[] bytes = Encoding.UTF8.GetBytes("Not Found");
						httpListenerResponse.ContentLength64 = bytes.Length;
						httpListenerResponse.OutputStream.Write(bytes, 0, bytes.Length);
					}
					httpListenerResponse?.Close();
				}
			}
			catch (Exception ex)
			{
				MoCore.Log.LogError((object)("HTTP server error: " + ex.Message));
			}
		}
	}
	public interface IMoHttpHandler
	{
		string GetPrefix();

		HttpListenerResponse HandleRequest(HttpListenerRequest request, HttpListenerResponse response);
	}
	public interface IMoPlugin
	{
		string GetCompatibleGameVersion();

		string GetVersionCheckUrl();

		IMoHttpHandler GetHttpHandler();

		BaseUnityPlugin GetPluginObject();
	}
	[BepInPlugin("com.mosadie.mocore", "MoCore", "2.0.2")]
	[BepInProcess("Slipstream_Win.exe")]
	public class MoCore : BaseUnityPlugin, IMoPlugin
	{
		private static ConfigEntry<bool> overrideVersionCheck;

		private static ConfigEntry<int> httpServerPort;

		private static HttpClient httpClient = new HttpClient();

		private static List<IMoPlugin> plugins = new List<IMoPlugin>();

		private static Dictionary<string, IMoHttpHandler> httpHandlers = new Dictionary<string, IMoHttpHandler>();

		private static HTTPServerThread httpServerThread = null;

		internal static ManualLogSource Log;

		public static readonly string COMPATIBLE_GAME_VERSION = "4.1595";

		public static readonly string GAME_VERSION_URL = "https://raw.githubusercontent.com/MoSadie/MoCore/refs/heads/main/versions.json";

		private MoCoreHttpHandler moCoreHttpHandler;

		public static bool IsSafe { get; private set; } = false;


		private void Awake()
		{
			try
			{
				Log = ((BaseUnityPlugin)this).Logger;
				Log.LogInfo((object)("Game version: " + Application.version));
				overrideVersionCheck = ((BaseUnityPlugin)this).Config.Bind<bool>("BE CAREFUL", "Override Version Check", false, "This will allow my plugins to run on any version of Slipstream, skipping the version checker. Use at your own risk.");
				httpServerPort = ((BaseUnityPlugin)this).Config.Bind<int>("HTTP", "HTTP Server Port", 8001, "The port to use for the HTTP server. This is used for any web requests plugins wish to accept.");
				httpClient.Timeout = TimeSpan.FromSeconds(5.0);
				httpServerThread = new HTTPServerThread(httpServerPort.Value);
				httpServerThread.StartListening();
				moCoreHttpHandler = new MoCoreHttpHandler(this);
				Application.quitting += ApplicationQuitting;
				IsSafe = RegisterPlugin(this);
				Log.LogInfo((object)"Plugin com.mosadie.mocore is loaded!");
			}
			catch (Exception ex)
			{
				Log.LogError((object)("An error occurred during plugin startup: " + ex.Message));
			}
		}

		private void ApplicationQuitting()
		{
			if (httpServerThread != null)
			{
				Log.LogInfo((object)"Application is quitting. Stopping HTTP server thread.");
				httpServerThread.StopListening();
				httpServerThread = null;
			}
		}

		public static bool RegisterPlugin(IMoPlugin plugin)
		{
			if (plugin == null)
			{
				Log.LogError((object)"Attempted to register a null plugin!!!");
				Log.LogError((object)("Stacktrace: " + Environment.StackTrace));
				return false;
			}
			if (IsRegisteredPlugin(plugin))
			{
				Log.LogError((object)("Plugin " + PluginName(plugin) + " (" + PluginId(plugin) + ") is already registered. Skipping."));
				return false;
			}
			Log.LogInfo((object)("Registering plugin " + PluginName(plugin) + " (" + PluginId(plugin) + ")"));
			Log.LogInfo((object)("Version: " + PluginVersion(plugin)));
			if (overrideVersionCheck.Value)
			{
				Log.LogWarning((object)"Version check override is enabled. Skipping version check.");
				plugins.Add(plugin);
				return RegisterHttpHandler(plugin);
			}
			if (plugin.GetVersionCheckUrl() != null)
			{
				if (!VersionCheck(plugin, Application.version))
				{
					return false;
				}
				Log.LogInfo((object)("Plugin " + PluginName(plugin) + " (" + PluginId(plugin) + ") is compatible with this version of the game (" + Application.version + ")."));
			}
			else if (plugin.GetCompatibleGameVersion() != null)
			{
				if (!plugin.GetCompatibleGameVersion().Equals(Application.version))
				{
					Log.LogError((object)("Plugin " + PluginName(plugin) + " (" + PluginId(plugin) + ") is not compatible with this (" + Application.version + " version of the game. (Expected version: " + plugin.GetCompatibleGameVersion() + ")"));
					return false;
				}
			}
			else
			{
				Log.LogInfo((object)("Plugin " + PluginName(plugin) + " (" + PluginId(plugin) + ") did not provide a version check URL or compatible game version. Skipping version check."));
			}
			plugins.Add(plugin);
			return RegisterHttpHandler(plugin);
		}

		private static bool RegisterHttpHandler(IMoPlugin plugin)
		{
			if (plugin == null)
			{
				Log.LogError((object)"Attempted to RegisterHttpHandler with a null plugin!!!");
				return false;
			}
			IMoHttpHandler httpHandler = plugin.GetHttpHandler();
			if (httpHandler == null)
			{
				Log.LogDebug((object)("HttpHandler is null for plugin " + PluginName(plugin) + " (" + PluginId(plugin) + "). Skipping (this is normal, null means does not need feature)"));
				return true;
			}
			Log.LogInfo((object)("Attempting to register http handler " + httpHandler.GetPrefix() + " for plugin " + PluginName(plugin) + " (" + PluginId(plugin) + ")"));
			if (httpHandler.GetPrefix() == null)
			{
				Log.LogError((object)"HttpHandler prefix is null. Skipping");
				return false;
			}
			if (httpHandler.GetPrefix().Length == 0)
			{
				Log.LogError((object)"HttpHandler prefix is empty. Skipping");
				return false;
			}
			if (httpHandler.GetPrefix().Contains(" "))
			{
				Log.LogError((object)"HttpHandler prefix contains spaces. Skipping");
				return false;
			}
			if (httpHandler.GetPrefix().Contains("/"))
			{
				Log.LogError((object)"HttpHandler prefix contains slashes. Skipping");
				return false;
			}
			if (httpHandlers.ContainsKey(httpHandler.GetPrefix()))
			{
				Log.LogError((object)("HttpHandler prefix " + httpHandler.GetPrefix() + " is already registered. Skipping"));
				return false;
			}
			Log.LogInfo((object)("Registering http handler " + httpHandler.GetPrefix() + " for plugin " + PluginName(plugin) + " (" + PluginId(plugin) + ")"));
			httpHandlers.Add(httpHandler.GetPrefix(), httpHandler);
			return true;
		}

		public static bool IsRegisteredPlugin(IMoPlugin plugin)
		{
			return plugins.Contains(plugin);
		}

		public static List<IMoPlugin> GetPlugins()
		{
			return new List<IMoPlugin>(plugins);
		}

		internal static Dictionary<string, IMoHttpHandler> GetHttpHandlers()
		{
			return httpHandlers;
		}

		private static bool VersionCheck(IMoPlugin plugin, string gameVersion)
		{
			try
			{
				Dictionary<string, HashSet<string>> dictionary = JsonConvert.DeserializeObject<Dictionary<string, HashSet<string>>>(httpClient.GetStringAsync(plugin.GetVersionCheckUrl()).GetAwaiter().GetResult());
				if (dictionary.ContainsKey(PluginVersion(plugin)) && dictionary[PluginVersion(plugin)].Contains(Application.version))
				{
					return true;
				}
				if (dictionary.ContainsKey(PluginVersion(plugin)))
				{
					Log.LogError((object)("Version " + PluginVersion(plugin) + " of " + PluginName(plugin) + " (" + PluginId(plugin) + ") is not compatible with this version of the game (" + Application.version + "). Please check for updates."));
					return false;
				}
				Log.LogError((object)("Version " + PluginVersion(plugin) + " of " + PluginName(plugin) + " (" + PluginId(plugin) + ") is not listed in the version check file. Please contact the plugin's creator."));
				return false;
			}
			catch (TaskCanceledException)
			{
				Log.LogError((object)"Version check timed out. Falling back to hardcoded version check.");
				return plugin.GetCompatibleGameVersion().Equals(gameVersion);
			}
			catch (Exception ex2)
			{
				Log.LogError((object)("An error occurred during remote version check, falling back to hardcoded version check: " + ex2.Message));
				return plugin.GetCompatibleGameVersion().Equals(gameVersion);
			}
		}

		private static string PluginName(IMoPlugin plugin)
		{
			return plugin.GetPluginObject().Info.Metadata.Name;
		}

		private static string PluginId(IMoPlugin plugin)
		{
			return plugin.GetPluginObject().Info.Metadata.GUID;
		}

		private static string PluginVersion(IMoPlugin plugin)
		{
			return plugin.GetPluginObject().Info.Metadata.Version.ToString();
		}

		public string GetCompatibleGameVersion()
		{
			return COMPATIBLE_GAME_VERSION;
		}

		public string GetVersionCheckUrl()
		{
			return GAME_VERSION_URL;
		}

		public BaseUnityPlugin GetPluginObject()
		{
			return (BaseUnityPlugin)(object)this;
		}

		public IMoHttpHandler GetHttpHandler()
		{
			return moCoreHttpHandler;
		}
	}
	internal class MoCoreHttpHandler : IMoHttpHandler
	{
		private class JsonPluginInfo
		{
			public string Name { get; set; }

			public string Version { get; set; }

			public string GUID { get; set; }

			public string VersionCheckUrl { get; set; }

			public string FallbackGameVersion { get; set; }

			internal JsonPluginInfo(IMoPlugin plugin)
			{
				Name = plugin.GetPluginObject().Info.Metadata.Name;
				Version = plugin.GetPluginObject().Info.Metadata.Version.ToString();
				GUID = plugin.GetPluginObject().Info.Metadata.GUID;
				VersionCheckUrl = plugin.GetVersionCheckUrl();
				FallbackGameVersion = plugin.GetCompatibleGameVersion();
			}
		}

		private readonly MoCore moCore;

		public MoCoreHttpHandler(MoCore moCore)
		{
			this.moCore = moCore;
		}

		public string GetPrefix()
		{
			return "mocore";
		}

		public HttpListenerResponse HandleRequest(HttpListenerRequest request, HttpListenerResponse response)
		{
			string[] array = request.Url.AbsolutePath.Trim('/').Split('/');
			if (array.Length < 2 || array[0] != "mocore")
			{
				response.StatusCode = 404;
				return response;
			}
			if (array[1] == "version")
			{
				response.StatusCode = 200;
				response.Headers.Add("Access-Control-Allow-Origin", "*");
				byte[] bytes = Encoding.UTF8.GetBytes(moCore.GetPluginObject().Info.Metadata.Version.ToString());
				response.ContentLength64 = bytes.Length;
				response.OutputStream.Write(bytes, 0, bytes.Length);
				response.Close();
				return response;
			}
			if (array[1] == "plugins")
			{
				List<JsonPluginInfo> list = new List<JsonPluginInfo>();
				foreach (IMoPlugin plugin in MoCore.GetPlugins())
				{
					list.Add(new JsonPluginInfo(plugin));
				}
				string s = JsonConvert.SerializeObject((object)list, (Formatting)1);
				response.StatusCode = 200;
				response.Headers.Add("Access-Control-Allow-Origin", "*");
				response.ContentType = "application/json";
				byte[] bytes2 = Encoding.UTF8.GetBytes(s);
				response.ContentLength64 = bytes2.Length;
				response.OutputStream.Write(bytes2, 0, bytes2.Length);
				return response;
			}
			if (array[1] == "plugin" && array.Length > 2)
			{
				IMoPlugin moPlugin = null;
				foreach (IMoPlugin plugin2 in MoCore.GetPlugins())
				{
					if (plugin2.GetPluginObject().Info.Metadata.GUID == array[2])
					{
						moPlugin = plugin2;
						break;
					}
				}
				if (moPlugin != null)
				{
					string s2 = JsonConvert.SerializeObject((object)new JsonPluginInfo(moPlugin), (Formatting)1);
					response.StatusCode = 200;
					response.Headers.Add("Access-Control-Allow-Origin", "*");
					response.ContentType = "application/json";
					byte[] bytes3 = Encoding.UTF8.GetBytes(s2);
					response.ContentLength64 = bytes3.Length;
					response.OutputStream.Write(bytes3, 0, bytes3.Length);
				}
				else
				{
					response.StatusCode = 404;
				}
			}
			else if (array[1] == "variable" && array.Length > 2 && array[2] == "parse")
			{
				if (!MoCore.IsSafe)
				{
					response.StatusCode = 503;
					response.Headers.Add("Access-Control-Allow-Origin", "*");
					return response;
				}
				string text = request.QueryString["string"];
				if (text != null)
				{
					string text2 = VariableHandler.ParseVariables(text);
					if (text2 == null)
					{
						response.StatusCode = 500;
						response.Headers.Add("Access-Control-Allow-Origin", "*");
						return response;
					}
					response.StatusCode = 200;
					response.Headers.Add("Access-Control-Allow-Origin", "*");
					byte[] bytes4 = Encoding.UTF8.GetBytes(text2);
					response.ContentLength64 = bytes4.Length;
					response.OutputStream.Write(bytes4, 0, bytes4.Length);
				}
				else
				{
					response.StatusCode = 400;
				}
			}
			else
			{
				response.StatusCode = 404;
			}
			return response;
		}
	}
	public class VariableHandler
	{
		private static Dictionary<string, string> crewMap = new Dictionary<string, string>();

		public static string ParseVariables(string message)
		{
			if (!MoCore.IsSafe)
			{
				return null;
			}
			string[] array = message.Split(' ');
			string text = "";
			string[] array2 = array;
			foreach (string text2 in array2)
			{
				if (text2.StartsWith("$"))
				{
					string variableValue = GetVariableValue(text2.Substring(1));
					text = ((variableValue != null) ? (text + variableValue + " ") : (text + text2 + " "));
				}
				else
				{
					text = text + text2 + " ";
				}
			}
			return text.Trim();
		}

		internal static string GetVariableValue(string variable)
		{
			//IL_052f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0534: Unknown result type (might be due to invalid IL or missing references)
			//IL_0560: Unknown result type (might be due to invalid IL or missing references)
			//IL_0565: Unknown result type (might be due to invalid IL or missing references)
			if (!MoCore.IsSafe)
			{
				return null;
			}
			string text = "";
			while (variable.Length > 0 && !char.IsLetterOrDigit(variable[variable.Length - 1]))
			{
				text = variable[variable.Length - 1] + text;
				variable = variable.Substring(0, variable.Length - 1);
			}
			string text2 = "";
			if (variable.StartsWith("randomCrew"))
			{
				text2 = GetRandomCrewMember(variable.Substring(10, variable.Length - 11));
			}
			else if (variable.StartsWith("crew"))
			{
				text2 = GetCrewMember(variable.Substring(5, variable.Length - 6));
			}
			else
			{
				switch (variable)
				{
				case "version":
					text2 = "2.0.2";
					break;
				case "captain":
					text2 = ((Svc.Get<MpSvc>().Captains != null && Svc.Get<MpSvc>().Captains.CaptainClient != null && Svc.Get<MpSvc>().Captains.CaptainClient.Player != null && Svc.Get<MpSvc>().Captains.CaptainClient.Player.DisplayName != null) ? Svc.Get<MpSvc>().Captains.CaptainClient.Player.DisplayName : "");
					break;
				case "enemyName":
				{
					MpScenarioController scenarios5 = Svc.Get<MpSvc>().Scenarios;
					text2 = ((scenarios5 != null && scenarios5.CurrentScenario != null && scenarios5.CurrentScenario.Battle != null && scenarios5.CurrentScenario.Battle.Metadata.EnemyName != null) ? scenarios5.CurrentScenario.Battle.Metadata.EnemyName : "");
					break;
				}
				case "enemyIntel":
				{
					MpScenarioController scenarios2 = Svc.Get<MpSvc>().Scenarios;
					text2 = ((scenarios2 != null && scenarios2.CurrentScenario != null && scenarios2.CurrentScenario.Battle != null && scenarios2.CurrentScenario.Battle.Metadata.IntelDescription != null) ? scenarios2.CurrentScenario.Battle.Metadata.IntelDescription : "");
					break;
				}
				case "enemyInvader":
				case "enemyInvaders":
				{
					MpScenarioController scenarios6 = Svc.Get<MpSvc>().Scenarios;
					text2 = ((scenarios6 != null && scenarios6.CurrentScenario != null && scenarios6.CurrentScenario.Battle != null && scenarios6.CurrentScenario.Battle.Metadata.InvaderDescription != null) ? scenarios6.CurrentScenario.Battle.Metadata.InvaderDescription : "");
					break;
				}
				case "enemyThreat":
				{
					MpScenarioController scenarios3 = Svc.Get<MpSvc>().Scenarios;
					text2 = ((scenarios3 != null && scenarios3.CurrentScenario != null && scenarios3.CurrentScenario.Battle != null) ? scenarios3.CurrentScenario.Battle.Metadata.ThreatLevel.ToString() : "");
					break;
				}
				case "enemySpeed":
				{
					MpScenarioController scenarios = Svc.Get<MpSvc>().Scenarios;
					text2 = ((scenarios != null && scenarios.CurrentScenario != null && scenarios.CurrentScenario.Battle != null) ? scenarios.CurrentScenario.Battle.Metadata.SpeedLevel.ToString() : "");
					break;
				}
				case "enemyCargo":
				{
					MpScenarioController scenarios4 = Svc.Get<MpSvc>().Scenarios;
					text2 = ((scenarios4 != null && scenarios4.CurrentScenario != null && scenarios4.CurrentScenario.Battle != null) ? scenarios4.CurrentScenario.Battle.Metadata.CargoLevel.ToString() : "");
					break;
				}
				case "campaignName":
				{
					MpCampaignController campaigns2 = Svc.Get<MpSvc>().Campaigns;
					if (campaigns2 != null && campaigns2.CurrentCampaign != null && campaigns2.CurrentCampaign.CaptainCampaign != null && campaigns2.CurrentCampaign.CaptainCampaign.CampaignVo != null)
					{
						RegionMetadataVo metadata = ((Root)(ref campaigns2.CurrentCampaign.CaptainCampaign.CampaignVo.RegionVo)).Metadata;
						if (((RegionMetadataVo)(ref metadata)).Name != null)
						{
							metadata = ((Root)(ref campaigns2.CurrentCampaign.CaptainCampaign.CampaignVo.RegionVo)).Metadata;
							text2 = ((RegionMetadataVo)(ref metadata)).Name;
							break;
						}
					}
					text2 = "";
					break;
				}
				case "sectorName":
				{
					MpCampaignController campaigns = Svc.Get<MpSvc>().Campaigns;
					text2 = ((campaigns != null && campaigns.CurrentCampaign != null && campaigns.CurrentCampaign.CaptainCampaign != null && campaigns.CurrentCampaign.CaptainCampaign.CampaignVo != null && campaigns.CurrentCampaign.CaptainCampaign.CampaignVo.CurrentSectorVo != null && ((SectorDefVo)(ref campaigns.CurrentCampaign.CaptainCampaign.CampaignVo.CurrentSectorVo.Definition)).Name != null) ? ((SectorDefVo)(ref campaigns.CurrentCampaign.CaptainCampaign.CampaignVo.CurrentSectorVo.Definition)).Name : "");
					break;
				}
				default:
					text2 = "";
					break;
				}
			}
			return text2 + text;
		}

		internal static string GetRandomCrewMember(string id)
		{
			if (crewMap.ContainsKey(id))
			{
				return crewMap[id];
			}
			Dictionary<int, Crewmate> dictionary = Svc.Get<MpSvc>().Crew.CrewMap;
			if (dictionary == null || dictionary.Count == 0)
			{
				return "";
			}
			int num = new Random().Next(0, dictionary.Count);
			int num2 = 0;
			Crewmate val = null;
			foreach (KeyValuePair<int, Crewmate> item in dictionary)
			{
				val = item.Value;
				if (num2 == num)
				{
					break;
				}
				num2++;
			}
			string displayName = val.Client.Player.DisplayName;
			crewMap.Add(id, displayName);
			return displayName;
		}

		internal static string GetCrewMember(string id)
		{
			Dictionary<int, Crewmate> dictionary = Svc.Get<MpSvc>().Crew.CrewMap;
			if (dictionary.Count == 0)
			{
				return "";
			}
			int result = 0;
			if (!int.TryParse(id, out result))
			{
				return "";
			}
			if (!dictionary.ContainsKey(result))
			{
				return "";
			}
			return dictionary[result].Client.Player.DisplayName;
		}

		internal static void Reset()
		{
			crewMap.Clear();
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "com.mosadie.mocore";

		public const string PLUGIN_NAME = "MoCore";

		public const string PLUGIN_VERSION = "2.0.2";
	}
}