Decompiled source of SlipChat v0.1.1

BepInEx/plugins/MoSadie-SlipChat/com.mosadie.slipchat.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using MoCore;
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.slipchat")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Local API for sending in-game announcements.")]
[assembly: AssemblyFileVersion("0.1.1.0")]
[assembly: AssemblyInformationalVersion("0.1.1+1be4c9dd2b56013e207ce32f94d1b677f830f9a9")]
[assembly: AssemblyProduct("SlipChat")]
[assembly: AssemblyTitle("com.mosadie.slipchat")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.1.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 SlipChat
{
	[BepInPlugin("com.mosadie.slipchat", "SlipChat", "0.1.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInProcess("Slipstream_Win.exe")]
	public class Plugin : BaseUnityPlugin, MoPlugin
	{
		private static ConfigEntry<int> port;

		private static ConfigEntry<bool> debugMode;

		private static HttpListener listener = null;

		internal static ManualLogSource Log;

		public static readonly string COMPATIBLE_GAME_VERSION = "4.1579";

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

		private void Awake()
		{
			try
			{
				Log = ((BaseUnityPlugin)this).Logger;
				if (!MoCore.RegisterPlugin((MoPlugin)(object)this))
				{
					Log.LogError((object)"Failed to register plugin with MoCore. Please check the logs for more information.");
					return;
				}
				port = ((BaseUnityPlugin)this).Config.Bind<int>("Server Settings", "Port", 8002, "Port to listen on.");
				debugMode = ((BaseUnityPlugin)this).Config.Bind<bool>("Developer Settings", "Debug Mode", false, "Enable debug mode, preventing the game from actually sending the order.");
				if (!HttpListener.IsSupported)
				{
					Log.LogError((object)"HttpListener is not supported on this platform.");
					listener = null;
					return;
				}
				listener = new HttpListener();
				listener.Prefixes.Add($"http://127.0.0.1:{port.Value}/sendchat/");
				listener.Prefixes.Add($"http://localhost:{port.Value}/sendchat/");
				listener.Start();
				listener.BeginGetContext(HandleRequest, listener);
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin com.mosadie.slipchat is loaded!");
				Application.quitting += ApplicationQuitting;
			}
			catch (PlatformNotSupportedException ex)
			{
				Log.LogError((object)"HttpListener is not supported on this platform.");
				Log.LogError((object)ex.Message);
			}
			catch (Exception ex2)
			{
				Log.LogError((object)"An error occurred while starting the plugin.");
				Log.LogError((object)ex2.Message);
			}
		}

		private void HandleRequest(IAsyncResult result)
		{
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Handling request");
			try
			{
				HttpListener httpListener = (HttpListener)result.AsyncState;
				HttpListenerContext httpListenerContext = httpListener.EndGetContext(result);
				HttpListenerRequest request = httpListenerContext.Request;
				HttpListenerResponse response = httpListenerContext.Response;
				_ = request.RawUrl.Split('?', 2)[0];
				HttpStatusCode statusCode;
				string s;
				if (!canUseAndOnHelm())
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)$"Captain Seat check failed. IsCaptain: {getIsCaptain()} IsFirstMate: {getIsFirstMate()} AndOnHelm: {canUseAndOnHelm()}");
					statusCode = HttpStatusCode.Forbidden;
					s = "You are not the captain/first mate or are not seated on the helm.";
				}
				else
				{
					string text = request.QueryString["message"];
					((BaseUnityPlugin)this).Logger.LogInfo((object)("Pre-parsed Message: " + text));
					if (text != null)
					{
						text = VariableHandler.ParseVariables(text);
						if (!EditableText.IsTextUsable(text))
						{
							((BaseUnityPlugin)this).Logger.LogInfo((object)$"Message is not usable: Null/Whitespace: {string.IsNullOrWhiteSpace(text)}. Null/Empty: {string.IsNullOrEmpty(text)}");
							statusCode = HttpStatusCode.BadRequest;
							s = "Message is not usable.";
						}
						else
						{
							if (!debugMode.Value)
							{
								RequestCatalog.CaptainIssueOrderAll((OrderType)7, text);
								((BaseUnityPlugin)this).Logger.LogInfo((object)("Message sent: " + text));
							}
							else
							{
								((BaseUnityPlugin)this).Logger.LogInfo((object)("Debug mode enabled, message not sent: " + text));
							}
							statusCode = HttpStatusCode.OK;
							s = "Message sent!";
						}
					}
					else
					{
						statusCode = HttpStatusCode.BadRequest;
						s = "No message provided.";
					}
				}
				response.StatusCode = (int)statusCode;
				response.Headers.Add("Access-Control-Allow-Origin", "*");
				byte[] bytes = Encoding.UTF8.GetBytes(s);
				response.ContentLength64 = bytes.Length;
				Stream outputStream = response.OutputStream;
				outputStream.Write(bytes, 0, bytes.Length);
				outputStream.Close();
				VariableHandler.Reset();
				httpListener.BeginGetContext(HandleRequest, httpListener);
			}
			catch (Exception ex)
			{
				Log.LogError((object)"An error occurred while handling the request.");
				Log.LogError((object)ex.Message);
			}
		}

		private static bool getIsCaptain()
		{
			try
			{
				if (Svc.Get<MpSvc>() == null)
				{
					Log.LogError((object)"An error occurred handling self crew. null MpSvc.");
					return false;
				}
				MpCaptainController captains = Svc.Get<MpSvc>().Captains;
				if (captains == null || captains.CaptainClient == null)
				{
					return false;
				}
				return captains.CaptainClient.IsLocal;
			}
			catch (Exception ex)
			{
				Log.LogError((object)("An error occurred while checking if the crewmate is the captain: " + ex.Message));
				return false;
			}
		}

		private static bool getIsFirstMate()
		{
			try
			{
				if (Svc.Get<MpSvc>() == null)
				{
					Log.LogError((object)"An error occurred handling self crew. null MpSvc.");
					return false;
				}
				MpClientController clients = Svc.Get<MpSvc>().Clients;
				if (clients == null || clients.LocalClient == null)
				{
					return false;
				}
				return ((SlipClient)clients.LocalClient).Roles.Has(Roles.FirstMate);
			}
			catch (Exception ex)
			{
				Log.LogError((object)("An error occurred while checking if the crewmate is the first mate: " + ex.Message));
				return false;
			}
		}

		private static bool canUseAndOnHelm()
		{
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			if (!getIsCaptain() && !getIsFirstMate())
			{
				Log.LogInfo((object)"Not captain or first mate.");
				return false;
			}
			try
			{
				MpSvc val = Svc.Get<MpSvc>();
				if (val == null)
				{
					Log.LogError((object)"An error occurred handling helm check. null MpSvc.");
					return false;
				}
				MpClientController clients = val.Clients;
				if (clients == null)
				{
					Log.LogWarning((object)"An error occurred handling helm check. null Clients.");
					return false;
				}
				LocalSlipClient localClient = clients.LocalClient;
				if (clients.LocalClient == null)
				{
					Log.LogWarning((object)"An error occurred handling helm check. null LocalClient.");
					return false;
				}
				List<Crewmate> crew = ((SlipClient)localClient).Crew;
				if (crew == null)
				{
					Log.LogWarning((object)"An error occurred handling helm check. null Crew list.");
					return false;
				}
				for (int i = 0; i < crew.Count; i++)
				{
					Log.LogInfo((object)$"Checking crewmate {i}: {crew[i].Client.Player.DisplayName} {crew[i].CurrentStation.StationType}");
					if ((Object)(object)crew[i] != (Object)null && (Object)(object)crew[1].CurrentStation != (Object)null && ((object)(StationType)(ref crew[i].CurrentStation.StationType)).Equals((object)(StationType)3))
					{
						Log.LogInfo((object)"Found valid crew on helm.");
						return true;
					}
				}
				Log.LogInfo((object)"No valid crew on helm.");
				return false;
			}
			catch (Exception ex)
			{
				Log.LogError((object)("An error occurred while checking if the crewmate is the captain/first mate and seated on the helm: " + ex.Message));
				Log.LogError((object)ex.StackTrace);
				return false;
			}
		}

		private void ApplicationQuitting()
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Stopping server");
			if (listener != null)
			{
				listener.Close();
			}
		}

		public string GetCompatibleGameVersion()
		{
			return COMPATIBLE_GAME_VERSION;
		}

		public string GetVersionCheckUrl()
		{
			return GAME_VERSION_URL;
		}

		public BaseUnityPlugin GetPluginObject()
		{
			return (BaseUnityPlugin)(object)this;
		}
	}
	internal class VariableHandler
	{
		private static Dictionary<string, string> crewMap = new Dictionary<string, string>();

		internal static string ParseVariables(string message)
		{
			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_04cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0503: Unknown result type (might be due to invalid IL or missing references)
			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 = "0.1.1";
					break;
				case "captain":
					text2 = 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.Count == 0)
			{
				return "";
			}
			Random random = new Random();
			Crewmate val = dictionary[random.Next(dictionary.Count)];
			crewMap.Add(id, val.Client.Player.DisplayName);
			return val.Client.Player.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.slipchat";

		public const string PLUGIN_NAME = "SlipChat";

		public const string PLUGIN_VERSION = "0.1.1";
	}
}