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 BepInEx.Logging;
using FishNet.Object;
using HarmonyLib;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("BulkSellMod")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("BulkSellMod")]
[assembly: AssemblyTitle("BulkSellMod")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace BulkSellMod;
[BepInPlugin("com.bulksell.htf", "BulkSellMod", "1.2.1")]
[BepInProcess("How to Fish")]
public class BulkSellMod : BaseUnityPlugin
{
private struct BulkSellJob
{
public NPC Npc;
public NPCQuest Quest;
public byte QuestIndex;
public byte Slot;
public PlayerInventory Inv;
public int Remaining;
public int ItemId;
}
[HarmonyPatch(typeof(NPC), "EatItem")]
private static class EatPatch
{
[HarmonyPostfix]
private static void Postfix(NPC __instance, NPCQuest quest, byte questIndex, Item item)
{
try
{
if (_isBulkFeeding || !SellWholeStack.Value || !_bulkArmed)
{
return;
}
_bulkArmed = false;
if (!Object.op_Implicit((Object)(object)Server.Instance) || !((NetworkBehaviour)Server.Instance).IsServerInitialized || !Object.op_Implicit((Object)(object)item))
{
return;
}
Player lastHolder = item.LastHolder;
if (!Object.op_Implicit((Object)(object)lastHolder))
{
return;
}
PlayerInventory inventory = lastHolder.Inventory;
if (!Object.op_Implicit((Object)(object)inventory))
{
return;
}
int num = 0;
foreach (KeyValuePair<byte, Item> item2 in inventory._items)
{
Item value = item2.Value;
if (Object.op_Implicit((Object)(object)value) && value.ID == item.ID)
{
int num2 = StackCount(inventory, item2.Key) + 1;
_bulkQueue.Enqueue(new BulkSellJob
{
Npc = __instance,
Quest = quest,
QuestIndex = questIndex,
Slot = item2.Key,
Inv = inventory,
Remaining = num2,
ItemId = item.ID
});
num += num2;
}
}
if (num > 0)
{
_logger.LogInfo((object)string.Format("{0}: Sold {1} of item {2} in one go.", "BulkSellMod", num, item.ID));
}
}
catch (Exception arg)
{
_logger.LogWarning((object)string.Format("{0}: bulk sell error: {1}", "BulkSellMod", arg));
}
}
}
public const string PluginGuid = "com.bulksell.htf";
public const string PluginName = "BulkSellMod";
public const string PluginVersion = "1.2.1";
public static ConfigEntry<bool> SellWholeStack;
private static bool _bulkArmed;
private const int MaxFeedsPerFrame = 6;
private static readonly Queue<BulkSellJob> _bulkQueue = new Queue<BulkSellJob>();
private static bool _isBulkFeeding;
private static MethodInfo _popServerStack;
private static MethodInfo _getStackCount;
private static MethodInfo _eatItem;
private static ManualLogSource _logger;
private void Awake()
{
_logger = ((BaseUnityPlugin)this).Logger;
SellWholeStack = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "SellWholeStack", true, "Master switch for bulk sell. Hold LeftShift and press Q to arm ONE whole-stack sale, then feed a fish to the NPC.");
Type type = AccessTools.TypeByName("StackableItems.StackManager");
if (type != null)
{
_popServerStack = type.GetMethod("PopServerStack", BindingFlags.Static | BindingFlags.Public);
_getStackCount = type.GetMethod("GetStackCount", BindingFlags.Static | BindingFlags.Public);
if (_popServerStack != null && _getStackCount != null)
{
((BaseUnityPlugin)this).Logger.LogInfo((object)"BulkSellMod: StackableItems found and hooked.");
}
}
Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "com.bulksell.htf");
((BaseUnityPlugin)this).Logger.LogInfo((object)"BulkSellMod v1.2.1 loaded.");
}
private void Update()
{
Keyboard current = Keyboard.current;
if (current != null && ((ButtonControl)current.leftShiftKey).isPressed && ((ButtonControl)current.qKey).wasPressedThisFrame && !_bulkArmed)
{
_bulkArmed = true;
_logger.LogInfo((object)"BulkSellMod: Bulk armed for next fish feed. Throw a fish!");
}
if (_bulkQueue.Count == 0)
{
return;
}
int num = 0;
while (num < 6 && _bulkQueue.Count > 0)
{
BulkSellJob item = _bulkQueue.Dequeue();
num++;
if (!Object.op_Implicit((Object)(object)item.Npc) || !Object.op_Implicit((Object)(object)item.Inv))
{
continue;
}
Item val = PopStack(item.Inv, item.Slot);
if ((Object)(object)val == (Object)null)
{
val = SlotItem(item.Inv, item.Slot);
}
if (Object.op_Implicit((Object)(object)val) && val.ID == item.ItemId && !val.IsDestroying && !((NetworkBehaviour)val).IsDeinitializing)
{
_isBulkFeeding = true;
try
{
EatItemDirect(item.Npc, item.Quest, item.QuestIndex, val);
}
finally
{
_isBulkFeeding = false;
}
}
if (item.Remaining > 1)
{
item.Remaining--;
_bulkQueue.Enqueue(item);
}
}
}
private static Item PopStack(PlayerInventory inv, byte slot)
{
if (_popServerStack == null)
{
return null;
}
try
{
object? obj = _popServerStack.Invoke(null, new object[2] { inv, slot });
return (Item)((obj is Item) ? obj : null);
}
catch
{
return null;
}
}
private static Item SlotItem(PlayerInventory inv, byte slot)
{
try
{
if (inv._items == null)
{
return null;
}
return inv._items[slot];
}
catch
{
return null;
}
}
private static int StackCount(PlayerInventory inv, byte slot)
{
if (_getStackCount == null)
{
return 0;
}
try
{
return (int)_getStackCount.Invoke(null, new object[2] { inv, slot });
}
catch
{
return 0;
}
}
private static void EatItemDirect(NPC npc, NPCQuest quest, byte questIndex, Item item)
{
if (_eatItem == null)
{
_eatItem = AccessTools.Method(typeof(NPC), "EatItem", (Type[])null, (Type[])null);
}
_eatItem.Invoke(npc, new object[3] { quest, questIndex, item });
}
}