Decompiled source of Anti Lag Photon Disc v0.1.0

BepInEx/plugins/dotoo_antilag_photon_disc.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
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("dotoo_antilag_photon_disc")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("dotoo_antilag_photon_disc")]
[assembly: AssemblyTitle("dotoo_antilag_photon_disc")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace AntiLagPhotonDisc
{
	[BepInPlugin("dotoo.antilagphotondisc", "Anti-lag Photon Disc", "0.1.0")]
	[MycoMod(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> DevMode;

		internal static ConfigEntry<int> MaxChunks;

		internal static ConfigEntry<float> PullSpeedMultiplier;

		private void Awake()
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Expected O, but got Unknown
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Expected O, but got Unknown
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			DevMode = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DevMode", false, "Enable verbose debug logging. Leave this off for normal play.");
			MaxChunks = ((BaseUnityPlugin)this).Config.Bind<int>("Limit", "MaxChunks", 100, new ConfigDescription("Maximum number of Photon Disc health chunks that can exist at once. When this is exceeded, the oldest chunks are removed first. Set to 0 to disable the limit. Only chunks spawned by the Photon Disc upgrade are counted.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 1000), Array.Empty<object>()));
			PullSpeedMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Pull", "PullSpeedMultiplier", 1f, new ConfigDescription("Multiplier for how fast Photon Disc health chunks fly toward you. 1 = vanilla speed. Only affects chunks spawned by the Photon Disc upgrade.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f), Array.Empty<object>()));
			Harmony harmony = new Harmony("dotoo.antilagphotondisc");
			TryPatch(harmony, typeof(PhotonDiscSpawnPatch));
			TryPatch(harmony, typeof(CollectableSpawnPatch));
			TryPatch(harmony, typeof(HealingDeactivatedPatch));
		}

		private static void TryPatch(Harmony harmony, Type patchType)
		{
			try
			{
				harmony.CreateClassProcessor(patchType).Patch();
				if (DevMode.Value)
				{
					Log.LogInfo((object)("[DevMode] Patched " + patchType.Name));
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Failed to patch " + patchType.Name + ": " + ex));
			}
		}
	}
	internal static class ChunkTracker
	{
		internal static bool InPhotonSpawn;

		internal static int RemovedThisCall;

		private static readonly LinkedList<HealingCollectable> list = new LinkedList<HealingCollectable>();

		private static readonly Dictionary<HealingCollectable, LinkedListNode<HealingCollectable>> nodes = new Dictionary<HealingCollectable, LinkedListNode<HealingCollectable>>();

		private static readonly FieldInfo prefabField = AccessTools.Field(typeof(ClientCollectable), "prefab");

		private static readonly FieldInfo speedField = AccessTools.Field(typeof(ClientCollectable), "magnetizeSpeed");

		internal static int Count => nodes.Count;

		internal static void Add(HealingCollectable heal)
		{
			Remove(heal);
			nodes[heal] = list.AddLast(heal);
			int value = Plugin.MaxChunks.Value;
			if (value <= 0)
			{
				return;
			}
			while (nodes.Count > value && list.First != null)
			{
				HealingCollectable value2 = list.First.Value;
				Remove(value2);
				RemovedThisCall++;
				if ((Object)(object)value2 != (Object)null && ((Component)value2).gameObject.activeSelf)
				{
					((ClientCollectable)value2).DespawnTrackedObject();
				}
			}
		}

		internal static void Remove(HealingCollectable heal)
		{
			if (heal != null && nodes.TryGetValue(heal, out var value))
			{
				list.Remove(value);
				nodes.Remove(heal);
			}
		}

		internal static void SetSpeed(HealingCollectable heal, float multiplier)
		{
			if (prefabField == null || speedField == null)
			{
				return;
			}
			object? value = prefabField.GetValue(heal);
			ClientCollectable val = (ClientCollectable)((value is ClientCollectable) ? value : null);
			if (!((Object)(object)val == (Object)null))
			{
				float num = (float)speedField.GetValue(val) * multiplier;
				float num2 = (float)speedField.GetValue(heal);
				if (!Mathf.Approximately(num2, num))
				{
					speedField.SetValue(heal, num);
				}
			}
		}
	}
	[HarmonyPatch]
	internal static class PhotonDiscSpawnPatch
	{
		private static int callCount;

		internal static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(PhotonDiscBullet), "SpawnHealthChunks", new Type[2]
			{
				typeof(int),
				typeof(float)
			}, (Type[])null);
		}

		internal static void Prefix(int count)
		{
			ChunkTracker.InPhotonSpawn = true;
			ChunkTracker.RemovedThisCall = 0;
			callCount = count;
		}

		internal static void Finalizer()
		{
			ChunkTracker.InPhotonSpawn = false;
			if (Plugin.DevMode.Value)
			{
				Plugin.Log.LogInfo((object)("[DevMode] SpawnHealthChunks count=" + callCount + " alive=" + ChunkTracker.Count + " removed=" + ChunkTracker.RemovedThisCall + " max=" + Plugin.MaxChunks.Value));
			}
		}
	}
	[HarmonyPatch]
	internal static class CollectableSpawnPatch
	{
		internal static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(ClientCollectable), "SpawnCollectable", new Type[3]
			{
				typeof(ClientCollectable),
				typeof(Vector3),
				typeof(float)
			}, (Type[])null);
		}

		internal static void Postfix(ClientCollectable __result)
		{
			HealingCollectable val = (HealingCollectable)(object)((__result is HealingCollectable) ? __result : null);
			if (!((Object)(object)val == (Object)null))
			{
				if (ChunkTracker.InPhotonSpawn)
				{
					ChunkTracker.Add(val);
					ChunkTracker.SetSpeed(val, Plugin.PullSpeedMultiplier.Value);
				}
				else
				{
					ChunkTracker.Remove(val);
					ChunkTracker.SetSpeed(val, 1f);
				}
			}
		}
	}
	[HarmonyPatch]
	internal static class HealingDeactivatedPatch
	{
		internal static MethodBase TargetMethod()
		{
			return AccessTools.DeclaredMethod(typeof(HealingCollectable), "OnDeactivated", (Type[])null, (Type[])null);
		}

		internal static void Postfix(HealingCollectable __instance)
		{
			ChunkTracker.Remove(__instance);
		}
	}
}