Decompiled source of VRates v1.0.0

BepInEx/plugins/VRates/VRates.dll

Decompiled 3 days ago
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using BepInEx.Unity.IL2CPP.Hook;
using Microsoft.CodeAnalysis;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("VRates")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+769d907fa198d8b5d0051daf14d397d3aa7e12d4")]
[assembly: AssemblyProduct("VRates")]
[assembly: AssemblyTitle("VRates")]
[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.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]
	[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;
		}
	}
	[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 VRates
{
	[BepInPlugin("com.originera.vrates", "VRates", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BasePlugin
	{
		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
		private delegate ushort SettingsClampHalfDelegate(float value, float min, float max, IntPtr fieldName);

		public const string PluginGuid = "com.originera.vrates";

		public const string PluginName = "VRates";

		public const string PluginVersion = "1.0.0";

		public const float DefaultHarvestMultiplier = 10f;

		public const float DefaultLootMultiplier = 10f;

		public const float DefaultMissionLootMultiplier = 10f;

		public const float DefaultStygianShardMultiplier = 10f;

		public const float DefaultBloodEssenceMultiplier = 10f;

		public const float DefaultCraftSpeedMultiplier = 10f;

		public const float DefaultRefinementSpeedMultiplier = 10f;

		public const float DefaultRecipeCostMultiplier = 1f;

		public const float DefaultRefinementCostMultiplier = 1f;

		public const float DefaultBuildCostMultiplier = 1f;

		public const float MinimumMultiplier = 0.01f;

		public const float MaximumMultiplier = 65504f;

		private const string HarvestSettingName = "MaterialYieldModifier_Global";

		private const string LootSettingName = "DropTableModifier_General";

		private const string MissionLootSettingName = "DropTableModifier_Missions";

		private const string StygianShardSettingName = "DropTableModifier_StygianShards";

		private const string BloodEssenceSettingName = "BloodEssenceYieldModifier";

		private const string CraftRateSettingName = "CraftRateModifier";

		private const string RefinementRateSettingName = "RefinementRateModifier";

		private const string RecipeCostSettingName = "RecipeCostModifier";

		private const string RefinementCostSettingName = "RefinementCostModifier";

		private const string BuildCostSettingName = "BuildCostModifier";

		private const uint ImageScnMemExecute = 536870912u;

		private static readonly byte[] Pattern = new byte[15]
		{
			64, 87, 72, 131, 236, 96, 128, 61, 0, 0,
			0, 0, 0, 73, 139
		};

		private static readonly bool[] PatternMask = new bool[15]
		{
			true, true, true, true, true, true, true, true, false, false,
			false, false, false, true, true
		};

		private ConfigFile? _vRatesConfig;

		private ConfigEntry<float>? _harvestMultiplier;

		private ConfigEntry<float>? _lootMultiplier;

		private ConfigEntry<float>? _missionLootMultiplier;

		private ConfigEntry<float>? _stygianShardMultiplier;

		private ConfigEntry<float>? _bloodEssenceMultiplier;

		private ConfigEntry<float>? _craftSpeedMultiplier;

		private ConfigEntry<float>? _refinementSpeedMultiplier;

		private ConfigEntry<float>? _recipeCostMultiplier;

		private ConfigEntry<float>? _refinementCostMultiplier;

		private ConfigEntry<float>? _buildCostMultiplier;

		private INativeDetour? _detour;

		private SettingsClampHalfDelegate? _original;

		private SettingsClampHalfDelegate? _detourDelegate;

		private bool _loggedHarvestIntercept;

		private bool _loggedLootIntercept;

		private bool _loggedMissionLootIntercept;

		private bool _loggedStygianShardIntercept;

		private bool _loggedBloodEssenceIntercept;

		private bool _loggedCraftSpeedIntercept;

		private bool _loggedRefinementSpeedIntercept;

		private bool _loggedRecipeCostIntercept;

		private bool _loggedRefinementCostIntercept;

		private bool _loggedBuildCostIntercept;

		private bool _loggedInvalidHarvest;

		private bool _loggedInvalidLoot;

		private bool _loggedInvalidMissionLoot;

		private bool _loggedInvalidStygianShard;

		private bool _loggedInvalidBloodEssence;

		private bool _loggedInvalidCraftSpeed;

		private bool _loggedInvalidRefinementSpeed;

		private bool _loggedInvalidRecipeCost;

		private bool _loggedInvalidRefinementCost;

		private bool _loggedInvalidBuildCost;

		private bool _usingVStackBroker;

		private MethodInfo? _vStackUnregisterMethod;

		private Func<float>? _harvestProviderDelegate;

		private Func<float>? _lootProviderDelegate;

		private Func<float>? _missionLootProviderDelegate;

		private Func<float>? _stygianShardProviderDelegate;

		private Func<float>? _bloodEssenceProviderDelegate;

		private Func<float>? _craftSpeedProviderDelegate;

		private Func<float>? _refinementSpeedProviderDelegate;

		private Func<float>? _recipeCostProviderDelegate;

		private Func<float>? _refinementCostProviderDelegate;

		private Func<float>? _buildCostProviderDelegate;

		public override void Load()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_0308: Unknown result type (might be due to invalid IL or missing references)
			//IL_030f: Expected O, but got Unknown
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Expected O, but got Unknown
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Expected O, but got Unknown
			//IL_0230: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Expected O, but got Unknown
			//IL_0276: Unknown result type (might be due to invalid IL or missing references)
			//IL_027c: Expected O, but got Unknown
			//IL_02be: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c4: Expected O, but got Unknown
			_vRatesConfig = new ConfigFile(Path.Combine(Paths.ConfigPath, "VRates.cfg"), true);
			_harvestMultiplier = BindRate("HarvestMultiplier", 10f, "Multiplier for MaterialYieldModifier_Global (resource-node harvesting).");
			_lootMultiplier = BindRate("LootMultiplier", 10f, "Multiplier for DropTableModifier_General (general loot from kills/chests/drop tables).");
			_missionLootMultiplier = BindRate("MissionLootMultiplier", 10f, "Multiplier for DropTableModifier_Missions (servant mission rewards).");
			_stygianShardMultiplier = BindRate("StygianShardMultiplier", 10f, "Multiplier for DropTableModifier_StygianShards (Stygian Shard drops).");
			_bloodEssenceMultiplier = BindRate("BloodEssenceMultiplier", 10f, "Multiplier for BloodEssenceYieldModifier (Blood Essence yield).");
			_craftSpeedMultiplier = BindRate("CraftSpeedMultiplier", 10f, "Multiplier for CraftRateModifier (crafting speed).");
			_refinementSpeedMultiplier = BindRate("RefinementSpeedMultiplier", 10f, "Multiplier for RefinementRateModifier (refinement/processing speed).");
			_recipeCostMultiplier = BindRate("RecipeCostMultiplier", 1f, "Multiplier for RecipeCostModifier (crafting recipe material cost). x1 is vanilla.");
			_refinementCostMultiplier = BindRate("RefinementCostMultiplier", 1f, "Multiplier for RefinementCostModifier (refinement material cost). x1 is vanilla.");
			_buildCostMultiplier = BindRate("BuildCostMultiplier", 1f, "Multiplier for BuildCostModifier (building material cost). x1 is vanilla.");
			bool flag = default(bool);
			if (TryRegisterWithVStack(out var vStackDetected))
			{
				ManualLogSource log = ((BasePlugin)this).Log;
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(53, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("VRates");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("1.0.0");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" loaded using the VStacks shared SettingsClamp hook.");
				}
				log.LogInfo(val);
				LogConfiguredRates();
				ManualLogSource log2 = ((BasePlugin)this).Log;
				val = new BepInExInfoLogInterpolatedStringHandler(13, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Config file: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(_vRatesConfig.ConfigFilePath);
				}
				log2.LogInfo(val);
				return;
			}
			if (vStackDetected)
			{
				((BasePlugin)this).Log.LogError((object)"VStacks was detected, but it does not expose the shared SettingsClamp compatibility API. Update VStacks to version 1.0.1 or newer. VRates will not install a second competing native hook.");
				return;
			}
			try
			{
				IntPtr intPtr = FindSettingsClampHalf();
				if (intPtr == IntPtr.Zero)
				{
					((BasePlugin)this).Log.LogError((object)"SettingsClamp::Half signature was not found. The game may have updated; VRates was not applied.");
					return;
				}
				SettingsClampHalfDelegate settingsClampHalfDelegate = (_detourDelegate = SettingsClampHalfDetour);
				SettingsClampHalfDelegate original = default(SettingsClampHalfDelegate);
				_detour = INativeDetour.CreateAndApply<SettingsClampHalfDelegate>(intPtr, settingsClampHalfDelegate, ref original);
				_original = original;
				ManualLogSource log3 = ((BasePlugin)this).Log;
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(37, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("VRates");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("1.0.0");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" loaded (managed-only BepInEx hook).");
				}
				log3.LogInfo(val);
				ManualLogSource log4 = ((BasePlugin)this).Log;
				val = new BepInExInfoLogInterpolatedStringHandler(33, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Hooked SettingsClamp::Half at 0x");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<long>(intPtr.ToInt64(), "X");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(".");
				}
				log4.LogInfo(val);
				LogConfiguredRates();
				ManualLogSource log5 = ((BasePlugin)this).Log;
				val = new BepInExInfoLogInterpolatedStringHandler(13, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Config file: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(_vRatesConfig.ConfigFilePath);
				}
				log5.LogInfo(val);
				((BasePlugin)this).Log.LogInfo((object)"VRates modifies only its ten explicitly supported rate/cost settings. All other V Rising settings pass through unchanged.");
			}
			catch (Exception ex)
			{
				ManualLogSource log6 = ((BasePlugin)this).Log;
				BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(46, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Failed to install SettingsClamp::Half detour: ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Exception>(ex);
				}
				log6.LogError(val2);
			}
		}

		public override bool Unload()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Expected O, but got Unknown
			bool flag = default(bool);
			try
			{
				if (_usingVStackBroker && (object)_vStackUnregisterMethod != null)
				{
					_vStackUnregisterMethod.Invoke(null, new object[1] { "com.originera.vrates" });
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = ((BasePlugin)this).Log;
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(60, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Error while unregistering from the VStacks settings broker: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				log.LogWarning(val);
			}
			try
			{
				_usingVStackBroker = false;
				_vStackUnregisterMethod = null;
				_harvestProviderDelegate = null;
				_lootProviderDelegate = null;
				_missionLootProviderDelegate = null;
				_stygianShardProviderDelegate = null;
				_bloodEssenceProviderDelegate = null;
				_craftSpeedProviderDelegate = null;
				_refinementSpeedProviderDelegate = null;
				_recipeCostProviderDelegate = null;
				_refinementCostProviderDelegate = null;
				_buildCostProviderDelegate = null;
				((IDisposable)_detour)?.Dispose();
				_detour = null;
				_original = null;
				_detourDelegate = null;
				_harvestMultiplier = null;
				_lootMultiplier = null;
				_missionLootMultiplier = null;
				_stygianShardMultiplier = null;
				_bloodEssenceMultiplier = null;
				_craftSpeedMultiplier = null;
				_refinementSpeedMultiplier = null;
				_recipeCostMultiplier = null;
				_refinementCostMultiplier = null;
				_buildCostMultiplier = null;
				_vRatesConfig = null;
			}
			catch (Exception ex2)
			{
				ManualLogSource log2 = ((BasePlugin)this).Log;
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(36, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Error while removing native detour: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex2);
				}
				log2.LogWarning(val);
			}
			return true;
		}

		private ConfigEntry<float> BindRate(string key, float defaultValue, string description)
		{
			if (_vRatesConfig == null)
			{
				throw new InvalidOperationException("VRates config is not initialized.");
			}
			return _vRatesConfig.Bind<float>("Rates", key, defaultValue, description + " " + $"Default: {defaultValue:0.###}. " + "Valid positive range: 0.01 to 65504. Restart the server/host after editing.");
		}

		private void LogConfiguredRates()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			ManualLogSource log = ((BasePlugin)this).Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(160, 10, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Harvest x");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(GetHarvestMultiplier(), "0.###");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; ");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("General Loot x");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(GetLootMultiplier(), "0.###");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; ");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Mission Loot x");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(GetMissionLootMultiplier(), "0.###");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; ");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Stygian Shards x");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(GetStygianShardMultiplier(), "0.###");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; ");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Blood Essence x");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(GetBloodEssenceMultiplier(), "0.###");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; ");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Craft Speed x");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(GetCraftSpeedMultiplier(), "0.###");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; ");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Refinement Speed x");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(GetRefinementSpeedMultiplier(), "0.###");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; ");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Recipe Cost x");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(GetRecipeCostMultiplier(), "0.###");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; ");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Refinement Cost x");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(GetRefinementCostMultiplier(), "0.###");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; ");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Build Cost x");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(GetBuildCostMultiplier(), "0.###");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(".");
			}
			log.LogInfo(val);
		}

		private bool TryRegisterWithVStack(out bool vStackDetected)
		{
			vStackDetected = false;
			Type type = null;
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			for (int i = 0; i < assemblies.Length; i++)
			{
				Type type2 = assemblies[i].GetType("VStack.Plugin", throwOnError: false, ignoreCase: false);
				if ((object)type2 != null)
				{
					type = type2;
					vStackDetected = true;
					break;
				}
			}
			if ((object)type == null)
			{
				return false;
			}
			MethodInfo method = type.GetMethod("RegisterSettingOverride", BindingFlags.Static | BindingFlags.Public, null, new Type[3]
			{
				typeof(string),
				typeof(string),
				typeof(Func<float>)
			}, null);
			MethodInfo method2 = type.GetMethod("UnregisterSettingOverrides", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(string) }, null);
			if ((object)method == null || (object)method2 == null)
			{
				return false;
			}
			_harvestProviderDelegate = GetHarvestMultiplier;
			_lootProviderDelegate = GetLootMultiplier;
			_missionLootProviderDelegate = GetMissionLootMultiplier;
			_stygianShardProviderDelegate = GetStygianShardMultiplier;
			_bloodEssenceProviderDelegate = GetBloodEssenceMultiplier;
			_craftSpeedProviderDelegate = GetCraftSpeedMultiplier;
			_refinementSpeedProviderDelegate = GetRefinementSpeedMultiplier;
			_recipeCostProviderDelegate = GetRecipeCostMultiplier;
			_refinementCostProviderDelegate = GetRefinementCostMultiplier;
			_buildCostProviderDelegate = GetBuildCostMultiplier;
			try
			{
				if (!RegisterWithBroker(method, "MaterialYieldModifier_Global", _harvestProviderDelegate) || !RegisterWithBroker(method, "DropTableModifier_General", _lootProviderDelegate) || !RegisterWithBroker(method, "DropTableModifier_Missions", _missionLootProviderDelegate) || !RegisterWithBroker(method, "DropTableModifier_StygianShards", _stygianShardProviderDelegate) || !RegisterWithBroker(method, "BloodEssenceYieldModifier", _bloodEssenceProviderDelegate) || !RegisterWithBroker(method, "CraftRateModifier", _craftSpeedProviderDelegate) || !RegisterWithBroker(method, "RefinementRateModifier", _refinementSpeedProviderDelegate) || !RegisterWithBroker(method, "RecipeCostModifier", _recipeCostProviderDelegate) || !RegisterWithBroker(method, "RefinementCostModifier", _refinementCostProviderDelegate) || !RegisterWithBroker(method, "BuildCostModifier", _buildCostProviderDelegate))
				{
					method2.Invoke(null, new object[1] { "com.originera.vrates" });
					return false;
				}
				_vStackUnregisterMethod = method2;
				_usingVStackBroker = true;
				((BasePlugin)this).Log.LogInfo((object)"VStacks compatibility detected. Registered all ten VRates settings with the shared SettingsClamp::Half hook; VRates will not install a second native detour.");
				return true;
			}
			catch
			{
				try
				{
					method2.Invoke(null, new object[1] { "com.originera.vrates" });
				}
				catch
				{
				}
				_usingVStackBroker = false;
				_vStackUnregisterMethod = null;
				_harvestProviderDelegate = null;
				_lootProviderDelegate = null;
				_missionLootProviderDelegate = null;
				_stygianShardProviderDelegate = null;
				_bloodEssenceProviderDelegate = null;
				_craftSpeedProviderDelegate = null;
				_refinementSpeedProviderDelegate = null;
				_recipeCostProviderDelegate = null;
				_refinementCostProviderDelegate = null;
				_buildCostProviderDelegate = null;
				throw;
			}
		}

		private static bool RegisterWithBroker(MethodInfo registerMethod, string settingName, Func<float> provider)
		{
			return Convert.ToBoolean(registerMethod.Invoke(null, new object[3] { "com.originera.vrates", settingName, provider }));
		}

		private ushort SettingsClampHalfDetour(float value, float min, float max, IntPtr fieldName)
		{
			SettingsClampHalfDelegate original = _original;
			if (original == null)
			{
				return 0;
			}
			if (IsIl2CppStringEqual(fieldName, "MaterialYieldModifier_Global"))
			{
				ApplySetting(ref value, ref min, ref max, GetHarvestMultiplier(), "MaterialYieldModifier_Global", ref _loggedHarvestIntercept);
			}
			else if (IsIl2CppStringEqual(fieldName, "DropTableModifier_General"))
			{
				ApplySetting(ref value, ref min, ref max, GetLootMultiplier(), "DropTableModifier_General", ref _loggedLootIntercept);
			}
			else if (IsIl2CppStringEqual(fieldName, "DropTableModifier_Missions"))
			{
				ApplySetting(ref value, ref min, ref max, GetMissionLootMultiplier(), "DropTableModifier_Missions", ref _loggedMissionLootIntercept);
			}
			else if (IsIl2CppStringEqual(fieldName, "DropTableModifier_StygianShards"))
			{
				ApplySetting(ref value, ref min, ref max, GetStygianShardMultiplier(), "DropTableModifier_StygianShards", ref _loggedStygianShardIntercept);
			}
			else if (IsIl2CppStringEqual(fieldName, "BloodEssenceYieldModifier"))
			{
				ApplySetting(ref value, ref min, ref max, GetBloodEssenceMultiplier(), "BloodEssenceYieldModifier", ref _loggedBloodEssenceIntercept);
			}
			else if (IsIl2CppStringEqual(fieldName, "CraftRateModifier"))
			{
				ApplySetting(ref value, ref min, ref max, GetCraftSpeedMultiplier(), "CraftRateModifier", ref _loggedCraftSpeedIntercept);
			}
			else if (IsIl2CppStringEqual(fieldName, "RefinementRateModifier"))
			{
				ApplySetting(ref value, ref min, ref max, GetRefinementSpeedMultiplier(), "RefinementRateModifier", ref _loggedRefinementSpeedIntercept);
			}
			else if (IsIl2CppStringEqual(fieldName, "RecipeCostModifier"))
			{
				ApplySetting(ref value, ref min, ref max, GetRecipeCostMultiplier(), "RecipeCostModifier", ref _loggedRecipeCostIntercept);
			}
			else if (IsIl2CppStringEqual(fieldName, "RefinementCostModifier"))
			{
				ApplySetting(ref value, ref min, ref max, GetRefinementCostMultiplier(), "RefinementCostModifier", ref _loggedRefinementCostIntercept);
			}
			else if (IsIl2CppStringEqual(fieldName, "BuildCostModifier"))
			{
				ApplySetting(ref value, ref min, ref max, GetBuildCostMultiplier(), "BuildCostModifier", ref _loggedBuildCostIntercept);
			}
			return original(value, min, max, fieldName);
		}

		private void ApplySetting(ref float value, ref float min, ref float max, float multiplier, string settingName, ref bool logged)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			value = multiplier;
			min = 0f;
			max = multiplier;
			if (!logged)
			{
				logged = true;
				ManualLogSource log = ((BasePlugin)this).Log;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(29, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(settingName);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" intercepted and forced to x");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(multiplier, "0.###");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(".");
				}
				log.LogInfo(val);
			}
		}

		private float GetHarvestMultiplier()
		{
			return GetValidatedMultiplier(_harvestMultiplier?.Value ?? 10f, 10f, "HarvestMultiplier", ref _loggedInvalidHarvest);
		}

		private float GetLootMultiplier()
		{
			return GetValidatedMultiplier(_lootMultiplier?.Value ?? 10f, 10f, "LootMultiplier", ref _loggedInvalidLoot);
		}

		private float GetMissionLootMultiplier()
		{
			return GetValidatedMultiplier(_missionLootMultiplier?.Value ?? 10f, 10f, "MissionLootMultiplier", ref _loggedInvalidMissionLoot);
		}

		private float GetStygianShardMultiplier()
		{
			return GetValidatedMultiplier(_stygianShardMultiplier?.Value ?? 10f, 10f, "StygianShardMultiplier", ref _loggedInvalidStygianShard);
		}

		private float GetBloodEssenceMultiplier()
		{
			return GetValidatedMultiplier(_bloodEssenceMultiplier?.Value ?? 10f, 10f, "BloodEssenceMultiplier", ref _loggedInvalidBloodEssence);
		}

		private float GetCraftSpeedMultiplier()
		{
			return GetValidatedMultiplier(_craftSpeedMultiplier?.Value ?? 10f, 10f, "CraftSpeedMultiplier", ref _loggedInvalidCraftSpeed);
		}

		private float GetRefinementSpeedMultiplier()
		{
			return GetValidatedMultiplier(_refinementSpeedMultiplier?.Value ?? 10f, 10f, "RefinementSpeedMultiplier", ref _loggedInvalidRefinementSpeed);
		}

		private float GetRecipeCostMultiplier()
		{
			return GetValidatedMultiplier(_recipeCostMultiplier?.Value ?? 1f, 1f, "RecipeCostMultiplier", ref _loggedInvalidRecipeCost);
		}

		private float GetRefinementCostMultiplier()
		{
			return GetValidatedMultiplier(_refinementCostMultiplier?.Value ?? 1f, 1f, "RefinementCostMultiplier", ref _loggedInvalidRefinementCost);
		}

		private float GetBuildCostMultiplier()
		{
			return GetValidatedMultiplier(_buildCostMultiplier?.Value ?? 1f, 1f, "BuildCostMultiplier", ref _loggedInvalidBuildCost);
		}

		private float GetValidatedMultiplier(float configured, float defaultValue, string settingName, ref bool loggedInvalid)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Expected O, but got Unknown
			bool flag = default(bool);
			if (float.IsNaN(configured) || float.IsInfinity(configured) || configured <= 0f)
			{
				if (!loggedInvalid)
				{
					loggedInvalid = true;
					ManualLogSource log = ((BasePlugin)this).Log;
					BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(29, 3, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Invalid ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(settingName);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" '");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(configured);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("'. Using default x");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(defaultValue, "0.###");
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(".");
					}
					log.LogWarning(val);
				}
				return defaultValue;
			}
			if (configured > 65504f)
			{
				if (!loggedInvalid)
				{
					loggedInvalid = true;
					ManualLogSource log2 = ((BasePlugin)this).Log;
					BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(45, 3, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(settingName);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" x");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(configured, "0.###");
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" exceeds the half-precision limit. ");
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Using x");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(65504f, "0.###");
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(".");
					}
					log2.LogWarning(val);
				}
				return 65504f;
			}
			return Math.Max(configured, 0.01f);
		}

		private unsafe static bool IsIl2CppStringEqual(IntPtr stringObject, string expected)
		{
			if (stringObject == IntPtr.Zero)
			{
				return false;
			}
			byte* ptr = (byte*)(void*)stringObject;
			int num = ((int*)ptr)[4];
			if (num != expected.Length || num < 0 || num > 128)
			{
				return false;
			}
			char* ptr2 = (char*)ptr + 10;
			for (int i = 0; i < num; i++)
			{
				if (ptr2[i] != expected[i])
				{
					return false;
				}
			}
			return true;
		}

		private unsafe IntPtr FindSettingsClampHalf()
		{
			ProcessModule processModule = null;
			foreach (ProcessModule module in Process.GetCurrentProcess().Modules)
			{
				if (string.Equals(module.ModuleName, "GameAssembly.dll", StringComparison.OrdinalIgnoreCase))
				{
					processModule = module;
					break;
				}
			}
			if (processModule == null)
			{
				throw new InvalidOperationException("GameAssembly.dll is not loaded.");
			}
			byte* ptr = (byte*)(void*)processModule.BaseAddress;
			if (*(ushort*)ptr != 23117)
			{
				throw new InvalidOperationException("Loaded GameAssembly.dll has an invalid DOS header.");
			}
			int num = ((int*)ptr)[15];
			byte* num2 = ptr + num;
			if (*(uint*)num2 != 17744)
			{
				throw new InvalidOperationException("Loaded GameAssembly.dll has an invalid PE header.");
			}
			ushort num3 = ((ushort*)num2)[3];
			ushort num4 = ((ushort*)num2)[10];
			byte* ptr2 = num2 + 24 + (int)num4;
			IntPtr intPtr = IntPtr.Zero;
			int num5 = 0;
			int num6 = 0;
			while (num6 < num3)
			{
				uint num7 = ((uint*)ptr2)[2];
				uint num8 = ((uint*)ptr2)[3];
				if ((((uint*)ptr2)[9] & 0x20000000) != 0 && num7 >= Pattern.Length)
				{
					byte* ptr3 = ptr + num8;
					int num9 = checked((int)num7);
					for (int i = 0; i <= num9 - Pattern.Length; i++)
					{
						if (Matches(ptr3 + i))
						{
							num5++;
							intPtr = (IntPtr)(ptr3 + i);
						}
					}
				}
				num6++;
				ptr2 += 40;
			}
			return num5 switch
			{
				0 => IntPtr.Zero, 
				1 => intPtr, 
				_ => throw new InvalidOperationException($"SettingsClamp::Half signature was not unique ({num5} matches). Refusing to hook."), 
			};
		}

		private unsafe static bool Matches(byte* address)
		{
			for (int i = 0; i < Pattern.Length; i++)
			{
				if (PatternMask[i] && address[i] != Pattern[i])
				{
					return false;
				}
			}
			return true;
		}
	}
}