Decompiled source of CustomApparatusValues v1.5.0

plugins/CustomApparatusValues/CustomApparatusValues.dll

Decompiled 3 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("CustomApparatusValues")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("CustomApparatusValues")]
[assembly: AssemblyTitle("CustomApparatusValues")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace CustomApparatusValues;

internal static class ApparatusValueSync
{
	private const string SyncMessageName = "CustomApparatusValues.SyncValue";

	private static bool handlersRegistered = false;

	private static readonly Dictionary<ulong, int> PendingValues = new Dictionary<ulong, int>();

	private static readonly HashSet<ulong> AppliedValues = new HashSet<ulong>();

	internal static void EnsureHandlersRegistered()
	{
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Expected O, but got Unknown
		NetworkManager singleton = NetworkManager.Singleton;
		if (!((Object)(object)singleton == (Object)null) && !handlersRegistered && singleton.CustomMessagingManager != null)
		{
			singleton.CustomMessagingManager.RegisterNamedMessageHandler("CustomApparatusValues.SyncValue", new HandleNamedMessageDelegate(OnReceiveSyncValueMessage));
			handlersRegistered = true;
			Plugin.LogVerbose("Handler de synchronisation enregistré.");
		}
	}

	internal static void ResetState()
	{
		PendingValues.Clear();
		AppliedValues.Clear();
		handlersRegistered = false;
	}

	internal static bool HasAlreadyBeenApplied(ulong networkObjectId)
	{
		return AppliedValues.Contains(networkObjectId);
	}

	internal static void MarkApplied(ulong networkObjectId)
	{
		if (!AppliedValues.Contains(networkObjectId))
		{
			AppliedValues.Add(networkObjectId);
		}
	}

	internal static void SyncToClients(GrabbableObject grabbableObject, int value)
	{
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)grabbableObject == (Object)null)
		{
			return;
		}
		NetworkObject networkObject = ((NetworkBehaviour)grabbableObject).NetworkObject;
		if ((Object)(object)networkObject == (Object)null)
		{
			Plugin.LogWarning("Impossible de synchroniser un objet sans NetworkObject.");
			return;
		}
		NetworkManager singleton = NetworkManager.Singleton;
		if ((Object)(object)singleton == (Object)null || singleton.CustomMessagingManager == null)
		{
			return;
		}
		EnsureHandlersRegistered();
		ulong networkObjectId = networkObject.NetworkObjectId;
		MarkApplied(networkObjectId);
		Plugin.LogVerbose("Sync envoyée pour l'objet réseau " + networkObjectId + " avec valeur " + value + ".");
		FastBufferWriter val = default(FastBufferWriter);
		try
		{
			val = new FastBufferWriter(12, (Allocator)2, -1);
			((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref networkObjectId, default(ForPrimitives));
			((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref value, default(ForPrimitives));
			foreach (ulong connectedClientsId in singleton.ConnectedClientsIds)
			{
				if (connectedClientsId != singleton.LocalClientId)
				{
					singleton.CustomMessagingManager.SendNamedMessage("CustomApparatusValues.SyncValue", connectedClientsId, val, (NetworkDelivery)3);
				}
			}
		}
		catch (Exception ex)
		{
			Plugin.LogError("Erreur lors de l'envoi de la synchronisation: " + ex);
		}
		finally
		{
			((FastBufferWriter)(ref val)).Dispose();
		}
	}

	private static void OnReceiveSyncValueMessage(ulong senderClientId, FastBufferReader reader)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			ulong num = default(ulong);
			((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref num, default(ForPrimitives));
			int value = default(int);
			((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref value, default(ForPrimitives));
			Plugin.LogVerbose("Sync reçue depuis " + senderClientId + " pour objet " + num + " => " + value);
			if (!TryApplyValueToSpawnedObject(num, value))
			{
				PendingValues[num] = value;
				Plugin.LogVerbose("Objet " + num + " pas encore disponible côté client. Sync mise en attente.");
			}
		}
		catch (Exception ex)
		{
			Plugin.LogError("Erreur lors de la réception d'une synchronisation: " + ex);
		}
	}

	internal static void TryApplyPendingValue(GrabbableObject grabbableObject)
	{
		if (!((Object)(object)grabbableObject == (Object)null) && !((Object)(object)((NetworkBehaviour)grabbableObject).NetworkObject == (Object)null))
		{
			ulong networkObjectId = ((NetworkBehaviour)grabbableObject).NetworkObject.NetworkObjectId;
			if (PendingValues.TryGetValue(networkObjectId, out var value))
			{
				ApplyValue(grabbableObject, value);
				PendingValues.Remove(networkObjectId);
				Plugin.LogVerbose("Valeur en attente appliquée à l'objet " + networkObjectId + ".");
			}
		}
	}

	internal static bool TryApplyValueToSpawnedObject(ulong objectId, int value)
	{
		NetworkManager singleton = NetworkManager.Singleton;
		if ((Object)(object)singleton == (Object)null || singleton.SpawnManager == null)
		{
			return false;
		}
		if (!singleton.SpawnManager.SpawnedObjects.TryGetValue(objectId, out var value2))
		{
			return false;
		}
		if ((Object)(object)value2 == (Object)null)
		{
			return false;
		}
		GrabbableObject component = ((Component)value2).GetComponent<GrabbableObject>();
		if ((Object)(object)component == (Object)null)
		{
			return false;
		}
		ApplyValue(component, value);
		return true;
	}

	internal static void ApplyValue(GrabbableObject grabbableObject, int value)
	{
		if ((Object)(object)grabbableObject == (Object)null)
		{
			return;
		}
		try
		{
			grabbableObject.SetScrapValue(value);
			if (grabbableObject.scrapValue != value)
			{
				grabbableObject.scrapValue = value;
			}
			if ((Object)(object)grabbableObject.itemProperties != (Object)null)
			{
				grabbableObject.itemProperties.creditsWorth = value;
			}
			if ((Object)(object)((NetworkBehaviour)grabbableObject).NetworkObject != (Object)null)
			{
				MarkApplied(((NetworkBehaviour)grabbableObject).NetworkObject.NetworkObjectId);
			}
			string text = (((Object)(object)grabbableObject.itemProperties != (Object)null) ? grabbableObject.itemProperties.itemName : "<unknown>");
			Plugin.LogVerbose("Valeur appliquée à '" + text + "' => " + value);
		}
		catch (Exception ex)
		{
			Plugin.LogError("Erreur lors de l'application d'une valeur synchronisée: " + ex);
		}
	}
}
[HarmonyPatch(typeof(StartOfRound))]
internal static class StartOfRoundPatch
{
	[HarmonyPostfix]
	[HarmonyPatch("Awake")]
	private static void AwakePostfix()
	{
		Plugin.ResetRuntimeState();
		ApparatusValueSync.ResetState();
		ApparatusValueSync.EnsureHandlersRegistered();
		Plugin.LogVerbose("Initialisation réseau du mod terminée.");
	}
}
[HarmonyPatch(typeof(GameNetworkManager))]
internal static class GameNetworkManagerPatch
{
	[HarmonyPostfix]
	[HarmonyPatch("Start")]
	private static void StartPostfix()
	{
		ApparatusValueSync.EnsureHandlersRegistered();
	}
}
[HarmonyPatch(typeof(GrabbableObject))]
internal static class GrabbableObjectPatch
{
	[HarmonyPostfix]
	[HarmonyPatch("Start")]
	private static void StartPostfix(GrabbableObject __instance)
	{
		if ((Object)(object)__instance == (Object)null || (Object)(object)__instance.itemProperties == (Object)null)
		{
			return;
		}
		string itemName = __instance.itemProperties.itemName;
		Plugin.LogVerbose("Objet détecté : '" + itemName + "' | scrap actuel : " + __instance.scrapValue);
		NetworkObject networkObject = ((NetworkBehaviour)__instance).NetworkObject;
		if ((Object)(object)networkObject == (Object)null)
		{
			Plugin.LogVerbose("Objet sans NetworkObject ignoré : '" + itemName + "'");
			return;
		}
		ulong networkObjectId = networkObject.NetworkObjectId;
		if (Plugin.IsHostOrServer())
		{
			if (ApparatusValueSync.HasAlreadyBeenApplied(networkObjectId))
			{
				return;
			}
			int value;
			bool flag = Plugin.TryGetWantedValue(itemName, out value);
			bool flag2 = Plugin.IsMidasOnlyTrackedItem(itemName);
			if (!flag && !flag2)
			{
				return;
			}
			int scrapValue = __instance.scrapValue;
			if (flag)
			{
				if (__instance.isInShipRoom && Plugin.IsRecognizedTrackedValue(itemName, scrapValue))
				{
					ApparatusValueSync.ApplyValue(__instance, scrapValue);
					ApparatusValueSync.SyncToClients(__instance, scrapValue);
					Plugin.LogInfo("Host: valeur sauvegardée conservée pour '" + itemName + "' => " + scrapValue);
					return;
				}
				int value2 = Plugin.ApplyMidasTouchIfNeeded(value, itemName);
				ApparatusValueSync.ApplyValue(__instance, value2);
				ApparatusValueSync.SyncToClients(__instance, value2);
				Plugin.LogInfo("Host: valeur fixée pour '" + itemName + "' => " + value2 + " (base " + value + ")");
				return;
			}
			if (flag2)
			{
				if (__instance.isInShipRoom && scrapValue > 0)
				{
					ApparatusValueSync.ApplyValue(__instance, scrapValue);
					ApparatusValueSync.SyncToClients(__instance, scrapValue);
					Plugin.LogInfo("Host: valeur sauvegardée conservée pour '" + itemName + "' => " + scrapValue);
					return;
				}
				int num = ((scrapValue > 0) ? scrapValue : 0);
				if (num > 0)
				{
					int value3 = Plugin.ApplyMidasTouchIfNeeded(num, itemName);
					ApparatusValueSync.ApplyValue(__instance, value3);
					ApparatusValueSync.SyncToClients(__instance, value3);
					Plugin.LogInfo("Host: compatibilité Midas-only appliquée pour '" + itemName + "' => " + value3 + " (base détectée " + num + ")");
				}
				return;
			}
		}
		if (Plugin.IsClientOnly())
		{
			ApparatusValueSync.TryApplyPendingValue(__instance);
		}
	}
}
internal static class MidasTouchRuntimePatch
{
	private static bool _installed;

	internal static void Install(Harmony harmony)
	{
		//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c0: Expected O, but got Unknown
		//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01dd: Expected O, but got Unknown
		if (_installed || harmony == null)
		{
			return;
		}
		_installed = true;
		try
		{
			Assembly moreShipUpgradesAssembly = Plugin.GetMoreShipUpgradesAssembly();
			Type midasType = Plugin.GetMidasType();
			Type baseUpgradeType = Plugin.GetBaseUpgradeType();
			Type tierUpgradeType = Plugin.GetTierUpgradeType();
			if (moreShipUpgradesAssembly == null)
			{
				Plugin.LogWarning("Compatibilité Midas Touch: assembly MoreShipUpgrades introuvable pour les patches runtime.");
				return;
			}
			List<MethodInfo> list = new List<MethodInfo>();
			List<MethodInfo> list2 = new List<MethodInfo>();
			Type[] types;
			try
			{
				types = moreShipUpgradesAssembly.GetTypes();
			}
			catch (ReflectionTypeLoadException ex)
			{
				types = ex.Types;
			}
			if (types == null)
			{
				return;
			}
			foreach (Type type in types)
			{
				if (type == null)
				{
					continue;
				}
				bool flag = false;
				if (midasType != null && (type == midasType || midasType.IsAssignableFrom(type)))
				{
					flag = true;
				}
				if (baseUpgradeType != null && (type == baseUpgradeType || baseUpgradeType.IsAssignableFrom(type)))
				{
					flag = true;
				}
				if (tierUpgradeType != null && (type == tierUpgradeType || tierUpgradeType.IsAssignableFrom(type)))
				{
					flag = true;
				}
				if (!flag && type.FullName != null && type.FullName.IndexOf("MidasTouch", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					flag = true;
				}
				if (!flag)
				{
					continue;
				}
				MethodInfo[] methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (MethodInfo methodInfo in methods)
				{
					if (!(methodInfo == null))
					{
						if (string.Equals(methodInfo.Name, "load", StringComparison.OrdinalIgnoreCase) || string.Equals(methodInfo.Name, "Load", StringComparison.OrdinalIgnoreCase))
						{
							list.Add(methodInfo);
						}
						else if (string.Equals(methodInfo.Name, "Increment", StringComparison.OrdinalIgnoreCase))
						{
							list2.Add(methodInfo);
						}
					}
				}
			}
			HarmonyMethod postfix = new HarmonyMethod(typeof(MidasTouchRuntimePatch).GetMethod("LoadPostfix", BindingFlags.Static | BindingFlags.NonPublic));
			HarmonyMethod postfix2 = new HarmonyMethod(typeof(MidasTouchRuntimePatch).GetMethod("IncrementPostfix", BindingFlags.Static | BindingFlags.NonPublic));
			PatchMethodList(harmony, list, postfix, "load");
			PatchMethodList(harmony, list2, postfix2, "Increment");
			if (list.Count == 0)
			{
				Plugin.LogWarning("Compatibilité Midas Touch: aucun load()/Load() pertinent trouvé pour patch runtime.");
			}
			if (list2.Count == 0)
			{
				Plugin.LogWarning("Compatibilité Midas Touch: aucun Increment() pertinent trouvé pour patch runtime.");
			}
		}
		catch (Exception ex2)
		{
			Plugin.LogError("Erreur lors de l'installation des patches runtime Midas Touch: " + ex2);
		}
	}

	private static void PatchMethodList(Harmony harmony, List<MethodInfo> methods, HarmonyMethod postfix, string label)
	{
		if (methods == null || postfix == null)
		{
			return;
		}
		HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
		for (int i = 0; i < methods.Count; i++)
		{
			MethodInfo methodInfo = methods[i];
			if (methodInfo == null || methodInfo.DeclaringType == null)
			{
				continue;
			}
			string item = BuildMethodKey(methodInfo);
			if (!hashSet.Contains(item))
			{
				hashSet.Add(item);
				try
				{
					harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, postfix, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Plugin.LogInfo("Compatibilité Midas Touch: patch runtime installé sur " + methodInfo.DeclaringType.FullName + "." + methodInfo.Name + "()");
				}
				catch (Exception ex)
				{
					Plugin.LogError("Erreur lors du patch runtime sur " + methodInfo.DeclaringType.FullName + "." + methodInfo.Name + "(): " + ex);
				}
			}
		}
	}

	private static string BuildMethodKey(MethodInfo method)
	{
		ParameterInfo[] parameters = method.GetParameters();
		string[] array = new string[parameters.Length];
		for (int i = 0; i < parameters.Length; i++)
		{
			array[i] = parameters[i].ParameterType.FullName;
		}
		return method.DeclaringType.FullName + "::" + method.Name + "(" + string.Join(",", array) + ")";
	}

	private static void LoadPostfix(object __instance)
	{
		try
		{
			Plugin.NotifyMidasLoad(__instance);
		}
		catch (Exception ex)
		{
			Plugin.LogError("Erreur dans le postfix runtime load()/Load() de Midas Touch: " + ex);
		}
	}

	private static void IncrementPostfix(object __instance)
	{
		try
		{
			Plugin.NotifyMidasIncrement(__instance);
		}
		catch (Exception ex)
		{
			Plugin.LogError("Erreur dans le postfix runtime Increment() de Midas Touch: " + ex);
		}
	}
}
[BepInPlugin("lc.mod.customapparatusvalues", "Custom Apparatus Values", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
	public const string ModGuid = "lc.mod.customapparatusvalues";

	public const string ModName = "Custom Apparatus Values";

	public const string ModVersion = "1.0.0";

	internal static Plugin Instance = null;

	internal static Harmony Harmony = null;

	internal static ConfigEntry<int> ApparatusValue = null;

	internal static ConfigEntry<int> PlasmaApparatusValue = null;

	internal static ConfigEntry<int> PinkApparatusValue = null;

	internal static ConfigEntry<int> HauntedApparatusValue = null;

	internal static ConfigEntry<int> ToxicApparatusValue = null;

	internal static ConfigEntry<int> BeholderEyeValue = null;

	internal static ConfigEntry<int> ThePaintingValue = null;

	internal static ConfigEntry<int> PowerStarValue = null;

	internal static ConfigEntry<int> BloodyApparatusValue = null;

	internal static ConfigEntry<int> CosmicApparatusValue = null;

	internal static ConfigEntry<int> RoyalApparatusValue = null;

	internal static ConfigEntry<int> SoulOrbValue = null;

	internal static ConfigEntry<bool> EnableVerboseLogs = null;

	internal static ConfigEntry<bool> EnableMidasTouchCompatibility = null;

	private static Assembly _moreShipUpgradesAssembly = null;

	private static Type _midasType = null;

	private static Type _baseUpgradeType = null;

	private static Type _tierUpgradeType = null;

	private static MethodInfo _assemblyGetUpgradeLevelMethod = null;

	private static bool _midasReflectionInitialized = false;

	private static readonly string[] _midasCandidates = new string[5] { "Midas Touch", "MidasTouch", "midas", "midas touch", "MoreShipUpgrades.UpgradeComponents.TierUpgrades.Ship.MidasTouch" };

	private static readonly HashSet<string> MidasOnlyItems = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "Human heart" };

	private static int _cachedMidasLevel = -1;

	internal static readonly Dictionary<string, Func<int>> TargetValues = new Dictionary<string, Func<int>>(StringComparer.OrdinalIgnoreCase)
	{
		{
			"Apparatus",
			() => ApparatusValue.Value
		},
		{
			"Plasma apparatus",
			() => PlasmaApparatusValue.Value
		},
		{
			"Pink Apparatus",
			() => PinkApparatusValue.Value
		},
		{
			"Haunted apparatus",
			() => HauntedApparatusValue.Value
		},
		{
			"Toxic Apparatus",
			() => ToxicApparatusValue.Value
		},
		{
			"Beholder's eye",
			() => BeholderEyeValue.Value
		},
		{
			"The painting",
			() => ThePaintingValue.Value
		},
		{
			"Power Star",
			() => PowerStarValue.Value
		},
		{
			"Bloody apparatus",
			() => BloodyApparatusValue.Value
		},
		{
			"Cosmic apparatus",
			() => CosmicApparatusValue.Value
		},
		{
			"Royal apparatus",
			() => RoyalApparatusValue.Value
		},
		{
			"Soul orb",
			() => SoulOrbValue.Value
		}
	};

	private void Awake()
	{
		//IL_0200: Unknown result type (might be due to invalid IL or missing references)
		//IL_020a: Expected O, but got Unknown
		Instance = this;
		ApparatusValue = ((BaseUnityPlugin)this).Config.Bind<int>("Values", "Apparatus", 200, "Valeur de l'Apparatus vanilla.");
		PlasmaApparatusValue = ((BaseUnityPlugin)this).Config.Bind<int>("Values", "PlasmaApparatus", 240, "Valeur du Plasma apparatus (Greenhouse).");
		PinkApparatusValue = ((BaseUnityPlugin)this).Config.Bind<int>("Values", "PinkApparatus", 210, "Valeur du Pink Apparatus (Toy Store).");
		HauntedApparatusValue = ((BaseUnityPlugin)this).Config.Bind<int>("Values", "HauntedApparatus", 225, "Valeur du Haunted apparatus (Rubber Rooms).");
		ToxicApparatusValue = ((BaseUnityPlugin)this).Config.Bind<int>("Values", "ToxicApparatus", 280, "Valeur du Toxic Apparatus (Grand Armory).");
		BeholderEyeValue = ((BaseUnityPlugin)this).Config.Bind<int>("Values", "BeholdersEye", 320, "Valeur du Beholder's eye (Atlantean Citadel).");
		ThePaintingValue = ((BaseUnityPlugin)this).Config.Bind<int>("Values", "ThePainting", 400, "Valeur de The painting (Art Gallery).");
		PowerStarValue = ((BaseUnityPlugin)this).Config.Bind<int>("Values", "PowerStar", 200, "Valeur du Power Star.");
		BloodyApparatusValue = ((BaseUnityPlugin)this).Config.Bind<int>("Values", "BloodyApparatus", 300, "Valeur du Bloody apparatus.");
		CosmicApparatusValue = ((BaseUnityPlugin)this).Config.Bind<int>("Values", "CosmicApparatus", 1600, "Valeur du Cosmic apparatus.");
		RoyalApparatusValue = ((BaseUnityPlugin)this).Config.Bind<int>("Values", "RoyalApparatus", 400, "Valeur du Royal apparatus.");
		SoulOrbValue = ((BaseUnityPlugin)this).Config.Bind<int>("Values", "SoulOrb", 2000, "Valeur du Soul orb.");
		EnableVerboseLogs = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "EnableVerboseLogs", true, "Active les logs détaillés.");
		EnableMidasTouchCompatibility = ((BaseUnityPlugin)this).Config.Bind<bool>("Compatibility", "EnableMidasTouchCompatibility", true, "Applique Midas Touch après la valeur de base du générateur.");
		InitializeMidasReflection();
		Harmony = new Harmony("lc.mod.customapparatusvalues");
		Harmony.PatchAll();
		MidasTouchRuntimePatch.Install(Harmony);
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Custom Apparatus Values chargé.");
	}

	internal static void ResetRuntimeState()
	{
		_cachedMidasLevel = -1;
		LogVerbose("Etat runtime Midas Touch réinitialisé.");
	}

	internal static bool TryGetWantedValue(string itemName, out int value)
	{
		value = 0;
		if (string.IsNullOrWhiteSpace(itemName))
		{
			return false;
		}
		string key = itemName.Trim();
		if (!TargetValues.TryGetValue(key, out var value2))
		{
			return false;
		}
		value = value2();
		return true;
	}

	internal static bool IsMidasOnlyTrackedItem(string itemName)
	{
		if (string.IsNullOrWhiteSpace(itemName))
		{
			return false;
		}
		return MidasOnlyItems.Contains(itemName.Trim());
	}

	internal static bool IsTrackedItem(string itemName)
	{
		if (IsMidasOnlyTrackedItem(itemName))
		{
			return true;
		}
		int value;
		return TryGetWantedValue(itemName, out value);
	}

	internal static bool IsRecognizedTrackedValue(string itemName, int currentValue)
	{
		if (currentValue <= 0)
		{
			return false;
		}
		if (!TryGetWantedValue(itemName, out var value))
		{
			return false;
		}
		for (int i = 0; i <= 5; i++)
		{
			if (((i <= 0) ? value : Mathf.RoundToInt((float)value * (1f + 0.2f * (float)i))) == currentValue)
			{
				return true;
			}
		}
		return false;
	}

	internal static bool IsHostOrServer()
	{
		if ((Object)(object)NetworkManager.Singleton == (Object)null)
		{
			return false;
		}
		return NetworkManager.Singleton.IsServer;
	}

	internal static bool IsClientOnly()
	{
		if ((Object)(object)NetworkManager.Singleton == (Object)null)
		{
			return false;
		}
		if (NetworkManager.Singleton.IsClient)
		{
			return !NetworkManager.Singleton.IsServer;
		}
		return false;
	}

	internal static void LogInfo(string message)
	{
		if ((Object)(object)Instance != (Object)null)
		{
			((BaseUnityPlugin)Instance).Logger.LogInfo((object)message);
		}
	}

	internal static void LogWarning(string message)
	{
		if ((Object)(object)Instance != (Object)null)
		{
			((BaseUnityPlugin)Instance).Logger.LogWarning((object)message);
		}
	}

	internal static void LogError(string message)
	{
		if ((Object)(object)Instance != (Object)null)
		{
			((BaseUnityPlugin)Instance).Logger.LogError((object)message);
		}
	}

	internal static void LogVerbose(string message)
	{
		if ((Object)(object)Instance != (Object)null && EnableVerboseLogs.Value)
		{
			((BaseUnityPlugin)Instance).Logger.LogInfo((object)message);
		}
	}

	internal static Type FindTypeInLoadedAssemblies(string fullName)
	{
		if (string.IsNullOrWhiteSpace(fullName))
		{
			return null;
		}
		Type type = Type.GetType(fullName);
		if (type != null)
		{
			return type;
		}
		type = AccessTools.TypeByName(fullName);
		if (type != null)
		{
			return type;
		}
		Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
		foreach (Assembly assembly in assemblies)
		{
			if (!(assembly == null))
			{
				type = assembly.GetType(fullName, throwOnError: false);
				if (type != null)
				{
					return type;
				}
			}
		}
		return null;
	}

	internal static Assembly GetMoreShipUpgradesAssembly()
	{
		return _moreShipUpgradesAssembly;
	}

	internal static Type GetMidasType()
	{
		return _midasType;
	}

	internal static Type GetBaseUpgradeType()
	{
		return _baseUpgradeType;
	}

	internal static Type GetTierUpgradeType()
	{
		return _tierUpgradeType;
	}

	private static MethodInfo FindMethodInAssembly(Assembly assembly, string methodName)
	{
		if (assembly == null || string.IsNullOrWhiteSpace(methodName))
		{
			return null;
		}
		Type[] types;
		try
		{
			types = assembly.GetTypes();
		}
		catch (ReflectionTypeLoadException ex)
		{
			types = ex.Types;
		}
		if (types == null)
		{
			return null;
		}
		foreach (Type type in types)
		{
			if (type == null)
			{
				continue;
			}
			MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (MethodInfo methodInfo in methods)
			{
				if (!(methodInfo == null) && string.Equals(methodInfo.Name, methodName, StringComparison.Ordinal))
				{
					return methodInfo;
				}
			}
		}
		return null;
	}

	private static string GetMethodSignature(MethodInfo method)
	{
		if (method == null)
		{
			return "<null>";
		}
		ParameterInfo[] parameters = method.GetParameters();
		string[] array = new string[parameters.Length];
		for (int i = 0; i < parameters.Length; i++)
		{
			array[i] = parameters[i].ParameterType.Name + " " + parameters[i].Name;
		}
		string text = ((method.DeclaringType != null) ? method.DeclaringType.FullName : "<no declaring type>");
		string text2 = (method.IsStatic ? "static " : "instance ");
		return text + " :: " + text2 + method.ReturnType.Name + " " + method.Name + "(" + string.Join(", ", array) + ")";
	}

	private static void InitializeMidasReflection()
	{
		if (_midasReflectionInitialized)
		{
			return;
		}
		_midasReflectionInitialized = true;
		try
		{
			_midasType = FindTypeInLoadedAssemblies("MoreShipUpgrades.UpgradeComponents.TierUpgrades.Ship.MidasTouch");
			_baseUpgradeType = FindTypeInLoadedAssemblies("MoreShipUpgrades.Misc.Upgrades.BaseUpgrade");
			_tierUpgradeType = FindTypeInLoadedAssemblies("MoreShipUpgrades.Misc.Upgrades.TierUpgrade");
			if (_midasType == null)
			{
				LogWarning("Compatibilité Midas Touch: type MidasTouch introuvable.");
				return;
			}
			_moreShipUpgradesAssembly = _midasType.Assembly;
			LogInfo("Compatibilité Midas Touch: type MidasTouch trouvé: " + _midasType.FullName);
			LogInfo("Compatibilité Midas Touch: assembly détecté: " + _moreShipUpgradesAssembly.GetName().Name);
			_assemblyGetUpgradeLevelMethod = FindMethodInAssembly(_moreShipUpgradesAssembly, "GetUpgradeLevel");
			if (_assemblyGetUpgradeLevelMethod != null)
			{
				LogInfo("Compatibilité Midas Touch: méthode GetUpgradeLevel trouvée.");
				LogInfo("Signature trouvée: " + GetMethodSignature(_assemblyGetUpgradeLevelMethod));
			}
			else
			{
				LogWarning("Compatibilité Midas Touch: méthode GetUpgradeLevel introuvable.");
			}
		}
		catch (Exception ex)
		{
			LogError("Erreur lors de l'initialisation de la compatibilité Midas Touch: " + ex);
		}
	}

	private static bool TryExtractInt(object value, out int intValue)
	{
		intValue = 0;
		if (value == null)
		{
			return false;
		}
		if (value is int)
		{
			intValue = (int)value;
			return true;
		}
		return int.TryParse(value.ToString(), out intValue);
	}

	private static bool TryGetRawMidasUpgradeLevel(out int rawLevel)
	{
		rawLevel = -1;
		if (_assemblyGetUpgradeLevelMethod == null)
		{
			return false;
		}
		try
		{
			ParameterInfo[] parameters = _assemblyGetUpgradeLevelMethod.GetParameters();
			if (parameters.Length != 1 || parameters[0].ParameterType != typeof(string))
			{
				return false;
			}
			int num = int.MinValue;
			bool flag = false;
			for (int i = 0; i < _midasCandidates.Length; i++)
			{
				string text = _midasCandidates[i];
				if (TryExtractInt(_assemblyGetUpgradeLevelMethod.Invoke(null, new object[1] { text }), out var intValue))
				{
					flag = true;
					LogVerbose("GetUpgradeLevel(\"" + text + "\") => " + intValue);
					if (intValue > num)
					{
						num = intValue;
					}
				}
			}
			if (!flag)
			{
				return false;
			}
			rawLevel = num;
			LogVerbose("Niveau Midas Touch brut retenu via GetUpgradeLevel = " + rawLevel);
			return true;
		}
		catch (Exception ex)
		{
			LogError("Erreur lors de GetUpgradeLevel pour Midas Touch: " + ex);
			return false;
		}
	}

	internal static bool IsMidasTouchInstance(object instance)
	{
		if (instance == null || _midasType == null)
		{
			return false;
		}
		Type type = instance.GetType();
		if (_midasType.IsAssignableFrom(type))
		{
			return true;
		}
		if (type.FullName != null && type.FullName.IndexOf("MidasTouch", StringComparison.OrdinalIgnoreCase) >= 0)
		{
			return true;
		}
		return false;
	}

	internal static void NotifyMidasLoad(object instance)
	{
		if (!IsMidasTouchInstance(instance))
		{
			return;
		}
		if (TryGetRawMidasUpgradeLevel(out var rawLevel))
		{
			if (rawLevel >= 1)
			{
				_cachedMidasLevel = rawLevel + 1;
				if (_cachedMidasLevel > 5)
				{
					_cachedMidasLevel = 5;
				}
				LogInfo("Compatibilité Midas Touch: niveau restauré via load() => " + _cachedMidasLevel);
			}
			else
			{
				_cachedMidasLevel = 1;
				LogInfo("Compatibilité Midas Touch: rang 1 détecté via load().");
			}
		}
		else
		{
			if (_cachedMidasLevel < 1)
			{
				_cachedMidasLevel = 1;
			}
			LogInfo("Compatibilité Midas Touch: fallback rang 1 via load().");
		}
	}

	internal static void NotifyMidasIncrement(object instance)
	{
		if (IsMidasTouchInstance(instance))
		{
			if (TryGetRawMidasUpgradeLevel(out var rawLevel) && rawLevel >= 1)
			{
				_cachedMidasLevel = rawLevel + 1;
			}
			else if (_cachedMidasLevel < 1)
			{
				_cachedMidasLevel = 2;
			}
			else
			{
				_cachedMidasLevel = Mathf.Min(_cachedMidasLevel + 1, 5);
			}
			LogInfo("Compatibilité Midas Touch: rang détecté via Increment() => " + _cachedMidasLevel);
		}
	}

	private static bool TryResolveMidasTouchLevel(out int level)
	{
		level = 0;
		if (_cachedMidasLevel > 0)
		{
			level = _cachedMidasLevel;
			LogVerbose("Résolution niveau Midas Touch via cache runtime = " + level);
			return true;
		}
		if (!TryGetRawMidasUpgradeLevel(out var rawLevel))
		{
			return false;
		}
		if (rawLevel >= 1)
		{
			level = rawLevel + 1;
			if (level > 5)
			{
				level = 5;
			}
			if (_cachedMidasLevel < level)
			{
				_cachedMidasLevel = level;
			}
			LogVerbose("Résolution niveau Midas Touch via GetUpgradeLevel : rawLevel = " + rawLevel + ", niveau final = " + level);
			return true;
		}
		level = 0;
		LogVerbose("Résolution niveau Midas Touch : aucun achat détecté (rawLevel = " + rawLevel + ")");
		return true;
	}

	internal static int ApplyMidasTouchIfNeeded(int baseValue, string itemName)
	{
		if (!EnableMidasTouchCompatibility.Value)
		{
			return baseValue;
		}
		if (!_midasReflectionInitialized)
		{
			InitializeMidasReflection();
		}
		if (TryResolveMidasTouchLevel(out var level))
		{
			if (level <= 0)
			{
				LogVerbose("Midas Touch non acheté pour '" + itemName + "' | niveau = " + level + " | valeur conservée = " + baseValue);
				return baseValue;
			}
			float num = 1f + 0.2f * (float)level;
			int result = Mathf.RoundToInt((float)baseValue * num);
			LogVerbose("Midas Touch appliqué à '" + itemName + "' | niveau = " + level + " | base = " + baseValue + " | multiplicateur = " + num.ToString("0.###") + " | final = " + result);
			return result;
		}
		return baseValue;
	}
}