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.");
}
}
}