Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of BetterArmoryFix v2.4.1
BetterArmoryFix.dll
Decompiled 2 months agousing 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)); } } } }