Decompiled source of BetterArmoryFix v2.4.1

BetterArmoryFix.dll

Decompiled 2 months ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Unity.Netcode;
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("BetterArmoryFix")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("BetterArmoryFix")]
[assembly: AssemblyTitle("BetterArmoryFix")]
[assembly: AssemblyVersion("1.0.0.0")]
[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 BetterArmoryFix
{
	[BepInPlugin("local.betterarmoryfix", "BetterArmory Fix", "2.4.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "local.betterarmoryfix";

		public const string Version = "2.4.1";

		internal static ManualLogSource Log;

		private void Awake()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Harmony val = new Harmony("local.betterarmoryfix");
			val.PatchAll(Assembly.GetExecutingAssembly());
			Log.LogInfo((object)"BetterArmoryFix cargado. Revisando qué parches lograron engancharse...");
			StartupDiagnostics.ReportAll();
		}
	}
	internal static class StartupDiagnostics
	{
		public static void ReportAll()
		{
			Check("Y4NGZUpgrades.Weapons.FlamethrowerStreamDriver", "RegisterNetworkHandlers");
			Check("Y4NGZUpgrades.Weapons.FlamethrowerStreamDriver", "SetLocalUse");
			Check("Y4NGZUpgrades.Weapons.FlamethrowerStreamDriver", "SendUse");
			Check("Y4NGZUpgrades.Weapons.FlamethrowerStreamDriver", "ServerSetUse");
			Check("Y4NGZUpgrades.Weapons.FlamethrowerStreamDriver", "SenderOwnsHeldWeapon");
			Check("Y4NGZUpgrades.Weapons.FlamethrowerStreamDriver", "ServerHolderValid");
			Check("Y4NGZUpgrades.Weapons.Patches.FlamethrowerPatches", "ItemActivate_Prefix");
			Check("Y4NGZUpgrades.Weapons.Y4NGZWeaponItem", "get_Shotgun");
			Check("MoreShipUpgrades.Managers.LguStore", "UpdateUpgradeBus");
			Check("GrabbableObject", "Start");
			Check("GameNetcodeStuff.PlayerControllerB", "SwitchToItemSlot");
		}

		private static void Check(string typeName, string methodName)
		{
			Type type = AccessTools.TypeByName(typeName);
			if (type == null)
			{
				Plugin.Log.LogWarning((object)("[BetterArmoryFix][STARTUP] Clase NO encontrada: " + typeName + " (mod ausente o cambió de nombre)"));
				return;
			}
			MethodInfo methodInfo = AccessTools.Method(type, methodName, (Type[])null, (Type[])null);
			Plugin.Log.LogInfo((object)("[BetterArmoryFix][STARTUP] " + typeName + "." + methodName + " -> " + ((methodInfo != null) ? "encontrado (OK)" : "NO ENCONTRADO (¡revisar!)")));
		}
	}
	[HarmonyPatch]
	public static class FlamethrowerRegisterHandlersPatch
	{
		private static CustomMessagingManager _lastSeenMessagingManager;

		private static FieldInfo _registeredManagerField;

		private static bool _resolvedOnce;

		public static MethodBase TargetMethod()
		{
			Type type = AccessTools.TypeByName("Y4NGZUpgrades.Weapons.FlamethrowerStreamDriver");
			return (type == null) ? null : AccessTools.Method(type, "RegisterNetworkHandlers", (Type[])null, (Type[])null);
		}

		public static void Prefix()
		{
			NetworkManager singleton = NetworkManager.Singleton;
			if (!((Object)(object)singleton == (Object)null))
			{
				CustomMessagingManager customMessagingManager = singleton.CustomMessagingManager;
				if (customMessagingManager != null && customMessagingManager != _lastSeenMessagingManager)
				{
					ResetFlamethrowerNetworkRegistration();
					_lastSeenMessagingManager = customMessagingManager;
				}
			}
		}

		private static void ResetFlamethrowerNetworkRegistration()
		{
			if (!_resolvedOnce)
			{
				Type type = AccessTools.TypeByName("Y4NGZUpgrades.Weapons.FlamethrowerStreamDriver");
				_registeredManagerField = AccessTools.Field(type, "_registeredMessaging") ?? AccessTools.Field(type, "_registeredManager");
				_resolvedOnce = true;
				if (_registeredManagerField == null)
				{
					Plugin.Log.LogWarning((object)"[BetterArmoryFix] No encontré _registeredMessaging ni _registeredManager en FlamethrowerStreamDriver. Este respaldo no podrá actuar (probablemente no haga falta si BetterArmory ya trae su propio fix).");
				}
			}
			if (!(_registeredManagerField == null))
			{
				_registeredManagerField.SetValue(null, null);
				Plugin.Log.LogInfo((object)"[BetterArmoryFix] Nuevo CustomMessagingManager detectado (reconexión). Forzando re-registro de los handlers del lanzallamas (respaldo).");
			}
		}
	}
	[HarmonyPatch]
	public static class ShotgunGetterSafetyPatch
	{
		private static bool _loggedOnce;

		public static MethodBase TargetMethod()
		{
			Type type = AccessTools.TypeByName("Y4NGZUpgrades.Weapons.Y4NGZWeaponItem");
			return (type == null) ? null : AccessTools.Method(type, "get_Shotgun", (Type[])null, (Type[])null);
		}

		[HarmonyFinalizer]
		public static Exception Finalizer(Exception __exception, ref object __result)
		{
			if (__exception != null)
			{
				__result = null;
				if (!_loggedOnce)
				{
					_loggedOnce = true;
					Plugin.Log.LogInfo((object)"[BetterArmoryFix] Contuve un crash en Y4NGZWeaponItem.get_Shotgun() (arma con referencia obsoleta). Devolviendo null de forma segura. (Este aviso solo se muestra una vez por sesión.)");
				}
			}
			return null;
		}
	}
	[HarmonyPatch]
	public static class SetLocalUseDiagnosticPatch
	{
		public static MethodBase TargetMethod()
		{
			Type type = AccessTools.TypeByName("Y4NGZUpgrades.Weapons.FlamethrowerStreamDriver");
			return (type == null) ? null : AccessTools.Method(type, "SetLocalUse", (Type[])null, (Type[])null);
		}

		public static void Prefix(object __instance, bool firing)
		{
			if (!firing)
			{
				return;
			}
			try
			{
				Type type = __instance.GetType();
				object obj = AccessTools.Field(type, "_shotgun")?.GetValue(__instance);
				if (obj == null)
				{
					Plugin.Log.LogInfo((object)"[BetterArmoryFix][DIAG] Intento de disparo con _shotgun == null.");
					return;
				}
				Type type2 = obj.GetType();
				object obj2 = AccessTools.Field(type2, "shellsLoaded")?.GetValue(obj);
				object obj3 = AccessTools.Method(type, "IsEquippedAndAlive", (Type[])null, (Type[])null)?.Invoke(__instance, null);
				object obj4 = AccessTools.Field(type, "_localReloading")?.GetValue(__instance);
				object obj5 = AccessTools.Method(type, "IsLocalHolder", (Type[])null, (Type[])null)?.Invoke(__instance, null);
				string text = "N/A";
				string text2 = "N/A";
				try
				{
					object obj6 = AccessTools.Field(type2, "playerHeldBy")?.GetValue(obj);
					text = ((obj6 == null) ? "null" : (AccessTools.Field(obj6.GetType(), "playerUsername")?.GetValue(obj6)?.ToString() ?? obj6.ToString()));
					Type type3 = AccessTools.TypeByName("GameNetworkManager");
					object obj7 = AccessTools.PropertyGetter(type3, "Instance")?.Invoke(null, null);
					object obj8 = ((obj7 == null) ? null : AccessTools.Field(type3, "localPlayerController")?.GetValue(obj7));
					text2 = ((obj8 == null) ? "null" : (AccessTools.Field(obj8.GetType(), "playerUsername")?.GetValue(obj8)?.ToString() ?? obj8.ToString()));
				}
				catch
				{
				}
				string text3 = "N/A";
				string text4 = "N/A";
				string text5 = "N/A";
				try
				{
					object obj10 = AccessTools.Property(AccessTools.TypeByName("Unity.Netcode.NetworkBehaviour"), "NetworkObject")?.GetValue(obj);
					if (obj10 != null)
					{
						text3 = AccessTools.Property(obj10.GetType(), "NetworkObjectId")?.GetValue(obj10)?.ToString() ?? "N/A";
						text5 = AccessTools.Property(obj10.GetType(), "OwnerClientId")?.GetValue(obj10)?.ToString() ?? "N/A";
					}
					text4 = AccessTools.Property(type2, "IsOwner")?.GetValue(obj)?.ToString() ?? "N/A";
				}
				catch
				{
				}
				Plugin.Log.LogInfo((object)("[BetterArmoryFix][DIAG] Intento de disparo -> shellsLoaded=" + obj2?.ToString() + ", IsEquippedAndAlive=" + obj3?.ToString() + ", IsLocalHolder=" + obj5?.ToString() + ", playerHeldBy=" + text + ", localPlayer=" + text2 + ", _localReloading=" + obj4?.ToString() + ", NetworkObjectId=" + text3 + ", IsOwner=" + text4 + ", OwnerClientId=" + text5));
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[BetterArmoryFix][DIAG] No se pudo leer el diagnóstico: " + ex.Message));
			}
		}
	}
	[HarmonyPatch]
	public static class ItemActivateDiagnosticPatch
	{
		public static MethodBase TargetMethod()
		{
			Type type = AccessTools.TypeByName("Y4NGZUpgrades.Weapons.Patches.FlamethrowerPatches");
			return (type == null) ? null : AccessTools.Method(type, "ItemActivate_Prefix", (Type[])null, (Type[])null);
		}

		public static void Prefix(object __instance, bool buttonDown)
		{
			if (!buttonDown)
			{
				return;
			}
			try
			{
				object obj = null;
				bool flag = false;
				string text = null;
				try
				{
					obj = (typeof(Component).GetMethod("GetComponent", Type.EmptyTypes)?.MakeGenericMethod(AccessTools.TypeByName("Y4NGZUpgrades.Weapons.FlamethrowerStreamDriver")))?.Invoke(__instance, null);
				}
				catch (Exception ex)
				{
					flag = true;
					text = ex.InnerException?.Message ?? ex.Message;
				}
				bool flag2 = obj != null;
				Plugin.Log.LogInfo((object)("[BetterArmoryFix][DIAG2] Clic en ShotgunItem -> GetComponent<FlamethrowerStreamDriver>() " + (flag ? ("LANZÓ EXCEPCIÓN: " + text) : (flag2 ? "encontrado (OK)" : "devolvió NULL (bug probable)"))));
			}
			catch (Exception ex2)
			{
				Plugin.Log.LogWarning((object)("[BetterArmoryFix][DIAG2] No se pudo leer el diagnóstico: " + ex2.Message));
			}
		}
	}
	[HarmonyPatch]
	public static class SendUseDiagnosticPatch
	{
		public static MethodBase TargetMethod()
		{
			Type type = AccessTools.TypeByName("Y4NGZUpgrades.Weapons.FlamethrowerStreamDriver");
			return (type == null) ? null : AccessTools.Method(type, "SendUse", (Type[])null, (Type[])null);
		}

		public static void Prefix(bool firing)
		{
			try
			{
				NetworkManager singleton = NetworkManager.Singleton;
				CustomMessagingManager val = ((singleton != null) ? singleton.CustomMessagingManager : null);
				Plugin.Log.LogInfo((object)("[BetterArmoryFix][DIAG3] SendUse(firing=" + firing + ") -> NetworkManager.Singleton=" + (((Object)(object)singleton == (Object)null) ? "null" : "OK") + ", CustomMessagingManager=" + ((val == null) ? "null (¡acá estaría el problema!)" : ("OK (hash=" + ((object)val).GetHashCode() + ")")) + ", LocalClientId=" + (((singleton != null) ? singleton.LocalClientId.ToString() : null) ?? "N/A")));
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[BetterArmoryFix][DIAG3] No se pudo leer el diagnóstico: " + ex.Message));
			}
		}
	}
	[HarmonyPatch]
	public static class ServerSetUseDiagnosticPatch
	{
		public static MethodBase TargetMethod()
		{
			Type type = AccessTools.TypeByName("Y4NGZUpgrades.Weapons.FlamethrowerStreamDriver");
			return (type == null) ? null : AccessTools.Method(type, "ServerSetUse", (Type[])null, (Type[])null);
		}

		public static void Prefix(object __instance, ulong senderClientId, bool firing)
		{
			if (!firing)
			{
				return;
			}
			try
			{
				Type type = __instance.GetType();
				object obj = AccessTools.Method(type, "SenderOwnsHeldWeapon", (Type[])null, (Type[])null)?.Invoke(__instance, new object[1] { senderClientId });
				object obj2 = AccessTools.Method(type, "ServerHolderValid", (Type[])null, (Type[])null)?.Invoke(__instance, null);
				object obj3 = AccessTools.Field(type, "_shotgun")?.GetValue(__instance);
				string text = "N/A";
				string text2 = "N/A";
				string text3 = "N/A";
				string text4 = "N/A";
				string text5 = "N/A";
				if (obj3 != null)
				{
					Type type2 = obj3.GetType();
					object obj4 = AccessTools.Field(type2, "playerHeldBy")?.GetValue(obj3);
					text2 = AccessTools.Field(type2, "isHeld")?.GetValue(obj3)?.ToString() ?? "N/A";
					text3 = AccessTools.Field(type2, "isPocketed")?.GetValue(obj3)?.ToString() ?? "N/A";
					if (obj4 != null)
					{
						Type type3 = obj4.GetType();
						text = AccessTools.Field(type3, "playerClientId")?.GetValue(obj4)?.ToString() ?? "N/A";
						text4 = AccessTools.Field(type3, "isPlayerDead")?.GetValue(obj4)?.ToString() ?? "N/A";
						object obj5 = AccessTools.Field(type3, "currentlyHeldObjectServer")?.GetValue(obj4);
						text5 = ((obj5 == obj3) ? "True" : "False");
					}
					else
					{
						text = "null (¡nadie sostiene el arma según el host!)";
					}
					Plugin.Log.LogInfo((object)("[BetterArmoryFix][DIAG4-HOST] ServerSetUse recibido de clientId=" + senderClientId + " -> SenderOwnsHeldWeapon=" + obj?.ToString() + ", ServerHolderValid=" + obj2?.ToString() + ", playerHeldBy.playerClientId=" + text + " (¿coincide con sender? " + (text == senderClientId.ToString()) + "), isHeld=" + text2 + ", isPocketed=" + text3 + ", isPlayerDead=" + text4 + ", currentlyHeldObjectServer==_shotgun=" + text5));
				}
				else
				{
					Plugin.Log.LogInfo((object)("[BetterArmoryFix][DIAG4-HOST] ServerSetUse recibido de clientId=" + senderClientId + " pero _shotgun == null en el servidor."));
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[BetterArmoryFix][DIAG4-HOST] No se pudo leer el diagnóstico: " + ex.Message));
			}
		}
	}
	[HarmonyPatch]
	public static class LguStoreUseHostSaveDataPatch
	{
		private static FieldInfo _playerIdField;

		private static ulong _originalPlayerId;

		private static bool _didSwap;

		public static MethodBase TargetMethod()
		{
			Type type = AccessTools.TypeByName("MoreShipUpgrades.Managers.LguStore");
			return (type == null) ? null : AccessTools.Method(type, "UpdateUpgradeBus", (Type[])null, (Type[])null);
		}

		public static void Prefix(object __instance, bool UseLocalSteamID)
		{
			_didSwap = false;
			Plugin.Log.LogInfo((object)("[BetterArmoryFix][DIAG-LGU] UpdateUpgradeBus llamado con UseLocalSteamID=" + UseLocalSteamID));
			if (!UseLocalSteamID)
			{
				return;
			}
			try
			{
				bool flag = IsHost();
				Plugin.Log.LogInfo((object)("[BetterArmoryFix][DIAG-LGU] IsHost=" + flag));
				if (flag)
				{
					return;
				}
				string trace;
				ulong? hostSteamId = GetHostSteamId(out trace);
				Plugin.Log.LogInfo((object)("[BetterArmoryFix][DIAG-LGU] Búsqueda de SteamID del host: " + trace));
				if (!hostSteamId.HasValue)
				{
					Plugin.Log.LogWarning((object)"[BetterArmoryFix][DIAG-LGU] No pude determinar el SteamID del host; no se pudo forzar la sincronización de stats.");
					return;
				}
				Type type = __instance.GetType();
				if (_playerIdField == null)
				{
					_playerIdField = AccessTools.Field(type, "playerID");
				}
				if (_playerIdField == null)
				{
					Plugin.Log.LogWarning((object)"[BetterArmoryFix][DIAG-LGU] No encontré el campo 'playerID' en LguStore.");
					return;
				}
				_originalPlayerId = (ulong)_playerIdField.GetValue(__instance);
				Plugin.Log.LogInfo((object)("[BetterArmoryFix][DIAG-LGU] playerID propio=" + _originalPlayerId + ", SteamID host=" + hostSteamId.Value));
				if (_originalPlayerId != hostSteamId.Value)
				{
					_playerIdField.SetValue(__instance, hostSteamId.Value);
					_didSwap = true;
					Plugin.Log.LogInfo((object)("[BetterArmoryFix] Forzando que el cliente cargue las stats del host (SteamID host=" + hostSteamId.Value + ") en vez de su copia personal."));
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[BetterArmoryFix][DIAG-LGU] No se pudo forzar la sincronización de stats con el host: " + ex));
			}
		}

		public static void Postfix(object __instance)
		{
			if (_didSwap)
			{
				try
				{
					_playerIdField.SetValue(__instance, _originalPlayerId);
				}
				catch
				{
				}
				_didSwap = false;
			}
		}

		private static bool IsHost()
		{
			Type type = AccessTools.TypeByName("Unity.Netcode.NetworkManager");
			object obj = AccessTools.PropertyGetter(type, "Singleton")?.Invoke(null, null);
			if (obj == null)
			{
				return false;
			}
			object obj2 = AccessTools.Property(type, "IsHost")?.GetValue(obj);
			bool flag = default(bool);
			int num;
			if (obj2 is bool)
			{
				flag = (bool)obj2;
				num = 1;
			}
			else
			{
				num = 0;
			}
			return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
		}

		private static ulong? GetHostSteamId(out string trace)
		{
			StringBuilder stringBuilder = new StringBuilder();
			try
			{
				Type type = AccessTools.TypeByName("GameNetworkManager");
				object obj = AccessTools.PropertyGetter(type, "Instance")?.Invoke(null, null);
				stringBuilder.Append("GameNetworkManager.Instance=" + ((obj != null) ? "OK" : "null") + "; ");
				if (obj == null)
				{
					trace = stringBuilder.ToString();
					return null;
				}
				object obj2 = AccessTools.Property(type, "currentLobby")?.GetValue(obj);
				stringBuilder.Append("currentLobby=" + ((obj2 != null) ? "OK" : "null") + "; ");
				if (obj2 == null)
				{
					trace = stringBuilder.ToString();
					return null;
				}
				Type type2 = obj2.GetType();
				object obj3 = AccessTools.Property(type2, "Owner")?.GetValue(obj2);
				stringBuilder.Append("Owner=" + ((obj3 != null) ? "OK" : "null") + "; ");
				if (obj3 == null)
				{
					trace = stringBuilder.ToString();
					return null;
				}
				Type type3 = obj3.GetType();
				object obj4 = AccessTools.Property(type3, "Id")?.GetValue(obj3);
				stringBuilder.Append("Id=" + ((obj4 != null) ? "OK" : "null") + "; ");
				if (obj4 == null)
				{
					trace = stringBuilder.ToString();
					return null;
				}
				Type type4 = obj4.GetType();
				FieldInfo fieldInfo = AccessTools.Field(type4, "Value");
				if (fieldInfo != null && fieldInfo.GetValue(obj4) is ulong value)
				{
					stringBuilder.Append("Value(field)=" + value);
					trace = stringBuilder.ToString();
					return value;
				}
				if (ulong.TryParse(obj4.ToString(), out var result))
				{
					stringBuilder.Append("Value(ToString parse)=" + result);
					trace = stringBuilder.ToString();
					return result;
				}
				stringBuilder.Append("no pude extraer un ulong de SteamId (tipo=" + type4.FullName + ")");
				trace = stringBuilder.ToString();
				return null;
			}
			catch (Exception ex)
			{
				stringBuilder.Append("EXCEPCIÓN: " + ex.Message);
				trace = stringBuilder.ToString();
				return null;
			}
		}
	}
	[HarmonyPatch]
	public static class GrabbableObjectVisibilityDiagnosticPatch
	{
		public static MethodBase TargetMethod()
		{
			Type type = AccessTools.TypeByName("GrabbableObject");
			return (type == null) ? null : AccessTools.Method(type, "Start", (Type[])null, (Type[])null);
		}

		public static void Postfix(object __instance)
		{
			try
			{
				object obj = ((__instance is Component) ? __instance : null);
				object obj2;
				if (obj == null)
				{
					obj2 = null;
				}
				else
				{
					GameObject gameObject = ((Component)obj).gameObject;
					obj2 = ((gameObject != null) ? ((Object)gameObject).name : null);
				}
				if (obj2 == null)
				{
					obj2 = "";
				}
				string text = (string)obj2;
				if (text.IndexOf("Y4NGZ", StringComparison.OrdinalIgnoreCase) < 0)
				{
					return;
				}
				Type type = __instance.GetType();
				string text2 = "N/A";
				string text3 = "N/A";
				string text4 = "N/A";
				string text5 = "N/A";
				try
				{
					object obj3 = AccessTools.Property(AccessTools.TypeByName("Unity.Netcode.NetworkBehaviour"), "NetworkObject")?.GetValue(__instance);
					if (obj3 != null)
					{
						Type type2 = obj3.GetType();
						text2 = AccessTools.Property(type2, "NetworkObjectId")?.GetValue(obj3)?.ToString() ?? "N/A";
						text3 = AccessTools.Property(type2, "IsSpawned")?.GetValue(obj3)?.ToString() ?? "N/A";
						text5 = AccessTools.Property(type2, "OwnerClientId")?.GetValue(obj3)?.ToString() ?? "N/A";
					}
					text4 = AccessTools.Property(type, "IsOwner")?.GetValue(__instance)?.ToString() ?? "N/A";
				}
				catch
				{
				}
				NetworkManager singleton = NetworkManager.Singleton;
				string text6 = (((Object)(object)singleton == (Object)null) ? "N/A" : (singleton.IsHost ? "HOST" : (singleton.IsClient ? "CLIENT" : "?")));
				string text7 = ((singleton != null) ? singleton.LocalClientId.ToString() : null) ?? "N/A";
				Plugin.Log.LogInfo((object)("[BetterArmoryFix][DIAG5-VISIBILIDAD] (" + text6 + ", miClientId=" + text7 + ") GrabbableObject.Start() para '" + text + "' -> NetworkObjectId=" + text2 + ", IsSpawned=" + text3 + ", IsOwner=" + text4 + ", OwnerClientId=" + text5));
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[BetterArmoryFix][DIAG5-VISIBILIDAD] No se pudo leer el diagnóstico: " + ex.Message));
			}
		}
	}
	[HarmonyPatch]
	public static class Y4NGZOwnershipFixupPatch
	{
		public static MethodBase TargetMethod()
		{
			Type type = AccessTools.TypeByName("GameNetcodeStuff.PlayerControllerB");
			Type type2 = AccessTools.TypeByName("GrabbableObject");
			if (type == null || type2 == null)
			{
				return null;
			}
			return AccessTools.Method(type, "SwitchToItemSlot", new Type[2]
			{
				typeof(int),
				type2
			}, (Type[])null);
		}

		public static void Postfix(object __instance, object fillSlotWithItem)
		{
			if (fillSlotWithItem == null)
			{
				return;
			}
			try
			{
				object? obj = AccessTools.Property(fillSlotWithItem.GetType(), "gameObject")?.GetValue(fillSlotWithItem);
				GameObject val = (GameObject)((obj is GameObject) ? obj : null);
				string text = ((val != null) ? ((Object)val).name : null) ?? "";
				if (text.IndexOf("Y4NGZ", StringComparison.OrdinalIgnoreCase) < 0)
				{
					return;
				}
				NetworkBehaviour val2 = (NetworkBehaviour)((fillSlotWithItem is NetworkBehaviour) ? fillSlotWithItem : null);
				if ((Object)(object)val2 == (Object)null || !val2.IsServer)
				{
					return;
				}
				NetworkBehaviour val3 = (NetworkBehaviour)((__instance is NetworkBehaviour) ? __instance : null);
				if ((Object)(object)val3 == (Object)null)
				{
					return;
				}
				Type type = fillSlotWithItem.GetType();
				FieldInfo fieldInfo = AccessTools.Field(type, "playerHeldBy");
				if (fieldInfo == null)
				{
					return;
				}
				object value = fieldInfo.GetValue(fillSlotWithItem);
				bool flag = value != __instance;
				NetworkObject networkObject = val2.NetworkObject;
				Type type2 = __instance.GetType();
				FieldInfo fieldInfo2 = AccessTools.Field(type2, "playerClientId");
				ulong num = ((fieldInfo2 != null) ? ((ulong)fieldInfo2.GetValue(__instance)) : val3.OwnerClientId);
				bool flag2 = (Object)(object)networkObject != (Object)null && networkObject.OwnerClientId != num;
				if (flag || flag2)
				{
					if (flag)
					{
						fieldInfo.SetValue(fillSlotWithItem, __instance);
					}
					if (flag2)
					{
						networkObject.ChangeOwnership(num);
					}
					Plugin.Log.LogInfo((object)("[BetterArmoryFix] Corregido mismatch de propiedad para '" + text + "': playerHeldBy desincronizado=" + flag + ", ownership de red desincronizado=" + flag2 + " -> ahora asignado al jugador que lo equipó (clientId=" + num + ")."));
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[BetterArmoryFix] No se pudo verificar/corregir el ownership del arma: " + ex.Message));
			}
		}
	}
}