using System;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using AmmoBag.Patches;
using BepInEx;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using LethalNetworkAPI;
using Unity.Netcode;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("AmmoBag")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AmmoBag")]
[assembly: AssemblyCopyright("Copyright © 2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("da0de89f-9696-4ca2-a169-d360d37a3b8f")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace AmmoBag
{
internal static class AmmoBagHelper
{
internal const int encode_base_number = 1000000;
internal static ulong pendingBagNetworkObjectId;
internal static int pendingAmmoInBagIndex;
internal static int FindAmmoInBelt(PlayerControllerB player, ShotgunItem __instance)
{
for (int i = 0; i < player.ItemSlots.Length; i++)
{
if (CheckSlot(__instance, player.ItemSlots[i]))
{
BeltBagPatchBase.logSource.LogInfo((object)("Found shell in slot " + i));
return 1000000;
}
}
if (CheckSlot(__instance, player.ItemOnlySlot))
{
BeltBagPatchBase.logSource.LogInfo((object)"Found shell in utilitySlot");
return 1000000;
}
BeltBagPatchBase.logSource.LogInfo((object)"No shells found");
return -1;
}
private static bool CheckSlot(ShotgunItem __instance, GrabbableObject slot)
{
if ((Object)(object)slot == (Object)null)
{
return false;
}
BeltBagItem val = (BeltBagItem)(object)((slot is BeltBagItem) ? slot : null);
if ((Object)(object)val == (Object)null)
{
return false;
}
int num = FindAmmoInBag(val, __instance.gunCompatibleAmmoID);
if (num == -1)
{
return false;
}
pendingBagNetworkObjectId = ((Component)val).GetComponent<NetworkObject>().NetworkObjectId;
pendingAmmoInBagIndex = num;
return true;
}
private static int FindAmmoInBag(BeltBagItem bag, int ammoTypeID)
{
for (int num = bag.objectsInBag.Count - 1; num >= 0; num--)
{
GrabbableObject val = bag.objectsInBag[num];
if (!((Object)(object)val == (Object)null))
{
GunAmmo val2 = (GunAmmo)(object)((val is GunAmmo) ? val : null);
if ((Object)(object)val2 != (Object)null && val2.ammoType == ammoTypeID)
{
return num;
}
}
}
return -1;
}
}
internal static class AmmoNetworking
{
private static LNetworkMessage<NetworkRequestStruct> msg_deleteShell_Server;
private static LNetworkMessage<NetworkRequestStruct> msg_deleteShell_Client;
internal static bool isHosting;
internal static void SetNetworkMessage()
{
msg_deleteShell_Server = LNetworkMessage<NetworkRequestStruct>.Connect("msg_DeleteOnServer", (Action<NetworkRequestStruct, ulong>)OnRemoveAmmoReceivedServer, (Action<NetworkRequestStruct>)null, (Action<NetworkRequestStruct, ulong>)null);
msg_deleteShell_Client = LNetworkMessage<NetworkRequestStruct>.Connect("msg_DeleteOnClients", (Action<NetworkRequestStruct, ulong>)null, (Action<NetworkRequestStruct>)OnRemoveAmmoReceivedClient, (Action<NetworkRequestStruct, ulong>)null);
}
public static void RequestRemoveAmmo(ulong bagNetworkObjectId, int ammoInBagIndex)
{
BeltBagPatchBase.logSource.LogInfo((object)"Requested remove ammo");
msg_deleteShell_Server.SendServer(new NetworkRequestStruct(bagNetworkObjectId, ammoInBagIndex));
}
private static void OnRemoveAmmoReceivedServer(NetworkRequestStruct data, ulong senderClientId)
{
if (NetworkManager.Singleton.SpawnManager.SpawnedObjects.TryGetValue(data.bagNetworkObjectId, out var value))
{
BeltBagItem component = ((Component)value).GetComponent<BeltBagItem>();
if ((Object)(object)component != (Object)null && data.ammoInBagIndex >= 0 && data.ammoInBagIndex < component.objectsInBag.Count)
{
component.objectsInBag.RemoveAt(data.ammoInBagIndex);
BeltBagPatchBase.logSource.LogInfo((object)"Host removed shell from bag");
}
else
{
BeltBagPatchBase.logSource.LogWarning((object)"SyncBagAmmoRemovalServerRpc: bag null or index out of range");
}
}
else
{
BeltBagPatchBase.logSource.LogWarning((object)("SyncBagAmmoRemovalServerRpc: could not find bag with id " + data.bagNetworkObjectId));
}
msg_deleteShell_Client.SendClients(new NetworkRequestStruct(data.bagNetworkObjectId, data.ammoInBagIndex));
}
private static void OnRemoveAmmoReceivedClient(NetworkRequestStruct @struct)
{
if (isHosting)
{
return;
}
if (!NetworkManager.Singleton.SpawnManager.SpawnedObjects.TryGetValue(@struct.bagNetworkObjectId, out var value))
{
BeltBagPatchBase.logSource.LogWarning((object)("SyncBagAmmoRemoval: could not find bag with NetworkObjectId " + @struct.bagNetworkObjectId));
return;
}
BeltBagItem component = ((Component)value).GetComponent<BeltBagItem>();
if ((Object)(object)component == (Object)null)
{
BeltBagPatchBase.logSource.LogWarning((object)"SyncBagAmmoRemoval: NetworkObject is not a BeltBagItem");
}
else if (@struct.ammoInBagIndex < 0 || @struct.ammoInBagIndex >= component.objectsInBag.Count)
{
BeltBagPatchBase.logSource.LogWarning((object)"SyncBagAmmoRemoval: ammoInBagIndex out of range");
}
else
{
component.objectsInBag.RemoveAt(@struct.ammoInBagIndex);
}
}
}
public struct NetworkRequestStruct
{
public ulong bagNetworkObjectId;
public int ammoInBagIndex;
public NetworkRequestStruct(ulong bagNetworkObjectId, int ammoInBagIndex)
{
this.bagNetworkObjectId = bagNetworkObjectId;
this.ammoInBagIndex = ammoInBagIndex;
}
}
[BepInPlugin("PixelIndieDev_AmmoBag", "Ammo Bag", "1.1.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class BeltBagPatchBase : BaseUnityPlugin
{
private readonly Harmony harmony = new Harmony("PixelIndieDev_AmmoBag");
private static BeltBagPatchBase instance;
internal static ManualLogSource logSource;
private void Awake()
{
if ((Object)(object)instance == (Object)null)
{
instance = this;
}
logSource = Logger.CreateLogSource("PixelIndieDev_AmmoBag");
harmony.PatchAll(typeof(BeltBagPatchBase));
harmony.PatchAll(typeof(NetworkPatch));
harmony.PatchAll(typeof(ShotgunPatch));
harmony.PatchAll(typeof(PlayerPatch));
harmony.PatchAll(typeof(MenuManagerPatch));
AmmoNetworking.SetNetworkMessage();
logSource.LogInfo((object)"Ammo Bag (version - 1.1.0.0): patches applied successfully");
}
}
internal static class ModInfo
{
internal const string modGUID = "PixelIndieDev_AmmoBag";
internal const string modName = "Ammo Bag";
internal const string modVersion = "1.1.0.0";
}
}
namespace AmmoBag.Patches
{
[HarmonyPatch(typeof(MenuManager))]
internal class MenuManagerPatch
{
[HarmonyPatch("StartHosting")]
[HarmonyPrefix]
[HarmonyPriority(0)]
private static void OnStartHostingPatch()
{
AmmoNetworking.isHosting = true;
}
[HarmonyPatch("StartAClient")]
[HarmonyPrefix]
[HarmonyPriority(0)]
private static void OnStartConnectingPatch()
{
AmmoNetworking.isHosting = false;
}
}
[HarmonyPatch(typeof(NetworkManager))]
internal static class NetworkPatch
{
[HarmonyPostfix]
[HarmonyPatch("SetSingleton")]
private static void RegisterPrefab()
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Expected O, but got Unknown
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
GameObject val = new GameObject("PixelIndieDev_AmmoBag Prefab");
((Object)val).hideFlags = (HideFlags)(((Object)val).hideFlags | 0x3D);
Object.DontDestroyOnLoad((Object)(object)val);
NetworkObject obj = val.AddComponent<NetworkObject>();
typeof(NetworkObject).GetField("GlobalObjectIdHash", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(obj, GetHash("PixelIndieDev_AmmoBag"));
NetworkManager.Singleton.PrefabHandler.AddNetworkPrefab(val);
}
private static uint GetHash(string value)
{
return value?.Aggregate(17u, (uint current, char c) => (current * 31) ^ c) ?? 0;
}
}
[HarmonyPatch(typeof(PlayerControllerB))]
internal class PlayerPatch
{
[HarmonyPatch("DestroyItemInSlotAndSync")]
[HarmonyPrefix]
[HarmonyPriority(0)]
private static bool PatchFindAmmo(PlayerControllerB __instance, int itemSlot)
{
if (itemSlot < 1000000)
{
return true;
}
ulong pendingBagNetworkObjectId = AmmoBagHelper.pendingBagNetworkObjectId;
int pendingAmmoInBagIndex = AmmoBagHelper.pendingAmmoInBagIndex;
if (!NetworkManager.Singleton.SpawnManager.SpawnedObjects.TryGetValue(pendingBagNetworkObjectId, out var _))
{
BeltBagPatchBase.logSource.LogWarning((object)("Could not find belt bag NetworkObject with id " + pendingBagNetworkObjectId));
return false;
}
AmmoNetworking.RequestRemoveAmmo(pendingBagNetworkObjectId, pendingAmmoInBagIndex);
return false;
}
}
[HarmonyPatch(typeof(ShotgunItem))]
internal class ShotgunPatch
{
[HarmonyPatch("FindAmmoInInventory")]
[HarmonyPostfix]
[HarmonyPriority(0)]
private static void PatchFindAmmo(ref int __result, ShotgunItem __instance)
{
if (__result == -1)
{
PlayerControllerB playerHeldBy = ((GrabbableObject)__instance).playerHeldBy;
if (!((Object)(object)playerHeldBy == (Object)null))
{
__result = AmmoBagHelper.FindAmmoInBelt(playerHeldBy, __instance);
}
}
}
}
}