Decompiled source of OneHitShovel v1.5.1

OneHitShovel.dll

Decompiled 3 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
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 OPJosMod.OneHitShovel.CustomRpc;
using OPJosMod.OneHitShovel.Patches;
using OPJosMod.OneHitShovel.Utils;
using Unity.Netcode;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("OPJosMod")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("OPJosMod")]
[assembly: AssemblyCopyright("Copyright ©  2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("70095872-b952-4e27-bbc4-3d70d0238f39")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace OPJosMod
{
	public static class ConfigVariables
	{
		public static bool syncDeathAnimations;
	}
}
namespace OPJosMod.OneHitShovel
{
	public static class Constants
	{
		public static List<string> humanoidNames = new List<string> { "SpringManModel", "DressGirlModel", "MeshContainer", "SpringMan(Clone)", "DressGirl(Clone)", "JesterEnemy(Clone)" };

		public static string[] fourLeggedNames = new string[2] { "PufferModel", "PufferEnemy(Clone)" };

		public static string[] dieInPlaceNames = new string[3] { "Bone.", "Bone", "SandWorm(Clone)" };

		public static string[] slimeNames = new string[10] { "BoneEast", "BoneNorth", "BoneSouth", "BoneWest", "BoneNorthWest", "BoneNorthEast", "BoneSouthEast", "BoneSouthWest", "Center", "Blob(Clone)" };

		public static string[] mechNames = new string[2] { "ClawTrigger", "RadMechEnemy(Clone)" };
	}
	public static class CustomEnemyDeaths
	{
		private static ManualLogSource mls;

		public static void SetLogSource(ManualLogSource logSource)
		{
			mls = logSource;
		}

		public static void killHumanoid(GameObject gameObject)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//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_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			mls.LogMessage((object)("try to kill " + ((Object)gameObject).name));
			gameObject.transform.rotation = Quaternion.Euler(-90f, 0f, 90f);
			Renderer component = gameObject.GetComponent<Renderer>();
			float num;
			if (!((Object)(object)component != (Object)null))
			{
				num = 0.1f;
			}
			else
			{
				Bounds bounds = component.bounds;
				num = ((Bounds)(ref bounds)).size.x * 0.1f;
			}
			float num2 = num;
			Transform transform = gameObject.transform;
			transform.position += new Vector3(0f, num2, 0f);
			Collider[] componentsInChildren = gameObject.GetComponentsInChildren<Collider>();
			Collider[] array = componentsInChildren;
			foreach (Collider val in array)
			{
				val.enabled = false;
			}
			EnemyAI val2 = findClosestEnemyAI(gameObject.transform.position);
			if ((Object)(object)val2 != (Object)null)
			{
				mls.LogMessage((object)"enemy ai isn't null");
				val2.isEnemyDead = true;
				((Behaviour)val2.creatureAnimator).enabled = false;
				stopAllSounds(val2);
			}
			else
			{
				mls.LogMessage((object)"enemy ai is null");
			}
		}

		public static IEnumerator KillMech(Vector3 hitLocation, bool updateOnServer = false)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			EnemyAI enemyAI = findClosestEnemyAI(hitLocation);
			try
			{
				mls.LogMessage((object)"trying to kill mech");
				if (enemyAI is RadMechAI)
				{
					RadMechAI radMech = (RadMechAI)enemyAI;
					((MonoBehaviour)radMech).StopAllCoroutines();
					killHumanoid(((Component)radMech).gameObject);
					if (updateOnServer)
					{
						updateLocationOnServer(((Component)radMech).gameObject);
					}
					radMech.DisableSpotlight();
					radMech.DisableBlowtorch();
					radMech.DisableThrusterSmoke();
					((EnemyAI)radMech).enemyHP = 0;
					((Behaviour)radMech.engineSFX).enabled = false;
					radMech.chargeForwardAudio.volume = 0f;
					radMech.engineSFX.volume = 0f;
					radMech.flyingDistantAudio.volume = 0f;
					radMech.spotlightOnAudio.volume = 0f;
					radMech.LocalLRADAudio.volume = 0f;
					radMech.LocalLRADAudio2.volume = 0f;
					radMech.blowtorchAudio.volume = 0f;
				}
			}
			catch
			{
			}
			yield return (object)new WaitForSeconds(0.2f);
			killHumanoid(((Component)enemyAI).gameObject);
		}

		public static void killInPlace(GameObject gameObject)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			mls.LogMessage((object)("try to kill " + ((Object)gameObject).name));
			Collider[] componentsInChildren = gameObject.GetComponentsInChildren<Collider>();
			Collider[] array = componentsInChildren;
			foreach (Collider val in array)
			{
				val.enabled = false;
			}
			EnemyAI val2 = findClosestEnemyAI(gameObject.transform.position);
			if ((Object)(object)val2 != (Object)null)
			{
				mls.LogMessage((object)"enemy ai isn't null");
				val2.isEnemyDead = true;
				((Behaviour)val2.creatureAnimator).enabled = false;
				stopAllSounds(val2);
			}
			else
			{
				mls.LogMessage((object)"enemy ai is null");
			}
		}

		public static void killFourLegged(GameObject gameObject)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//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_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			mls.LogMessage((object)("try to kill " + ((Object)gameObject).name));
			gameObject.transform.rotation = Quaternion.Euler(180f, 0f, 0f);
			Renderer component = gameObject.GetComponent<Renderer>();
			float num;
			if (!((Object)(object)component != (Object)null))
			{
				num = 1f;
			}
			else
			{
				Bounds bounds = component.bounds;
				num = ((Bounds)(ref bounds)).size.y * 0.1f;
			}
			float num2 = num;
			Transform transform = gameObject.transform;
			transform.position += new Vector3(0f, num2, 0f);
			Collider[] componentsInChildren = gameObject.GetComponentsInChildren<Collider>();
			Collider[] array = componentsInChildren;
			foreach (Collider val in array)
			{
				val.enabled = false;
			}
			EnemyAI val2 = findClosestEnemyAI(gameObject.transform.position);
			if ((Object)(object)val2 != (Object)null)
			{
				mls.LogMessage((object)"enemy ai isn't null");
				val2.isEnemyDead = true;
				((Behaviour)val2.creatureAnimator).enabled = false;
				stopAllSounds(val2);
			}
			else
			{
				mls.LogMessage((object)"enemy ai is null");
			}
		}

		public static void killSlime(GameObject gameObject)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			mls.LogMessage((object)("try to kill " + ((Object)gameObject).name));
			EnemyAI val = findClosestEnemyAI(gameObject.transform.position);
			if ((Object)(object)val != (Object)null)
			{
				mls.LogMessage((object)"enemy ai isn't null");
				val.isEnemyDead = true;
				((Behaviour)val.creatureAnimator).enabled = false;
			}
			else
			{
				mls.LogMessage((object)"enemy ai is null");
			}
			Object.Destroy((Object)(object)val);
			stopAllSounds(val);
			string[] slimeNames = Constants.slimeNames;
			foreach (string name in slimeNames)
			{
				destroySlimePart(gameObject, name);
			}
		}

		public static void updateLocationOnServer(GameObject gameObject)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			EnemyAI val = findClosestEnemyAI(gameObject.transform.position);
			if ((Object)(object)val != (Object)null)
			{
				val.KillEnemyServerRpc(false);
			}
			else
			{
				mls.LogMessage((object)"no enemy to kill");
			}
			if (ConfigVariables.syncDeathAnimations)
			{
				string code = MessageTaskUtil.GetCode(MessageTasks.EnemyDied);
				Vector3 position = gameObject.transform.position;
				string message = code + ((object)(Vector3)(ref position)).ToString();
				RpcMessage message2 = new RpcMessage(message, (int)StartOfRound.Instance.localPlayerController.playerClientId, MessageCodes.Request);
				RpcMessageHandler.SendRpcMessage(message2);
			}
			else
			{
				val.KillEnemyServerRpc(true);
			}
		}

		private static void stopAllSounds(EnemyAI enemy)
		{
			AudioSource[] componentsInChildren = ((Component)enemy).GetComponentsInChildren<AudioSource>();
			AudioSource[] array = componentsInChildren;
			foreach (AudioSource val in array)
			{
				val.Stop();
			}
		}

		private static void destroySlimePart(GameObject gameObject, string name)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			GameObject[] array = Object.FindObjectsOfType<GameObject>();
			GameObject val = null;
			float num = float.PositiveInfinity;
			GameObject[] array2 = array;
			foreach (GameObject val2 in array2)
			{
				if (((Object)val2).name == name)
				{
					float num2 = Vector3.Distance(gameObject.transform.position, val2.transform.position);
					if (num2 < num && num2 < 15f)
					{
						num = num2;
						val = val2;
					}
				}
			}
			if ((Object)(object)val != (Object)null)
			{
				mls.LogMessage((object)("Closest Enemy with name '" + name + "' found: " + ((Object)val).name));
			}
			else
			{
				mls.LogMessage((object)("No Enemy with name '" + name + "' found in the scene."));
			}
			Object.Destroy((Object)(object)val);
		}

		public static EnemyAI findClosestEnemyAI(Vector3 location)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			EnemyAI val = null;
			EnemyAI[] array = Object.FindObjectsOfType<EnemyAI>();
			float num = float.PositiveInfinity;
			EnemyAI[] array2 = array;
			foreach (EnemyAI val2 in array2)
			{
				float num2 = Vector3.Distance(location, ((Component)val2).transform.position);
				if (num2 < num)
				{
					num = num2;
					val = val2;
				}
			}
			if ((Object)(object)val != (Object)null)
			{
				mls.LogMessage((object)("Closest EnemyAI found: " + ((Object)val).name));
			}
			else
			{
				mls.LogError((object)"No EnemyAI found in the scene.");
			}
			return val;
		}

		public static void KillAnyEnemy(EnemyAI enemy)
		{
			mls.LogMessage((object)("enemy died " + ((Object)enemy).name));
			GameObject gameObject = ((Component)enemy).gameObject;
			KillGameObjectEnemy(gameObject);
		}

		public static void KillGameObjectEnemy(GameObject gameObject)
		{
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)gameObject != (Object)null && ((Object)gameObject).name != "Player")
			{
				mls.LogMessage((object)("kill game object with name: " + ((Object)gameObject).name));
				if (Constants.humanoidNames.Contains(((Object)gameObject).name))
				{
					killHumanoid(gameObject);
				}
				if (Constants.fourLeggedNames.Contains(((Object)gameObject).name))
				{
					killFourLegged(gameObject);
				}
				if (Constants.slimeNames.Contains(((Object)gameObject).name))
				{
					killSlime(gameObject);
				}
				if (Constants.mechNames.Contains(((Object)gameObject).name))
				{
					((MonoBehaviour)StartOfRound.Instance.localPlayerController).StartCoroutine(KillMech(gameObject.transform.position));
				}
				if (((Object)gameObject).name == null)
				{
					return;
				}
				int num = ((Object)gameObject).name.LastIndexOf('.');
				if (num != -1)
				{
					string value = ((Object)gameObject).name.Substring(0, num + 1);
					if (Constants.dieInPlaceNames.Contains(value))
					{
						killInPlace(gameObject);
					}
				}
			}
			else
			{
				mls.LogError((object)"game object was null");
			}
		}
	}
	public static class GeneralUtil
	{
		public static Vector3 StringToVector3(string s)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			string[] array = s.Trim('(', ')').Split(new char[1] { ',' });
			float num = float.Parse(array[0]);
			float num2 = float.Parse(array[1]);
			float num3 = float.Parse(array[2]);
			return new Vector3(num, num2, num3);
		}

		public static int GetGameVersion()
		{
			try
			{
				return GameNetworkManager.Instance.gameVersionNum;
			}
			catch
			{
			}
			return 0;
		}
	}
	public static class GlobalVariables
	{
		public static bool ModActivated;
	}
	[BepInPlugin("OpJosMod.OneHitShovel", "OneHitShovel", "1.5.1")]
	public class OpJosMod : BaseUnityPlugin
	{
		private const string modGUID = "OpJosMod.OneHitShovel";

		private const string modName = "OneHitShovel";

		private const string modVersion = "1.5.1";

		private readonly Harmony harmony = new Harmony("OpJosMod.OneHitShovel");

		private static OpJosMod Instance;

		internal ManualLogSource mls;

		private void Awake()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
			mls = Logger.CreateLogSource("OpJosMod.OneHitShovel");
			setupConfig();
			PatchesForRPC.SetLogSource(mls);
			RpcMessageHandler.SetLogSource(mls);
			CompleteRecievedTasks.SetLogSource(mls);
			ShovelPatch.SetLogSource(mls);
			CustomEnemyDeaths.SetLogSource(mls);
			harmony.PatchAll();
		}

		private void setupConfig()
		{
			ConfigEntry<bool> val = ((BaseUnityPlugin)this).Config.Bind<bool>("Custom Death Animations", "CustomDeathAnimations", true, "Setting for attempting to sync death animations for enemies that can't normally die. If off the enemies will just despawn instead.");
			ConfigVariables.syncDeathAnimations = val.Value;
		}
	}
}
namespace OPJosMod.OneHitShovel.Utils
{
	public class ReflectionUtils
	{
		public static void InvokeMethod(object obj, string methodName, object[] parameters)
		{
			Type type = obj.GetType();
			MethodInfo method = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			method.Invoke(obj, parameters);
		}

		public static void InvokeMethod(object obj, Type forceType, string methodName, object[] parameters)
		{
			MethodInfo method = forceType.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			method.Invoke(obj, parameters);
		}

		public static void SetPropertyValue(object obj, string propertyName, object value)
		{
			Type type = obj.GetType();
			PropertyInfo property = type.GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			property.SetValue(obj, value);
		}

		public static T InvokeMethod<T>(object obj, string methodName, object[] parameters)
		{
			Type type = obj.GetType();
			MethodInfo method = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			return (T)method.Invoke(obj, parameters);
		}

		public static T GetFieldValue<T>(object obj, string fieldName)
		{
			Type type = obj.GetType();
			FieldInfo field = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			return (T)field.GetValue(obj);
		}

		public static void SetFieldValue(object obj, string fieldName, object value)
		{
			Type type = obj.GetType();
			FieldInfo field = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			field.SetValue(obj, value);
		}
	}
}
namespace OPJosMod.OneHitShovel.Patches
{
	[HarmonyPatch(typeof(Shovel))]
	internal class ShovelPatch
	{
		private static ManualLogSource mls;

		public static void SetLogSource(ManualLogSource logSource)
		{
			mls = logSource;
		}

		[HarmonyPatch("HitShovel")]
		[HarmonyPrefix]
		private static void hitShovelPatch(Shovel __instance)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			if (!GlobalVariables.ModActivated)
			{
				return;
			}
			try
			{
				__instance.shovelHitForce = 30;
				GameObject val = null;
				PlayerControllerB fieldValue = ReflectionUtils.GetFieldValue<PlayerControllerB>(__instance, "previousPlayerHeldBy");
				RaycastHit[] fieldValue2 = ReflectionUtils.GetFieldValue<RaycastHit[]>(__instance, "objectsHitByShovel");
				List<RaycastHit> fieldValue3 = ReflectionUtils.GetFieldValue<List<RaycastHit>>(__instance, "objectsHitByShovelList");
				int fieldValue4 = ReflectionUtils.GetFieldValue<int>(__instance, "shovelMask");
				fieldValue2 = Physics.SphereCastAll(((Component)fieldValue.gameplayCamera).transform.position + ((Component)fieldValue.gameplayCamera).transform.right * -0.35f, 0.8f, ((Component)fieldValue.gameplayCamera).transform.forward, 1.5f, fieldValue4, (QueryTriggerInteraction)2);
				fieldValue3 = fieldValue2.OrderBy((RaycastHit x) => ((RaycastHit)(ref x)).distance).ToList();
				IHittable val3 = default(IHittable);
				for (int i = 0; i < fieldValue3.Count; i++)
				{
					RaycastHit val2 = fieldValue3[i];
					if (((Component)((RaycastHit)(ref val2)).transform).TryGetComponent<IHittable>(ref val3) && !((Object)((Component)((RaycastHit)(ref val2)).transform).gameObject).name.Contains("Player"))
					{
						mls.LogMessage((object)("Hit object: " + ((Object)((Component)((RaycastHit)(ref val2)).transform).gameObject).name));
						val = ((Component)((RaycastHit)(ref val2)).transform).gameObject;
					}
				}
				if ((Object)(object)val != (Object)null)
				{
					CustomEnemyDeaths.KillGameObjectEnemy(val);
					CustomEnemyDeaths.updateLocationOnServer(val);
				}
				Vector3? val4 = checkIfHitMech();
				if (val4.HasValue)
				{
					((MonoBehaviour)StartOfRound.Instance.localPlayerController).StartCoroutine(CustomEnemyDeaths.KillMech(val4.Value, updateOnServer: true));
				}
			}
			catch (Exception ex)
			{
				mls.LogError((object)ex);
			}
		}

		private static Vector3? checkIfHitMech()
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				PlayerControllerB localPlayerController = StartOfRound.Instance.localPlayerController;
				RadMechAI[] array = Object.FindObjectsOfType<RadMechAI>();
				if (array.Length == 0)
				{
					return null;
				}
				RadMechAI val = null;
				float num = float.PositiveInfinity;
				RadMechAI[] array2 = array;
				foreach (RadMechAI val2 in array2)
				{
					Vector3 val3 = ((Component)val2).transform.position - ((Component)localPlayerController).transform.position;
					if (Vector3.Dot(((Component)localPlayerController).transform.forward, ((Vector3)(ref val3)).normalized) > 0.5f)
					{
						float magnitude = ((Vector3)(ref val3)).magnitude;
						if (magnitude <= 3f && magnitude < num)
						{
							num = magnitude;
							val = val2;
						}
					}
				}
				if ((Object)(object)val == (Object)null)
				{
					return null;
				}
				return ((Component)val).transform.position;
			}
			catch
			{
				return null;
			}
		}
	}
}
namespace OPJosMod.OneHitShovel.CustomRpc
{
	public static class CompleteRecievedTasks
	{
		private static ManualLogSource mls;

		public static void SetLogSource(ManualLogSource logSource)
		{
			mls = logSource;
		}

		public static void ModActivated(string modName)
		{
			if (mls.SourceName == modName)
			{
				mls.LogMessage((object)"Mod Activated");
				GlobalVariables.ModActivated = true;
			}
		}

		public static void EnemyDied(string position)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			Vector3 location = GeneralUtil.StringToVector3(position);
			EnemyAI val = CustomEnemyDeaths.findClosestEnemyAI(location);
			if ((Object)(object)val != (Object)null)
			{
				CustomEnemyDeaths.KillAnyEnemy(val);
			}
			else
			{
				mls.LogMessage((object)"couldnt find enemy to kill");
			}
		}
	}
	public enum MessageCodes
	{
		Request,
		Response
	}
	public static class MessageCodeUtil
	{
		public static string GetCode(MessageCodes code)
		{
			return code switch
			{
				MessageCodes.Request => ":rpcRequest:", 
				MessageCodes.Response => ":rpcResponse:", 
				_ => ":Error:", 
			};
		}

		public static bool stringContainsMessageCode(string givenString)
		{
			return givenString.Contains(GetCode(MessageCodes.Request)) || givenString.Contains(GetCode(MessageCodes.Response));
		}

		public static string returnMessageWithoutCode(string message)
		{
			if (stringContainsMessageCode(message))
			{
				int length = GetCode(MessageCodes.Request).Length;
				return message.Substring(length);
			}
			return message;
		}
	}
	public enum MessageTasks
	{
		ModActivated,
		EnemyDied,
		ErrorNoTask
	}
	public static class MessageTaskUtil
	{
		public static string GetCode(MessageTasks code)
		{
			return code switch
			{
				MessageTasks.ModActivated => ":ModActivated:", 
				MessageTasks.EnemyDied => ":EnemyDied:", 
				MessageTasks.ErrorNoTask => ":Error:", 
				_ => ":Error:", 
			};
		}

		public static string getMessageWithoutTask(string message)
		{
			foreach (MessageTasks value in Enum.GetValues(typeof(MessageTasks)))
			{
				string code2 = GetCode(value);
				message = message.Replace(code2, "");
			}
			return message.Trim();
		}

		public static MessageTasks getMessageTask(string givenString)
		{
			if (givenString.Contains(GetCode(MessageTasks.ModActivated)))
			{
				return MessageTasks.ModActivated;
			}
			if (givenString.Contains(GetCode(MessageTasks.EnemyDied)))
			{
				return MessageTasks.EnemyDied;
			}
			return MessageTasks.ErrorNoTask;
		}
	}
	public class RpcMessage
	{
		public string Message { get; set; }

		public int FromUser { get; set; }

		public MessageCodes MessageCode { get; set; }

		public RpcMessage(string message, int user, MessageCodes code)
		{
			Message = message;
			FromUser = user;
			MessageCode = code;
		}

		public string getMessageWithCode()
		{
			return MessageCodeUtil.GetCode(MessageCode) + Message;
		}
	}
	public static class RpcMessageHandler
	{
		private static ManualLogSource mls;

		private static float lastSentTime = Time.time;

		private static float messageWaitTime = 1f;

		public static void SetLogSource(ManualLogSource logSource)
		{
			mls = logSource;
		}

		public static void SendRpcMessage(RpcMessage message)
		{
			if (!(Time.time - lastSentTime > messageWaitTime))
			{
				return;
			}
			lastSentTime = Time.time;
			HUDManager instance = HUDManager.Instance;
			if ((Object)(object)instance != (Object)null)
			{
				MethodInfo method = typeof(HUDManager).GetMethod("AddPlayerChatMessageServerRpc", BindingFlags.Instance | BindingFlags.NonPublic);
				if (method != null)
				{
					object[] parameters = new object[2]
					{
						message.getMessageWithCode(),
						message.FromUser
					};
					method.Invoke(instance, parameters);
				}
				else
				{
					mls.LogError((object)"AddPlayerChatMessageServerRpc method not found in HUDManager class.");
				}
			}
			else
			{
				mls.LogError((object)"HUDManager.Instance is null.");
			}
		}

		public static void ReceiveRpcMessage(string message, int user)
		{
			if (user != (int)StartOfRound.Instance.localPlayerController.playerClientId)
			{
				string text = MessageCodeUtil.returnMessageWithoutCode(message);
				if (message.Contains(MessageCodeUtil.GetCode(MessageCodes.Request)))
				{
					MessageTasks messageTask = MessageTaskUtil.getMessageTask(text);
					string messageWithoutTask = MessageTaskUtil.getMessageWithoutTask(text);
					handleTask(messageTask, messageWithoutTask);
				}
				else if (message.Contains(MessageCodeUtil.GetCode(MessageCodes.Response)))
				{
					mls.LogMessage((object)"got the response that the other clients recieved this message");
				}
			}
		}

		public static void SendRpcResponse(string message)
		{
			RpcMessage message2 = new RpcMessage(message, (int)StartOfRound.Instance.localPlayerController.playerClientId, MessageCodes.Response);
			SendRpcMessage(message2);
		}

		private static void handleTask(MessageTasks task, string message)
		{
			switch (task)
			{
			case MessageTasks.ModActivated:
				CompleteRecievedTasks.ModActivated(message);
				break;
			case MessageTasks.EnemyDied:
				CompleteRecievedTasks.EnemyDied(message);
				break;
			case MessageTasks.ErrorNoTask:
				mls.LogError((object)"got an error task");
				break;
			}
		}
	}
	public static class PatchesForRPC
	{
		public static ManualLogSource mls;

		public static void SetLogSource(ManualLogSource logSource)
		{
			mls = logSource;
		}
	}
	[HarmonyPatch(typeof(HUDManager))]
	internal static class HUDManagerPatchForRPC
	{
		private static float lastRecievedAt = Time.time;

		private static string lastRecievedMessage = "";

		private static float messageWaitTime = 0.5f;

		[HarmonyPatch("AddPlayerChatMessageClientRpc")]
		[HarmonyPrefix]
		private static void addPlayerChatMessageClientRpcPatch(ref string chatMessage, ref int playerId)
		{
			if (MessageCodeUtil.stringContainsMessageCode(chatMessage) && (Time.time - lastRecievedAt > messageWaitTime || chatMessage != lastRecievedMessage))
			{
				lastRecievedAt = Time.time;
				lastRecievedMessage = chatMessage;
				RpcMessageHandler.ReceiveRpcMessage(chatMessage, playerId);
			}
		}

		[HarmonyPatch("AddChatMessage")]
		[HarmonyPrefix]
		private static bool addChatMessagePatch(ref string chatMessage)
		{
			if (MessageCodeUtil.stringContainsMessageCode(chatMessage))
			{
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(StartOfRound))]
	internal static class StartOfRoundPatchForRPC
	{
		[HarmonyPatch("OnClientConnect")]
		[HarmonyPostfix]
		private static void patchOnClientConnect(StartOfRound __instance)
		{
			((MonoBehaviour)__instance).StartCoroutine(activateModForOthers(__instance));
		}

		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		private static void patchStart(StartOfRound __instance)
		{
			if (((NetworkBehaviour)__instance).IsHost)
			{
				GlobalVariables.ModActivated = true;
			}
		}

		[HarmonyPatch("OnLocalDisconnect")]
		[HarmonyPostfix]
		private static void patchOnLocalDisconnect(StartOfRound __instance)
		{
			GlobalVariables.ModActivated = false;
		}

		private static IEnumerator activateModForOthers(StartOfRound __instance)
		{
			yield return (object)new WaitForSeconds(3f);
			if (((NetworkBehaviour)__instance).IsHost)
			{
				GlobalVariables.ModActivated = true;
				string message = MessageTaskUtil.GetCode(MessageTasks.ModActivated) + PatchesForRPC.mls.SourceName;
				RpcMessage rpcMessage = new RpcMessage(message, (int)__instance.localPlayerController.playerClientId, MessageCodes.Request);
				RpcMessageHandler.SendRpcMessage(rpcMessage);
			}
		}
	}
}