public static bool receiveLeftClick_Prefix(int x, int y, bool playSound, // Original arguments
ref Item ___sourceItem, ref TemporaryAnimatedSprite ___poof,
ItemGrabMenu.behaviorOnItemSelect ___behaviorFunction, bool ___essential, // Private fields
ItemGrabMenu __instance) // Special
{
try
{
Monitor.Log($"Invoked ItemGrabMenu.receiveLeftClick_Prefix.", LogLevel.Debug);
// Reimplemented game code
/**
//base.receiveLeftClick(x, y, !__instance.destroyItemOnClick); // Reimplemented below
var baseMethod = typeof(MenuWithInventory).GetMethod("receiveLeftClick");
var ftn = baseMethod.MethodHandle.GetFunctionPointer();
var baseReceiveLeftClick = (Action<int, int, bool>)Activator.CreateInstance(
typeof(Action<int, int, bool>), __instance, ftn);
baseReceiveLeftClick(x, y, !__instance.destroyItemOnClick);
// Shipping bin menu
if (__instance.shippingBin && __instance.lastShippedHolder.containsPoint(x, y))
{
if (Game1.getFarm().lastItemShipped == null)
return false; // Don't run original code
Game1.getFarm().getShippingBin(Game1.player).Remove(Game1.getFarm().lastItemShipped);
if (Game1.player.addItemToInventoryBool(Game1.getFarm().lastItemShipped, false))
{
Game1.playSound("coin");
Game1.getFarm().lastItemShipped = (Item)null;
if (Game1.player.ActiveObject == null)
return false; // Don't run original code
Game1.player.showCarrying();
Game1.player.Halt();
}
else
Game1.getFarm().getShippingBin(Game1.player).Add(Game1.getFarm().lastItemShipped);
}
else
{
// Select color for chests
if (__instance.chestColorPicker != null)
{
__instance.chestColorPicker.receiveLeftClick(x, y, true);
if (___sourceItem != null && ___sourceItem is Chest)
(___sourceItem as Chest).playerChoiceColor.Value = __instance.chestColorPicker.getColorFromSelection(__instance.chestColorPicker.colorSelection);
}
if (__instance.colorPickerToggleButton != null && __instance.colorPickerToggleButton.containsPoint(x, y))
{
Game1.player.showChestColorPicker = !Game1.player.showChestColorPicker;
__instance.chestColorPicker.visible = Game1.player.showChestColorPicker;
try
{
Game1.playSound("drumkit6");
}
catch (Exception ex)
{
}
__instance.SetupBorderNeighbors();
}
// Junimo harvest toggle
if (__instance.whichSpecialButton != -1 && __instance.specialButton != null && __instance.specialButton.containsPoint(x, y))
{
Game1.playSound("drumkit6");
if (__instance.whichSpecialButton == 1 && __instance.context != null && __instance.context is JunimoHut)
{
(__instance.context as JunimoHut).noHarvest.Value = !(bool)(NetFieldBase<bool, NetBool>)(__instance.context as JunimoHut).noHarvest;
__instance.specialButton.sourceRect.X = (bool)(NetFieldBase<bool, NetBool>)(__instance.context as JunimoHut).noHarvest ? 124 : 108;
}
}
// Click with empty hand
if (__instance.heldItem == null && __instance.showReceivingMenu)
{
__instance.heldItem = __instance.ItemsToGrabMenu.leftClick(x, y, __instance.heldItem, false);
// behaviorOnItemGrab Action
if (__instance.heldItem != null && __instance.behaviorOnItemGrab != null)
{
__instance.behaviorOnItemGrab(__instance.heldItem, Game1.player);
// ???
if (Game1.activeClickableMenu != null && Game1.activeClickableMenu is ItemGrabMenu)
{
(Game1.activeClickableMenu as ItemGrabMenu).setSourceItem(___sourceItem);
if (Game1.options.SnappyMenus)
{
(Game1.activeClickableMenu as ItemGrabMenu).currentlySnappedComponent = __instance.currentlySnappedComponent;
(Game1.activeClickableMenu as ItemGrabMenu).snapCursorToCurrentSnappedComponent();
}
}
}
// Dwarvish translation guide
if (__instance.heldItem is StardewValley.Object && (int)(NetFieldBase<int, NetInt>)(__instance.heldItem as StardewValley.Object).parentSheetIndex == 326)
{
__instance.heldItem = (Item)null;
Game1.player.canUnderstandDwarves = true;
___poof = new TemporaryAnimatedSprite("TileSheets\\animations", new Rectangle(0, 320, 64, 64), 50f, 8, 0, new Vector2((float)(x - x % 64 + 16), (float)(y - y % 64 + 16)), false, false);
Game1.playSound("fireball");
}
// Lost book
else if (__instance.heldItem is StardewValley.Object && (int)(NetFieldBase<int, NetInt>)(__instance.heldItem as StardewValley.Object).parentSheetIndex == 102)
{
__instance.heldItem = (Item)null;
Game1.player.foundArtifact(102, 1);
___poof = new TemporaryAnimatedSprite("TileSheets\\animations", new Rectangle(0, 320, 64, 64), 50f, 8, 0, new Vector2((float)(x - x % 64 + 16), (float)(y - y % 64 + 16)), false, false);
Game1.playSound("fireball");
}
// Stardrop
if (__instance.heldItem is StardewValley.Object && Utility.IsNormalObjectAtParentSheetIndex(__instance.heldItem, 434))
{
StardewValley.Object heldItem = __instance.heldItem as StardewValley.Object;
__instance.heldItem = (Item)null;
__instance.exitThisMenu(false);
Game1.player.eatObject(heldItem, true);
}
// New Recipe
else if (__instance.heldItem is StardewValley.Object && (bool)(NetFieldBase<bool, NetBool>)(__instance.heldItem as StardewValley.Object).isRecipe)
{
string key = __instance.heldItem.Name.Substring(0, __instance.heldItem.Name.IndexOf("Recipe") - 1);
try
{
if ((__instance.heldItem as StardewValley.Object).Category == -7)
Game1.player.cookingRecipes.Add(key, 0);
else
Game1.player.craftingRecipes.Add(key, 0);
___poof = new TemporaryAnimatedSprite("TileSheets\\animations", new Rectangle(0, 320, 64, 64), 50f, 8, 0, new Vector2((float)(x - x % 64 + 16), (float)(y - y % 64 + 16)), false, false);
Game1.playSound("newRecipe");
}
catch (Exception ex)
{
}
__instance.heldItem = (Item)null;
}
// Try to add to inventory - this is where it's going wrong for grandpa callbacks
else if (Game1.player.addItemToInventoryBool(__instance.heldItem, false)) // Can I pass in a delegate? No.
{
if (__instance.inventory.onAddItem != null) // MY ADDITIONS!
__instance.inventory.onAddItem(__instance.heldItem, Game1.player); // MY ADDITIONS!
__instance.heldItem = (Item)null;
Game1.playSound("coin");
}
}
// Hands are full. Check if reverse grab is allowed
else if ((__instance.reverseGrab || ___behaviorFunction != null) && __instance.isWithinBounds(x, y))
{
___behaviorFunction(__instance.heldItem, Game1.player); // Action is executed? (Works for callbacks?)
if (Game1.activeClickableMenu != null && Game1.activeClickableMenu is ItemGrabMenu)
{
(Game1.activeClickableMenu as ItemGrabMenu).setSourceItem(___sourceItem);
if (Game1.options.SnappyMenus)
{
(Game1.activeClickableMenu as ItemGrabMenu).currentlySnappedComponent = __instance.currentlySnappedComponent;
(Game1.activeClickableMenu as ItemGrabMenu).snapCursorToCurrentSnappedComponent();
}
}
if (__instance.destroyItemOnClick)
{
__instance.heldItem = (Item)null;
return false; // Don't run original code
}
}
if (__instance.organizeButton != null && __instance.organizeButton.containsPoint(x, y))
{
ClickableComponent snappedComponent = __instance.currentlySnappedComponent;
ItemGrabMenu.organizeItemsInList(__instance.ItemsToGrabMenu.actualInventory);
Game1.activeClickableMenu = (IClickableMenu)new ItemGrabMenu(__instance.ItemsToGrabMenu.actualInventory, false, true, new InventoryMenu.highlightThisItem(InventoryMenu.highlightAllItems), ___behaviorFunction, (string)null, __instance.behaviorOnItemGrab, false, true, true, true, true, __instance.source, ___sourceItem, __instance.whichSpecialButton, __instance.context).setEssential(___essential);
if (snappedComponent != null)
{
Game1.activeClickableMenu.setCurrentlySnappedComponentTo(snappedComponent.myID);
if (Game1.options.SnappyMenus)
__instance.snapCursorToCurrentSnappedComponent();
}
(Game1.activeClickableMenu as ItemGrabMenu).heldItem = __instance.heldItem;
Game1.playSound("Ship");
}
if (__instance.fillStacksButton != null && __instance.fillStacksButton.containsPoint(x, y))
{
__instance.FillOutStacks();
Game1.playSound("Ship");
}
// This one seems to trigger statue callback behaviour. It calls inventory.onAddItem. Try with fishing artifact?
// I think the difference is for delegate onAddItem functions, versus in-built "new Artifact?" checking functions.
else
{
if (__instance.heldItem == null || __instance.isWithinBounds(x, y) || !__instance.heldItem.canBeTrashed())
return false; // Don't run original code
__instance.DropHeldItem();
}
}
return false;**/
return true;
}
catch (Exception ex)
{
Monitor.Log($"Failed in {nameof(receiveLeftClick_Prefix)}:\n{ex}", LogLevel.Error);
return true; // Run original code
}
}