Decompiled source of CustomEnemyUpdater v1.0.0

CustomEnemyUpdater.dll

Decompiled 2 weeks ago
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using CustomEnemyUpdater.Patches;
using Enemies;
using GTFO.API.Utilities;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using SNetwork;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("CustomEnemyUpdater")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+64811ecc44ca4dd4c485286092e86fefdd4a2f16")]
[assembly: AssemblyProduct("CustomEnemyUpdater")]
[assembly: AssemblyTitle("CustomEnemyUpdater")]
[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;
		}
	}
}
namespace CustomEnemyUpdater
{
	public static class Configuration
	{
		private static readonly ConfigEntry<bool> _fixedUpdate;

		private static readonly ConfigEntry<int> _node;

		private static readonly ConfigEntry<string> _locomotion;

		private static readonly ConfigEntry<string> _behaviour;

		private static readonly ConfigEntry<string> _detection;

		private static readonly ConfigEntry<string> _network;

		public static readonly int[] Locomotion;

		public static readonly int[] Behaviour;

		public static readonly int[] Detection;

		public static readonly int[] Network;

		private static readonly ConfigFile _configFile;

		public static bool FixedUpdate { get; private set; }

		public static int Node { get; private set; }

		static Configuration()
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			FixedUpdate = false;
			Node = 0;
			Locomotion = new int[3];
			Behaviour = new int[3];
			Detection = new int[3];
			Network = new int[3];
			_configFile = new ConfigFile(Path.Combine(Paths.ConfigPath, "CustomEnemyUpdater.cfg"), true);
			string text = "Custom Settings";
			string text2 = "Use fixed update instead of the default update system.\nIf modified in-game, requires a game restart to apply.";
			_fixedUpdate = _configFile.Bind<bool>(text, "Use Fixed Update", false, text2);
			text = "Update Settings";
			text2 = "Handles locomotion updates, such as movement, animations, and attacks.\nAccepts values for Close, Near, Far as comma-separated values.";
			_locomotion = _configFile.Bind<string>(text, "Locomotion", "20, 10, 5", text2);
			text2 = "Handles behaviour updates, such as pathfinding and checking when to attack. Most cannot run for an enemy more than once every 0.2s.\nAccepts values for Close, Near, Far as comma-separated values.";
			_behaviour = _configFile.Bind<string>(text, "Behaviour", "5, 2, 1", text2);
			text2 = "Handles detection updates, such as detecting sound in stealth and deciding which player to target in combat.\nAccepts values for Close, Near, Far as comma-separated values.";
			_detection = _configFile.Bind<string>(text, "Detection", "10, 4, 1", text2);
			text2 = "Handles locomotion network updates, syncing enemy positions with clients.\nAccepts values for Close, Near, Far as comma-separated values.";
			_network = _configFile.Bind<string>(text, "Network", "12, 3, 1", text2);
			text2 = "The number of nodes/rooms to update. Iterates through all enemies in the node(s). Generally best left at 1 as it provides information for the other updates.";
			_node = _configFile.Bind<int>(text, "Node", 1, text2);
			UpdateValues();
		}

		internal static void Init()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			LiveEdit.CreateListener(Paths.ConfigPath, "CustomEnemyUpdater.cfg", false).FileChanged += new LiveEditEventHandler(OnFileChanged);
		}

		private static void OnFileChanged(LiveEditEventArgs _)
		{
			_configFile.Reload();
			UpdateValues();
			EnemyUpdateManagerPatches.Reload();
		}

		private static void UpdateValues()
		{
			FixedUpdate = _fixedUpdate.Value;
			PopulateUpdateVals(Locomotion, _locomotion.Value);
			PopulateUpdateVals(Behaviour, _behaviour.Value);
			PopulateUpdateVals(Detection, _detection.Value);
			PopulateUpdateVals(Network, _network.Value);
			Node = _node.Value;
		}

		private static void PopulateUpdateVals(int[] array, string csv)
		{
			string[] array2 = csv.Split(',');
			if (array2.Length != 3)
			{
				DinoLogger.Warning($"Expected 3 values for update values, but found {array2.Length}!");
			}
			for (int i = 0; i < Math.Min(array.Length, array2.Length); i++)
			{
				if (!int.TryParse(array2[i].Trim(), out var result))
				{
					DinoLogger.Error("Unable to read " + array2[i] + " as integer!");
				}
				else
				{
					array[i] = result;
				}
			}
		}
	}
	internal static class DinoLogger
	{
		private static ManualLogSource logger = Logger.CreateLogSource("CustomEnemyUpdater");

		public static void Log(string format, params object[] args)
		{
			Log(string.Format(format, args));
		}

		public static void Log(string str)
		{
			if (logger != null)
			{
				logger.Log((LogLevel)8, (object)str);
			}
		}

		public static void Warning(string format, params object[] args)
		{
			Warning(string.Format(format, args));
		}

		public static void Warning(string str)
		{
			if (logger != null)
			{
				logger.Log((LogLevel)4, (object)str);
			}
		}

		public static void Error(string format, params object[] args)
		{
			Error(string.Format(format, args));
		}

		public static void Error(string str)
		{
			if (logger != null)
			{
				logger.Log((LogLevel)2, (object)str);
			}
		}

		public static void Debug(string format, params object[] args)
		{
			Debug(string.Format(format, args));
		}

		public static void Debug(string str)
		{
			if (logger != null)
			{
				logger.Log((LogLevel)32, (object)str);
			}
		}
	}
	[BepInPlugin("Dinorush.CustomEnemyUpdater", "CustomEnemyUpdater", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	internal sealed class EntryPoint : BasePlugin
	{
		public const string MODNAME = "CustomEnemyUpdater";

		public override void Load()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			Configuration.Init();
			Harmony val = new Harmony("CustomEnemyUpdater");
			val.PatchAll();
			if (Configuration.FixedUpdate)
			{
				val.PatchAll(typeof(GS_InLevelPatches));
			}
			((BasePlugin)this).Log.LogMessage((object)"Loaded CustomEnemyUpdater");
		}
	}
}
namespace CustomEnemyUpdater.Patches
{
	[HarmonyPatch(typeof(EnemyUpdateManager))]
	internal static class EnemyUpdateManagerPatches
	{
		[HarmonyPatch("Setup")]
		[HarmonyPostfix]
		private static void OnSetup(EnemyUpdateManager __instance)
		{
			((SteppedUpdateGroup)__instance.m_nodeUpdates).m_maxUpdateCountPerFrame = Configuration.Node;
			((SteppedUpdateGroup)__instance.m_locomotionUpdatesClose).m_maxUpdateCountPerFrame = Configuration.Locomotion[0];
			((SteppedUpdateGroup)__instance.m_locomotionUpdatesNear).m_maxUpdateCountPerFrame = Configuration.Locomotion[1];
			((SteppedUpdateGroup)__instance.m_locomotionUpdatesFar).m_maxUpdateCountPerFrame = Configuration.Locomotion[2];
			((SteppedUpdateGroup)__instance.m_behaviourUpdatesClose).m_maxUpdateCountPerFrame = Configuration.Behaviour[0];
			((SteppedUpdateGroup)__instance.m_behaviourUpdatesNear).m_maxUpdateCountPerFrame = Configuration.Behaviour[1];
			((SteppedUpdateGroup)__instance.m_behaviourUpdatesFar).m_maxUpdateCountPerFrame = Configuration.Behaviour[2];
			((SteppedUpdateGroup)__instance.m_detectionUpdatesClose).m_maxUpdateCountPerFrame = Configuration.Detection[0];
			((SteppedUpdateGroup)__instance.m_detectionUpdatesNear).m_maxUpdateCountPerFrame = Configuration.Detection[1];
			((SteppedUpdateGroup)__instance.m_detectionUpdatesFar).m_maxUpdateCountPerFrame = Configuration.Detection[2];
			((SteppedUpdateGroup)__instance.m_networkUpdatesClose).m_maxUpdateCountPerFrame = Configuration.Network[0];
			((SteppedUpdateGroup)__instance.m_networkUpdatesNear).m_maxUpdateCountPerFrame = Configuration.Network[1];
			((SteppedUpdateGroup)__instance.m_networkUpdatesFar).m_maxUpdateCountPerFrame = Configuration.Network[2];
		}

		public static void Reload()
		{
			OnSetup(EnemyUpdateManager.Current);
		}
	}
	internal static class GS_InLevelPatches
	{
		[HarmonyPrefix]
		[HarmonyPatch(typeof(GS_InLevel), "FixedUpdate")]
		public static bool FixedUpdate()
		{
			if (SNet.MasterManagement.IsMigrating || SNet.Lobbies.CheckPendingJoinRequest)
			{
				return true;
			}
			EnemyUpdateManager.Current.GamestateUpdateFixed();
			Mastermind.Current.GameStateUpdateFixed();
			return false;
		}
	}
}