Decompiled source of AbsorptionEitrShield v0.3.19

AbsorptionEitrShield.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
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(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("AbsorptionEitrShield")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("AbsorptionEitrShield")]
[assembly: AssemblyTitle("AbsorptionEitrShield")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 AbsorptionEitrShield
{
	[BepInPlugin("com.absorptioneitrshield.mod", "AbsorptionEitrShield", "0.3.19")]
	public sealed class AbsorptionEitrShieldPlugin : BaseUnityPlugin
	{
		[CompilerGenerated]
		private sealed class <InitNetWhenReady>d__16 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public AbsorptionEitrShieldPlugin <>4__this;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <InitNetWhenReady>d__16(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if ((Object)(object)ZNet.instance == (Object)null || ZRoutedRpc.instance == null)
				{
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				Net.EnsureRegistered();
				if (Net.IsServer())
				{
					Server_EnableMod = CE_EnableMod.Value;
					Server_UseRecharge = CE_UseRecharge.Value;
					Net.ServerBroadcastSettings(Server_EnableMod, Server_UseRecharge);
				}
				else
				{
					Net.ClientRequestSync();
				}
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <RevertClientConfigNextFrame>d__14 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public AbsorptionEitrShieldPlugin <>4__this;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <RevertClientConfigNextFrame>d__14(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = null;
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					SetLocalConfigSilently(Server_EnableMod, Server_UseRecharge);
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		public const string ModName = "AbsorptionEitrShield";

		public const string ModGUID = "com.absorptioneitrshield.mod";

		public const string ModVersion = "0.3.19";

		internal static ManualLogSource Log;

		internal static AbsorptionEitrShieldPlugin Instance;

		internal static ConfigEntry<bool> CE_EnableMod;

		internal static ConfigEntry<bool> CE_UseRecharge;

		internal static bool Server_EnableMod = true;

		internal static bool Server_UseRecharge = true;

		private static bool _silentConfigSet;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			CE_EnableMod = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable/disable AbsorptionEitrShield. Host/server decides.");
			CE_UseRecharge = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "UseRecharge", true, "If enabled: shield works only when Eitr is fully charged; deactivates when Eitr is drained to ~0 and waits for full recharge. Host/server decides.");
			((BaseUnityPlugin)this).Config.SettingChanged += OnConfigChanged;
			_harmony = new Harmony("com.absorptioneitrshield.mod");
			_harmony.PatchAll();
			((MonoBehaviour)this).StartCoroutine(InitNetWhenReady());
			Log.LogInfo((object)"AbsorptionEitrShield v0.3.19 loaded.");
		}

		private void OnDestroy()
		{
			try
			{
				((BaseUnityPlugin)this).Config.SettingChanged -= OnConfigChanged;
			}
			catch
			{
			}
			try
			{
				_harmony.UnpatchSelf();
			}
			catch
			{
			}
		}

		private void OnConfigChanged(object sender, EventArgs e)
		{
			if (!_silentConfigSet)
			{
				if (!Net.IsServer())
				{
					((MonoBehaviour)this).StartCoroutine(RevertClientConfigNextFrame());
					return;
				}
				Server_EnableMod = CE_EnableMod.Value;
				Server_UseRecharge = CE_UseRecharge.Value;
				Net.ServerBroadcastSettings(Server_EnableMod, Server_UseRecharge);
			}
		}

		[IteratorStateMachine(typeof(<RevertClientConfigNextFrame>d__14))]
		private IEnumerator RevertClientConfigNextFrame()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <RevertClientConfigNextFrame>d__14(0)
			{
				<>4__this = this
			};
		}

		internal static void SetLocalConfigSilently(bool enabled, bool useRecharge)
		{
			try
			{
				_silentConfigSet = true;
				CE_EnableMod.Value = enabled;
				CE_UseRecharge.Value = useRecharge;
			}
			finally
			{
				_silentConfigSet = false;
			}
		}

		[IteratorStateMachine(typeof(<InitNetWhenReady>d__16))]
		private IEnumerator InitNetWhenReady()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <InitNetWhenReady>d__16(0)
			{
				<>4__this = this
			};
		}
	}
	internal static class Runtime
	{
		public static float IgnoreAbsorbUntilTime = -1f;

		public static bool ModEnabled()
		{
			return AbsorptionEitrShieldPlugin.Server_EnableMod;
		}

		public static bool UseRecharge()
		{
			return AbsorptionEitrShieldPlugin.Server_UseRecharge;
		}

		public static bool IsDieBypassActive()
		{
			return Time.time < IgnoreAbsorbUntilTime;
		}
	}
	internal static class Net
	{
		private const string RPC_RequestSync = "AES_RequestSync";

		private const string RPC_SetSettings = "AES_SetSettings";

		private static bool _registered;

		public static void EnsureRegistered()
		{
			if (_registered || ZRoutedRpc.instance == null)
			{
				return;
			}
			try
			{
				ZRoutedRpc.instance.Register<ZPackage>("AES_RequestSync", (Action<long, ZPackage>)RPC_RequestSync_Handler);
				ZRoutedRpc.instance.Register<ZPackage>("AES_SetSettings", (Action<long, ZPackage>)RPC_SetSettings_Handler);
				_registered = true;
			}
			catch (Exception ex)
			{
				AbsorptionEitrShieldPlugin.Log.LogWarning((object)("[AES] RPC register failed: " + ex.GetType().Name + ": " + ex.Message));
			}
		}

		public static bool IsServer()
		{
			try
			{
				return (Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer();
			}
			catch
			{
				return false;
			}
		}

		public static void ClientRequestSync()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			try
			{
				if (ZRoutedRpc.instance == null)
				{
					return;
				}
				ZPackage val = new ZPackage();
				long num = ZRoutedRpc.Everybody;
				try
				{
					MethodInfo methodInfo = AccessTools.Method(typeof(ZRoutedRpc), "GetServerPeerID", Type.EmptyTypes, (Type[])null);
					if (methodInfo != null)
					{
						object obj = methodInfo.Invoke(ZRoutedRpc.instance, null);
						if (obj is long)
						{
							long num2 = (long)obj;
							if (num2 != 0)
							{
								num = num2;
							}
						}
					}
				}
				catch
				{
				}
				ZRoutedRpc.instance.InvokeRoutedRPC(num, "AES_RequestSync", new object[1] { val });
			}
			catch
			{
			}
		}

		public static void ServerBroadcastSettings(bool enabled, bool useRecharge)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			try
			{
				if (IsServer() && ZRoutedRpc.instance != null)
				{
					ZPackage val = new ZPackage();
					val.Write(enabled);
					val.Write(useRecharge);
					ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "AES_SetSettings", new object[1] { val });
				}
			}
			catch (Exception ex)
			{
				AbsorptionEitrShieldPlugin.Log.LogWarning((object)("[AES] Broadcast failed: " + ex.GetType().Name + ": " + ex.Message));
			}
		}

		private static void RPC_RequestSync_Handler(long sender, ZPackage pkg)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			if (!IsServer())
			{
				return;
			}
			ZPackage val = new ZPackage();
			val.Write(AbsorptionEitrShieldPlugin.Server_EnableMod);
			val.Write(AbsorptionEitrShieldPlugin.Server_UseRecharge);
			try
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(sender, "AES_SetSettings", new object[1] { val });
			}
			catch (Exception ex)
			{
				AbsorptionEitrShieldPlugin.Log.LogWarning((object)("[AES] Reply sync failed: " + ex.GetType().Name + ": " + ex.Message));
			}
		}

		private static void RPC_SetSettings_Handler(long sender, ZPackage pkg)
		{
			try
			{
				bool flag = pkg.ReadBool();
				bool flag2 = pkg.ReadBool();
				AbsorptionEitrShieldPlugin.Server_EnableMod = flag;
				AbsorptionEitrShieldPlugin.Server_UseRecharge = flag2;
				AbsorptionEitrShieldPlugin.SetLocalConfigSilently(flag, flag2);
				AbsorptionEitrShieldPlugin.Log.LogInfo((object)$"[AES] Synced from server: Enabled={flag}, UseRecharge={flag2}");
			}
			catch (Exception ex)
			{
				AbsorptionEitrShieldPlugin.Log.LogWarning((object)("[AES] Apply settings failed: " + ex.GetType().Name + ": " + ex.Message));
			}
		}
	}
	internal sealed class ShieldState
	{
		public bool Active;

		public float LastMaxEitr;
	}
	internal static class ShieldSystem
	{
		private static readonly ConditionalWeakTable<Player, ShieldState> States = new ConditionalWeakTable<Player, ShieldState>();

		private const float FullEps = 0.01f;

		private const float DrainThreshold = 1.01f;

		private static readonly MethodInfo GetMaxEitrMI = AccessTools.Method(typeof(Player), "GetMaxEitr", Type.EmptyTypes, (Type[])null);

		public static ShieldState Get(Player p)
		{
			return States.GetOrCreateValue(p);
		}

		public static float ReadEitr(Player p)
		{
			return p.GetEitr();
		}

		public static float ReadMaxEitr(Player p)
		{
			try
			{
				if (GetMaxEitrMI != null)
				{
					return (float)GetMaxEitrMI.Invoke(p, null);
				}
			}
			catch
			{
			}
			return 0f;
		}

		public static void Evaluate(Player p)
		{
			ShieldState shieldState = Get(p);
			float num = ReadEitr(p);
			float num2 = ReadMaxEitr(p);
			if (!Runtime.ModEnabled())
			{
				shieldState.Active = false;
				shieldState.LastMaxEitr = num2;
				return;
			}
			if (!Runtime.UseRecharge())
			{
				shieldState.Active = num2 > 0.001f;
				shieldState.LastMaxEitr = num2;
				return;
			}
			if (num2 <= 0.001f)
			{
				shieldState.Active = false;
				shieldState.LastMaxEitr = 0f;
				return;
			}
			if (shieldState.LastMaxEitr > 0.001f && num2 > shieldState.LastMaxEitr + 0.01f && num < num2 - 0.01f)
			{
				shieldState.Active = false;
			}
			shieldState.LastMaxEitr = num2;
			if (shieldState.Active)
			{
				if (num <= 1.01f)
				{
					shieldState.Active = false;
				}
			}
			else if (num >= num2 - 0.01f)
			{
				shieldState.Active = true;
			}
		}
	}
	internal sealed class ShieldUpdater : MonoBehaviour
	{
		private Player _player;

		private void Awake()
		{
			_player = ((Component)this).GetComponent<Player>();
		}

		private void Update()
		{
			if (!((Object)(object)_player == (Object)null) && ((Character)_player).IsOwner() && !((Character)_player).IsDead())
			{
				ShieldSystem.Evaluate(_player);
			}
		}
	}
	[HarmonyPatch(typeof(Player), "Awake")]
	internal static class Player_Awake_AttachUpdater
	{
		private static void Postfix(Player __instance)
		{
			if (!((Object)(object)__instance == (Object)null) && ((Character)__instance).IsOwner() && (Object)(object)((Component)__instance).GetComponent<ShieldUpdater>() == (Object)null)
			{
				((Component)__instance).gameObject.AddComponent<ShieldUpdater>();
			}
		}
	}
	internal static class DamageUtil
	{
		public static float SumHitDamage(HitData hit)
		{
			//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)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			DamageTypes damage = hit.m_damage;
			return damage.m_blunt + damage.m_slash + damage.m_pierce + damage.m_chop + damage.m_pickaxe + damage.m_fire + damage.m_frost + damage.m_lightning + damage.m_poison + damage.m_spirit;
		}

		public static string F(float v)
		{
			return v.ToString("0.###", CultureInfo.InvariantCulture);
		}
	}
	[HarmonyPatch]
	internal static class Character_ApplyDamage_EitrShieldPatch
	{
		private struct State
		{
			public bool Active;

			public float Absorb;

			public float HpBefore;

			public float EitrBefore;

			public float D;
		}

		private static MethodBase TargetMethod()
		{
			List<MethodInfo> declaredMethods = AccessTools.GetDeclaredMethods(typeof(Character));
			foreach (MethodInfo item in declaredMethods)
			{
				if (!(item == null) && !(item.Name != "ApplyDamage"))
				{
					ParameterInfo[] parameters = item.GetParameters();
					if (parameters.Length >= 1 && !(parameters[0].ParameterType != typeof(HitData)))
					{
						return item;
					}
				}
			}
			return null;
		}

		private static void Prefix(Character __instance, HitData hit, ref State __state)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			__state = default(State);
			if ((Object)(object)__instance == (Object)null || hit == null || !(__instance is Player))
			{
				return;
			}
			Player val = (Player)__instance;
			if (!((Character)val).IsOwner() || ((Character)val).IsDead() || Runtime.IsDieBypassActive())
			{
				return;
			}
			ShieldSystem.Evaluate(val);
			ShieldState shieldState = ShieldSystem.Get(val);
			if (!shieldState.Active)
			{
				return;
			}
			float eitr = val.GetEitr();
			if (eitr <= 0.0001f)
			{
				return;
			}
			float num = DamageUtil.SumHitDamage(hit);
			if (!(num <= 0.0001f))
			{
				float num2 = num;
				if (num2 > eitr)
				{
					num2 = eitr;
				}
				if (!(num2 <= 0.0001f))
				{
					float health = ((Character)val).GetHealth();
					__state.Active = true;
					__state.Absorb = num2;
					__state.HpBefore = health;
					__state.EitrBefore = eitr;
					__state.D = num;
					((Character)val).SetHealth(health + num2);
					((Character)val).AddEitr(0f - num2);
				}
			}
		}

		private static Exception Finalizer(Character __instance, HitData hit, State __state, Exception __exception)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			if (__exception != null && __state.Active && (Object)(object)__instance != (Object)null && __instance is Player)
			{
				try
				{
					Player val = (Player)__instance;
					if (((Character)val).IsOwner() && !((Character)val).IsDead())
					{
						((Character)val).SetHealth(__state.HpBefore);
						((Character)val).AddEitr(__state.Absorb);
					}
				}
				catch
				{
				}
			}
			return __exception;
		}
	}
	[HarmonyPatch]
	internal static class Terminal_DieBypassPatch
	{
		[CompilerGenerated]
		private sealed class <TargetMethods>d__0 : IEnumerable<MethodBase>, IEnumerable, IEnumerator<MethodBase>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private MethodBase <>2__current;

			private int <>l__initialThreadId;

			private Type <t>5__1;

			private List<MethodInfo>.Enumerator <>s__2;

			private MethodInfo <m>5__3;

			private ParameterInfo[] <p>5__4;

			MethodBase IEnumerator<MethodBase>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <TargetMethods>d__0(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || num == 1)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<t>5__1 = null;
				<>s__2 = default(List<MethodInfo>.Enumerator);
				<m>5__3 = null;
				<p>5__4 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				try
				{
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						<t>5__1 = typeof(Terminal);
						<>s__2 = AccessTools.GetDeclaredMethods(<t>5__1).GetEnumerator();
						<>1__state = -3;
						break;
					case 1:
						<>1__state = -3;
						<p>5__4 = null;
						<m>5__3 = null;
						break;
					}
					while (<>s__2.MoveNext())
					{
						<m>5__3 = <>s__2.Current;
						if (!(<m>5__3 == null) && (<m>5__3.Name.Contains("RunCommand") || <m>5__3.Name.Contains("TryRunCommand")))
						{
							<p>5__4 = <m>5__3.GetParameters();
							if (<p>5__4.Length >= 1 && !(<p>5__4[0].ParameterType != typeof(string)))
							{
								<>2__current = <m>5__3;
								<>1__state = 1;
								return true;
							}
						}
					}
					<>m__Finally1();
					<>s__2 = default(List<MethodInfo>.Enumerator);
					return false;
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				((IDisposable)<>s__2).Dispose();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<MethodBase> IEnumerable<MethodBase>.GetEnumerator()
			{
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					return this;
				}
				return new <TargetMethods>d__0(0);
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<MethodBase>)this).GetEnumerator();
			}
		}

		[IteratorStateMachine(typeof(<TargetMethods>d__0))]
		private static IEnumerable<MethodBase> TargetMethods()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <TargetMethods>d__0(-2);
		}

		private static void Prefix(object[] __args)
		{
			if (__args == null || __args.Length < 1)
			{
				return;
			}
			string text = __args[0] as string;
			if (!string.IsNullOrEmpty(text))
			{
				string text2 = text.Trim();
				if (text2.StartsWith("/"))
				{
					text2 = text2.Substring(1).Trim();
				}
				if (text2.Equals("die", StringComparison.OrdinalIgnoreCase) || text2.StartsWith("die ", StringComparison.OrdinalIgnoreCase))
				{
					Runtime.IgnoreAbsorbUntilTime = Time.time + 0.35f;
				}
			}
		}
	}
}