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;
}
}
}