Decompiled source of LethalChat v1.1.0

LethalWorkingConditions.dll

Decompiled 2 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using LethalLib.Modules;
using LethalWorkingConditions.Classes.ChatCommand;
using LethalWorkingConditions.Classes.ChatCommand.Commands;
using LethalWorkingConditions.Helpers;
using LethalWorkingConditions.Patches;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.EventSystems;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("LethalWorkingCondition")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("LethalWorkingCondition")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("6efab151-7ff3-4bb1-a345-7f43604d9c10")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace LethalWorkingConditions
{
	public class LWCConfig
	{
		public readonly string Name = "LethalChat";

		public static readonly bool PlayerControllerUnlimitedSprintDefault = false;

		public static ConfigEntry<bool> PlayerControllerUnlimitedSprint;

		public static readonly string TerminalCommandPrefixDefault = "----";

		public static ConfigEntry<string> TerminalCommandPrefix;

		public static readonly bool TerminalCommandDisableChatDefault = false;

		public static ConfigEntry<bool> TerminalCommandDisableChat;

		public static readonly bool AllowSpawnCommandIfNotHostDefault = false;

		public static ConfigEntry<bool> AllowSpawnCommandIfNotHost;

		public static readonly bool MonsterEventsEnabledDefault = false;

		public static ConfigEntry<bool> MonsterEventsEnabled;

		public LWCConfig(ConfigFile cfg)
		{
			AllowSpawnCommandIfNotHost = cfg.Bind<bool>(Name, "AllowSpawnCommandIfNotHost", AllowSpawnCommandIfNotHostDefault, "If enabled, you can use the spawn command even when you are not the host");
		}
	}
	internal class Content
	{
		private static LWCLogger logger = new LWCLogger("Content");

		public static AssetBundle MainAssetsBundle;

		private static readonly string mainAssetBundleName = "lethalworkingconditions";

		public static Dictionary<string, GameObject> Prefabs = new Dictionary<string, GameObject>();

		private static void TryLoadAssets()
		{
			MainAssetsBundle = AssetBundle.LoadFromFile(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), mainAssetBundleName));
			if ((Object)(object)MainAssetsBundle != (Object)null)
			{
				logger.LogInfo("AssetBundle " + mainAssetBundleName + " loaded successfully");
			}
			else
			{
				logger.LogError("Could not load AssetBundle from " + mainAssetBundleName);
			}
		}

		private static void LoadPatches()
		{
			LethalWorkingConditions.harmony.PatchAll(typeof(RoundManagerBPatch));
			LethalWorkingConditions.harmony.PatchAll(typeof(HUDManagerBPatch));
			logger.LogInfo("Done loading patches");
		}

		private static void LoadEnemies()
		{
		}

		private static void LoadEnemy(string name, int rarity, LevelTypes levelType, SpawnType spawnType)
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			logger.LogInfo("Loading enemy " + name);
			EnemyType val = MainAssetsBundle.LoadAsset<EnemyType>(name);
			TerminalNode val2 = MainAssetsBundle.LoadAsset<TerminalNode>(name + "TN");
			TerminalKeyword val3 = MainAssetsBundle.LoadAsset<TerminalKeyword>(name + "TK");
			NetworkPrefabs.RegisterNetworkPrefab(val.enemyPrefab);
			Enemies.RegisterEnemy(val, rarity, levelType, spawnType, val2, val3);
			logger.LogInfo("Loaded " + name);
		}

		public static void Load()
		{
			LethalWorkingConditions.harmony.PatchAll(typeof(LethalWorkingConditions));
			LoadPatches();
			foreach (KeyValuePair<string, GameObject> prefab in Prefabs)
			{
				GameObject value = prefab.Value;
				string key = prefab.Key;
				AudioSource[] componentsInChildren = value.GetComponentsInChildren<AudioSource>();
				if (componentsInChildren.Length != 0)
				{
					AudioSource[] array = componentsInChildren;
					foreach (AudioSource val in array)
					{
						val.volume *= 1f;
					}
				}
			}
			logger.LogInfo("Content loaded");
		}
	}
	[BepInPlugin("Trebossa.LethalChat", "Lethal Chat", "1.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class LethalWorkingConditions : BaseUnityPlugin
	{
		public const string modGUID = "Trebossa.LethalChat";

		public const string modName = "Lethal Chat";

		public const string modVersion = "1.1.0";

		public static readonly Harmony harmony = new Harmony("Trebossa.LethalChat");

		public static LethalWorkingConditions Instance;

		private static LWCLogger logger;

		public static LWCConfig Config { get; internal set; }

		private void Awake()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
			Config = new LWCConfig(((BaseUnityPlugin)this).Config);
			LWCLogger.Init();
			logger = new LWCLogger("LWC");
			Content.Load();
			logger.LogInfo("Done loading config");
			AllowNetworkPrefabs();
		}

		private void AllowNetworkPrefabs()
		{
			Type[] types = Assembly.GetExecutingAssembly().GetTypes();
			Type[] array = types;
			foreach (Type type in array)
			{
				MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic);
				MethodInfo[] array2 = methods;
				foreach (MethodInfo methodInfo in array2)
				{
					object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false);
					if (customAttributes.Length != 0)
					{
						methodInfo.Invoke(null, null);
					}
				}
			}
		}
	}
}
namespace LethalWorkingConditions.Patches
{
	[HarmonyPatch(typeof(HUDManager))]
	internal class HUDManagerBPatch
	{
		private static bool chatDisabled = LWCConfig.TerminalCommandDisableChat.Value;

		[HarmonyPatch("SubmitChat_performed")]
		[HarmonyPrefix]
		private static bool HUDManager_SubmitChat_performed_Prefix(ref HUDManager __instance)
		{
			string text = __instance.chatTextField.text;
			if (!text.ToLower().StartsWith(ChatCommand.CommandPrefix) && !chatDisabled)
			{
				return true;
			}
			CommandStatus commandStatus = HandleCommandLogic(text, ref __instance);
			CleanupGUI(ref __instance);
			if (commandStatus == CommandStatus.NOT_SET && !chatDisabled)
			{
				return true;
			}
			return false;
		}

		private static CommandStatus HandleCommandLogic(string text, ref HUDManager __instance)
		{
			CommandStatus result = CommandStatus.NOT_SET;
			if (text.ToLower().StartsWith(ChatCommand.CommandPrefix + "spawn"))
			{
				SpawnCommand spawnCommand = new SpawnCommand(ref __instance);
				result = spawnCommand.ExecuteCommand();
			}
			return result;
		}

		private static void CleanupGUI(ref HUDManager __instance)
		{
			PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
			localPlayerController.isTypingChat = false;
			__instance.chatTextField.text = "";
			EventSystem.current.SetSelectedGameObject((GameObject)null);
			__instance.PingHUDElement(__instance.Chat, 2f, 1f, 0.2f);
			((Behaviour)__instance.typingIndicator).enabled = false;
		}
	}
	[HarmonyPatch(typeof(RoundManager))]
	internal class RoundManagerBPatch
	{
		internal static bool isHost;

		internal static RoundManager currentRound;

		internal static SelectableLevel currentLevel;

		internal static EnemyVent[] currentLevelVents;

		[HarmonyPatch("Start")]
		[HarmonyPrefix]
		private static void RoundManagerBPatch_Start_Prefix(ref float ___mapSizeMultiplier)
		{
			___mapSizeMultiplier = 2f;
			isHost = ((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost;
		}

		[HarmonyPatch("AdvanceHourAndSpawnNewBatchOfEnemies")]
		[HarmonyPrefix]
		private static void RoundManagerBPatch_AdvanceHourAndSpawnNewBatchOfEnemies_Prefix(ref EnemyVent[] ___allEnemyVents, ref SelectableLevel ___currentLevel)
		{
			currentLevel = ___currentLevel;
			currentLevelVents = ___allEnemyVents;
		}

		[HarmonyPatch("LoadNewLevel")]
		[HarmonyPrefix]
		private static void RoundManagerBPatch_LoadNewLevel_Prefix(ref SelectableLevel newLevel)
		{
			currentRound = RoundManager.Instance;
		}
	}
}
namespace LethalWorkingConditions.Helpers
{
	internal class LWCLogger
	{
		public static ManualLogSource mls;

		public readonly string source;

		public LWCLogger(string source)
		{
			this.source = source;
		}

		public static void Init()
		{
			mls = Logger.CreateLogSource("Trebossa.LethalChat");
		}

		public void LogInfo(string message)
		{
			if (mls != null)
			{
				mls.LogInfo((object)("[" + source + "] " + message));
			}
		}

		public void LogWarning(string message)
		{
			if (mls != null)
			{
				mls.LogWarning((object)("[" + source + "] " + message));
			}
		}

		public void LogError(string message)
		{
			if (mls != null)
			{
				mls.LogError((object)("[" + source + "] " + message));
			}
		}
	}
	internal class ObjectFinder
	{
		public static List<T> FindObjectsInRadius<T>(Transform transform, float radius)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			List<T> list = new List<T>();
			Collider[] array = Physics.OverlapSphere(transform.position, radius);
			Collider[] array2 = array;
			foreach (Collider val in array2)
			{
				T component = ((Component)val).GetComponent<T>();
				if (component != null)
				{
					list.Add(component);
				}
			}
			return list;
		}

		public static T[] FindObjectsOfType<T>() where T : Object
		{
			return Object.FindObjectsOfType<T>();
		}
	}
}
namespace LethalWorkingConditions.Classes
{
	internal enum EnemySpawnLocation
	{
		Auto,
		Inside,
		Outside
	}
	internal class EnemySpawner
	{
		private static LWCLogger logger = new LWCLogger("EnemySpawner");

		public static List<SpawnableEnemyWithRarity> EnemiesInside => RoundManagerBPatch.currentLevel.Enemies;

		public static List<SpawnableEnemyWithRarity> EnemiesOutside => RoundManagerBPatch.currentLevel.OutsideEnemies;

		public static bool SpawnEnemy(SpawnableEnemyWithRarity enemy, int amount, EnemySpawnLocation spawnLocation = EnemySpawnLocation.Auto)
		{
			if (!RoundManagerBPatch.isHost)
			{
				logger.LogInfo("Could not spawn enemies because user is not host");
				return false;
			}
			switch (spawnLocation)
			{
			case EnemySpawnLocation.Auto:
				if (FindEnemy(EnemiesInside, enemy.enemyType.enemyName) != null)
				{
					return SpawnEnemyAtRandomVent(enemy, amount);
				}
				return SpawnEnemyAtRandomOutsidePosition(enemy, amount);
			case EnemySpawnLocation.Inside:
				return SpawnEnemyAtRandomVent(enemy, amount);
			case EnemySpawnLocation.Outside:
				return SpawnEnemyAtRandomOutsidePosition(enemy, amount);
			default:
				return false;
			}
		}

		private static bool SpawnEnemyAtRandomVent(SpawnableEnemyWithRarity enemy, int amount)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				int num = RoundManagerBPatch.currentLevel.Enemies.IndexOf(enemy);
				for (int i = 0; i < amount; i++)
				{
					int num2 = Random.Range(0, RoundManagerBPatch.currentRound.allEnemyVents.Length);
					Vector3 position = RoundManagerBPatch.currentRound.allEnemyVents[num2].floorNode.position;
					float y = RoundManagerBPatch.currentRound.allEnemyVents[i].floorNode.eulerAngles.y;
					RoundManagerBPatch.currentRound.SpawnEnemyOnServer(position, y, RoundManagerBPatch.currentLevel.Enemies.IndexOf(enemy));
				}
			}
			catch (Exception ex)
			{
				logger.LogError("Failed to spawn enemies: " + ex.ToString());
				return false;
			}
			return true;
		}

		private static bool SpawnEnemyAtRandomOutsidePosition(SpawnableEnemyWithRarity enemy, int amount)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				for (int i = 0; i < amount - 1; i++)
				{
					GameObject val = Object.Instantiate<GameObject>(RoundManagerBPatch.currentLevel.OutsideEnemies[RoundManagerBPatch.currentLevel.OutsideEnemies.IndexOf(enemy)].enemyType.enemyPrefab, GameObject.FindGameObjectsWithTag("OutsideAINode")[Random.Range(0, GameObject.FindGameObjectsWithTag("OutsideAINode").Length - 1)].transform.position, Quaternion.Euler(Vector3.zero));
					val.gameObject.GetComponentInChildren<NetworkObject>().Spawn(true);
				}
			}
			catch (Exception ex)
			{
				logger.LogError("Failed to spawn enemies: " + ex.ToString());
				return false;
			}
			return true;
		}

		public static SpawnableEnemyWithRarity FindEnemy(List<SpawnableEnemyWithRarity> list, string search)
		{
			return list.Find((SpawnableEnemyWithRarity e) => e.enemyType.enemyName.ToLower().Contains(search.ToLower()));
		}
	}
}
namespace LethalWorkingConditions.Classes.ChatCommand
{
	public enum CommandStatus
	{
		NOT_SET,
		PREQUISITES_NOT_MET,
		PARAMS_INCOMPLETE,
		OK
	}
	internal abstract class ChatCommand
	{
		protected LWCLogger logger;

		public static string CommandPrefix = LWCConfig.TerminalCommandPrefix.Value ?? LWCConfig.TerminalCommandPrefixDefault;

		protected HUDManager hudManager;

		protected readonly string text;

		protected string[] parameters;

		protected string commandName = "N/A";

		protected string noticeTitle => "Command: " + CommandPrefix + commandName;

		protected virtual string GetFullCommandSyntax()
		{
			return CommandPrefix + commandName;
		}

		protected virtual void OnInterception()
		{
		}

		protected abstract bool CanBeCalled();

		protected abstract bool ParseParameters();

		protected abstract void Execute();

		public ChatCommand(string commandname, ref HUDManager hudManager)
		{
			this.hudManager = hudManager;
			commandName = commandname;
			logger = new LWCLogger(commandName ?? "");
			text = hudManager.chatTextField.text;
			parameters = text.Split(new char[1] { ' ' }).Skip(1).ToArray();
		}

		protected void IssueNotification(string message, bool isWarning = false)
		{
			HUDManager.Instance.DisplayTip(noticeTitle, message, isWarning, false, "LC_Tip1");
			logger.LogInfo(noticeTitle + ": " + message);
		}

		protected void IssueCommandSyntax()
		{
			IssueNotification("Wrong Syntax: " + GetFullCommandSyntax());
		}

		public CommandStatus ExecuteCommand()
		{
			if (!CanBeCalled())
			{
				return CommandStatus.PREQUISITES_NOT_MET;
			}
			if (!ParseParameters())
			{
				IssueCommandSyntax();
				return CommandStatus.PARAMS_INCOMPLETE;
			}
			Execute();
			return CommandStatus.OK;
		}
	}
}
namespace LethalWorkingConditions.Classes.ChatCommand.Commands
{
	internal class SpawnCommand : ChatCommand
	{
		private string targetEnemyNameParam = "";

		private int targetEnemyAmountParam = 1;

		private EnemySpawnLocation spawnLocation = EnemySpawnLocation.Auto;

		private bool targetEnemyFound = false;

		private string targetEnemyName;

		private string creaturesAvailableString => string.Join("|", EnemySpawner.EnemiesInside.Select((SpawnableEnemyWithRarity e) => e.enemyType.enemyName).ToArray()) + "|" + string.Join("|", EnemySpawner.EnemiesOutside.Select((SpawnableEnemyWithRarity e) => e.enemyType.enemyName).ToArray());

		public SpawnCommand(ref HUDManager hudManager)
			: base("Spawn", ref hudManager)
		{
		}

		protected override string GetFullCommandSyntax()
		{
			return base.GetFullCommandSyntax() + " <" + creaturesAvailableString + "> [amount=1] [inside|outside]";
		}

		protected override bool CanBeCalled()
		{
			if (!RoundManagerBPatch.isHost)
			{
				IssueNotification("Only the host is allowed to use this comand");
				return false;
			}
			try
			{
				List<SpawnableEnemyWithRarity> enemiesOutside = EnemySpawner.EnemiesOutside;
				List<SpawnableEnemyWithRarity> enemiesInside = EnemySpawner.EnemiesInside;
				if (enemiesOutside.Count <= 0 || enemiesInside.Count <= 0)
				{
					throw new Exception();
				}
			}
			catch
			{
				IssueNotification("You need to start the game before spawning enemies");
				return false;
			}
			return true;
		}

		protected override bool ParseParameters()
		{
			if (parameters.Length < 1)
			{
				return false;
			}
			targetEnemyNameParam = parameters[0].ToLower();
			if (parameters.Length > 1)
			{
				int.TryParse(parameters[1], out targetEnemyAmountParam);
			}
			if (parameters.Length > 2)
			{
				string text = parameters[2].ToLower();
				if (text.StartsWith("in"))
				{
					spawnLocation = EnemySpawnLocation.Inside;
				}
				if (text.StartsWith("out"))
				{
					spawnLocation = EnemySpawnLocation.Outside;
				}
			}
			return true;
		}

		protected override void Execute()
		{
			List<SpawnableEnemyWithRarity> outsideEnemies = RoundManagerBPatch.currentLevel.OutsideEnemies;
			List<SpawnableEnemyWithRarity> enemies = RoundManagerBPatch.currentLevel.Enemies;
			List<SpawnableEnemyWithRarity> availableEnemies = outsideEnemies.Concat(enemies).ToList();
			HandleSpawnEnemies(availableEnemies);
			if (!targetEnemyFound)
			{
				IssueCommandSyntax();
			}
		}

		private void HandleSpawnEnemies(List<SpawnableEnemyWithRarity> availableEnemies)
		{
			foreach (SpawnableEnemyWithRarity availableEnemy in availableEnemies)
			{
				if (!targetEnemyFound && availableEnemy.enemyType.enemyName.ToLower().Contains(targetEnemyNameParam))
				{
					targetEnemyFound = true;
					targetEnemyName = availableEnemy.enemyType.enemyName;
					if (EnemySpawner.SpawnEnemy(availableEnemy, targetEnemyAmountParam, spawnLocation))
					{
						IssueNotification($"Spawned {targetEnemyAmountParam} {targetEnemyName}");
					}
					else
					{
						IssueNotification("Could not spawn enemies because an unknown error occured. Check console");
					}
				}
			}
		}
	}
}