Decompiled source of Straftat Stream Safety v1.0.0

BepInEx/plugins/StraftatStreamSafety/StrafStreamSafety.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Configuration;
using Goodgulf.Graphics;
using HarmonyLib;
using HeathenEngineering.SteamworksIntegration.UI;
using Microsoft.CodeAnalysis;
using StrafStreamSafety.Config;
using TMPro;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("StrafStreamSafety")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+fa9bb2816b96cc38462026a386ac1cef7feaab8d")]
[assembly: AssemblyProduct("StrafStreamSafety")]
[assembly: AssemblyTitle("StrafStreamSafety")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
public class ProxyChatWriter
{
	private Process proxyProcess;

	private string filePath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "pipe.exe");

	private StreamWriter proxyInputWriter;

	private readonly SemaphoreSlim _writeSemaphore = new SemaphoreSlim(1, 1);

	public async Task LaunchProxyChat()
	{
		try
		{
			proxyProcess = new Process();
			proxyProcess.StartInfo.FileName = filePath;
			proxyProcess.StartInfo.RedirectStandardInput = true;
			proxyProcess.StartInfo.RedirectStandardOutput = true;
			proxyProcess.StartInfo.UseShellExecute = false;
			proxyProcess.StartInfo.CreateNoWindow = true;
			proxyProcess.Start();
			proxyInputWriter = proxyProcess.StandardInput;
			await WriteToProxy("Proxy Chat Initialized. Move this to your second monitor.");
		}
		catch (Exception ex2)
		{
			Exception ex = ex2;
			Debug.LogException(ex);
		}
	}

	public async Task WriteToProxy(string message)
	{
		await _writeSemaphore.WaitAsync();
		try
		{
			if (proxyInputWriter != null && proxyInputWriter.BaseStream.CanWrite)
			{
				await proxyInputWriter.WriteLineAsync(message);
				await proxyInputWriter.FlushAsync();
			}
		}
		catch (Exception ex2)
		{
			Exception ex = ex2;
			Debug.LogError((object)("Failed to write to proxy: " + ex.Message));
		}
		finally
		{
			_writeSemaphore.Release();
		}
	}
}
namespace StrafStreamSafety
{
	[BepInPlugin("malco.StrafStreamSafety", "StrafStreamSafety", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		private readonly Harmony harmony = new Harmony("malco.StrafStreamSafety");

		private Process consoleProcess;

		public static Plugin instance;

		public ProxyChatWriter proxyChatWriter;

		public PluginConfig cfg;

		public List<string> badWords = new List<string>();

		private void Awake()
		{
			instance = this;
			cfg = new PluginConfig(((BaseUnityPlugin)this).Config);
			cfg.InitBindings();
			proxyChatWriter = new ProxyChatWriter();
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			string path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "badWords");
			if (File.Exists(path))
			{
				badWords.AddRange(File.ReadAllLines(path));
			}
			else
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"badWords file not found!");
			}
			harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Patched StrafStreamSafety");
		}

		public string CensorBadWords(string input)
		{
			foreach (string badWord in badWords)
			{
				input = Regex.Replace(input, Regex.Escape(badWord), new string('*', badWord.Length), RegexOptions.IgnoreCase);
			}
			return input;
		}
	}
}
namespace StrafStreamSafety.Patches
{
	[HarmonyPatch(typeof(FriendInviteDropDown))]
	internal class FriendInviteDropdownPatcher
	{
		[HarmonyPostfix]
		[HarmonyPatch("Start")]
		private static void Start(FriendInviteDropDown __instance)
		{
			bool active = !Plugin.instance.cfg.PRIVACY;
			((Component)((Component)__instance).transform.GetChild(0)).gameObject.SetActive(active);
			((Component)((Component)__instance).transform.GetChild(2)).gameObject.SetActive(active);
			((Component)((Component)__instance).transform.GetChild(3)).gameObject.SetActive(active);
			if (Plugin.instance.cfg.USE_PROXY)
			{
				((Component)((Component)__instance).transform.parent.GetChild(1)).gameObject.SetActive(false);
			}
		}
	}
	[HarmonyPatch(typeof(FriendList))]
	internal class FriendsListPatcher
	{
		[HarmonyPostfix]
		[HarmonyPatch("Start")]
		private static void Start(FriendList __instance)
		{
			((Component)__instance).gameObject.SetActive(!Plugin.instance.cfg.PRIVACY);
		}
	}
	[HarmonyPatch(typeof(MatchChatLine))]
	internal class MatchChatPatcher
	{
		[HarmonyPrefix]
		[HarmonyPatch("StartDuration")]
		private static void CensorChat(MatchChatLine __instance)
		{
			((Component)((Component)__instance).transform.GetChild(0)).gameObject.SetActive(!Plugin.instance.cfg.REMOVE_ICONS);
			Type type = ((object)__instance).GetType();
			FieldInfo field = type.GetField("nameLine", BindingFlags.Instance | BindingFlags.NonPublic);
			if (field != null)
			{
				object? value = field.GetValue(__instance);
				TMP_Text val = (TMP_Text)((value is TMP_Text) ? value : null);
				if ((Object)(object)val != (Object)null)
				{
					if (Plugin.instance.cfg.CENSOR)
					{
						val.text = Plugin.instance.CensorBadWords(val.text);
					}
					if (Plugin.instance.cfg.USE_PROXY)
					{
						Plugin.instance.proxyChatWriter.WriteToProxy(val.text + " said:");
						val.text = "Name";
					}
				}
			}
			FieldInfo field2 = type.GetField("matchLine", BindingFlags.Instance | BindingFlags.NonPublic);
			if (!(field2 != null))
			{
				return;
			}
			object? value2 = field2.GetValue(__instance);
			TMP_Text val2 = (TMP_Text)((value2 is TMP_Text) ? value2 : null);
			if ((Object)(object)val2 != (Object)null)
			{
				if (Plugin.instance.cfg.CENSOR)
				{
					val2.text = Plugin.instance.CensorBadWords(val2.text);
				}
				if (Plugin.instance.cfg.USE_PROXY)
				{
					Plugin.instance.proxyChatWriter.WriteToProxy("\t" + val2.text);
					val2.text = "Said something in chat.";
				}
			}
		}
	}
	[HarmonyPatch(typeof(MenuController))]
	internal class MenuControllerPatcher
	{
		[HarmonyPostfix]
		[HarmonyPatch("Start")]
		private static void Start(MenuController __instance)
		{
			((Component)((Component)__instance).transform.GetChild(2).GetChild(9).GetChild(2)).gameObject.SetActive(!Plugin.instance.cfg.PRIVACY);
		}
	}
	[HarmonyPatch(typeof(PauseManager))]
	internal class PauseManagerPatcher
	{
		[HarmonyPostfix]
		[HarmonyPatch("Awake")]
		private static void DisableChat(PauseManager __instance)
		{
			if (Plugin.instance.cfg.DISABLE_CHAT)
			{
				Type typeFromHandle = typeof(PauseManager);
				FieldInfo field = typeFromHandle.GetField("ChatBox", BindingFlags.Instance | BindingFlags.NonPublic);
				if (field != null)
				{
					object? value = field.GetValue(__instance);
					GameObject val = (GameObject)((value is GameObject) ? value : null);
					((Component)val.transform.parent.GetChild(0)).gameObject.SetActive(false);
				}
			}
		}
	}
	[HarmonyPatch(typeof(PlayerListItem))]
	internal class PlayerListItemPatcher
	{
		[HarmonyPostfix]
		[HarmonyPatch("SetPlayerValues")]
		private static void SetValues(PlayerListItem __instance)
		{
			TMP_Text component = ((Component)((Component)__instance).transform.GetChild(1)).GetComponent<TMP_Text>();
			if (Plugin.instance.cfg.CENSOR)
			{
				component.text = Plugin.instance.CensorBadWords(component.text);
			}
			if (Plugin.instance.cfg.USE_PROXY)
			{
				component.text = "Name";
			}
			if (Plugin.instance.cfg.REMOVE_ICONS)
			{
				((Component)((Component)__instance).transform.GetChild(0)).gameObject.SetActive(false);
			}
		}
	}
	[HarmonyPatch(typeof(Settings))]
	internal class SettingsPatcher
	{
		[HarmonyPrefix]
		[HarmonyPatch("Start")]
		private static void Start()
		{
			if (Plugin.instance.cfg.USE_PROXY && !Plugin.instance.cfg.DISABLE_CHAT)
			{
				Plugin.instance.proxyChatWriter.LaunchProxyChat();
			}
		}
	}
}
namespace StrafStreamSafety.Config
{
	public class PluginConfig
	{
		private readonly ConfigFile configFile;

		public bool USE_PROXY { get; set; }

		public bool DISABLE_CHAT { get; set; }

		public bool CENSOR { get; set; }

		public bool REMOVE_ICONS { get; set; }

		public bool PRIVACY { get; set; }

		public PluginConfig(ConfigFile cfg)
		{
			configFile = cfg;
		}

		private T ConfigEntry<T>(string section, string key, T defaultVal, string description)
		{
			return configFile.Bind<T>(section, key, defaultVal, description).Value;
		}

		public void InitBindings()
		{
			USE_PROXY = ConfigEntry("Use Chat Proxy", "Chat", defaultVal: false, "If true, chat will be redirected to an external application.");
			DISABLE_CHAT = ConfigEntry("Fully Disable Chat", "Chat", defaultVal: false, "If true, the ingame chat will not display anything at all.");
			REMOVE_ICONS = ConfigEntry("Remove Foreign Icons", "Chat", defaultVal: false, "If true, player avatar icons will be hidden.");
			CENSOR = ConfigEntry("Censor Content", "Chat", defaultVal: true, "If true, Names and chat messages will attempt to be censored and replaced with '*'s.");
			PRIVACY = ConfigEntry("Privacy Mode", "Chat", defaultVal: true, "If true, disables the friends list and friend drop down preventing information including your friend code ID from being shared.");
		}
	}
}