[SPIGOT-1009] Crafting items using shift causes insufficient CraftItemEvent Created: 29/Jun/15  Updated: 24/Jun/20

Status: Open
Project: Spigot
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Minor
Reporter: Lukas Assignee: Unassigned
Resolution: Unresolved Votes: 4
Labels: Craftbukkit, bug, event
Environment:

Windows 7 with Java JDK 8


Attachments: PNG File step1.PNG     PNG File step2.PNG    

 Description   

Look at the attachements for example. I've got two iron ingots and two flints in my crafting menu. Now using shift + left click crafts two flint and steel. But there is only 1 CraftItemEvent called having the following content:

[11:59:20] [Server thread/INFO]: event.getCurrentItem().getType() = FLINT_AND_STEEL
[11:59:20] [Server thread/INFO]: event.getCurrentItem().getAmount() = 1
[11:59:20] [Server thread/INFO]: event.getCurrentItem().getDurability() = 0

I've also tested it with torches producing the same bug.

That is a problem if you want to modify every item beeing crafted, like reducing durability of flint and steel.



 Comments   
Comment by YourCoal [ 24/Jun/20 ]

I think it would be best if there was some sort of way to call the event multiple times perhaps when items are crafted, or if there was some way to detect the multiple stacks resulted, like multiple pickaxes, have a List of ItemStacks.

Comment by Foorcee [ 25/Feb/20 ]


It might also be good to have a real crafting event. It can also be called more often, through the recusion. Currently the event is only called once, although several items are being crafted.

Comment by Foorcee [ 23/Feb/20 ]

The issue still exists.
Is it possible to find a solution that fix the issue?
Maybe add a PostCraftItemEvent that provides the amount of crafted items.

Comment by lizardfreak321 [ 01/Aug/16 ]

I was able to manually calculate how many there would be, but just in case I got it wrong I canceled the event and re-implemented the features that shift-click does. This is how I do it:

int numberOfItems = originalResult.getAmount();
if (event.isShiftClick()) {
	// Looks for the ingredient with the lowest amount.
	int itemsChecked = 0;
	for (ItemStack item : event.getInventory().getMatrix()) {
		if (item != null && !item.getType().equals(Material.AIR)) {
			if (itemsChecked == 0)
				numberOfItems = item.getAmount();
			else
				numberOfItems = Math.min(numberOfItems, item.getAmount());
			itemsChecked++;
			}
	}
	// Cancels it because this plugin is taking over.
	event.setResult(Result.DENY);
	event.setCancelled(true);

	int number = compatibleSlots(originalResult, event.getWhoClicked().getInventory());

	// There needs to be enough room to put these items, so it checks which one is
	numberOfItems = Math.min(number, numberOfItems * originalResult.getAmount());
	// Adds the items to the user's inventory here
}
public int compatibleSlots(ItemStack compatibleWith, Inventory inv) {
	int slots = 0;
	for (int i = 0; i < inv.getSize(); i++) {
		if (inv.getItem(i) == null || inv.getItem(i).getType().equals(Material.AIR))
			slots += compatibleWith.getMaxStackSize();
		else if (isCompatible(compatibleWith, inv.getItem(i)))
			slots += (compatibleWith.getMaxStackSize() - inv.getItem(i).getAmount());
	}
	return slots;
}

My code works but it is far from perfect. If there was some easy way to get how many items Minecraft's code intends to do, it would be better since I can imagine there being times where my code is inaccurate. That is why I completely redid the craft item event on shift, because my code cannot afford any inaccuracies.

Comment by PixelPerfect [ 16/Jul/16 ]

Might be worth sticking a PostCraftItemEvent on which could contain a function for getting how many items were crafted and another returning a list of slots they went to. From that, multiple easy workarounds would be possible.

Comment by md_5 [ 11/Jul/16 ]

Right so this is due to a design flaw in the CraftItemEvent which returns what is in the slot which you clicked.
As you can see in step1.PNG this is a slot of size 1.

Also Minecraft uses a recursive implementation, so it doesn't know how much it can craft ahead of time :\

Comment by Lukas [ 07/Jul/15 ]

In some cases, there might be a workaround. In my case, i wanted to set durability to each flint and steel ever crafted. So i can iterate through the whole inventory after each crafting process:
for ( ItemStack itemStack : event.getWhoClicked().getInventory() ) {
if ( itemStack != null && itemStack.getType() == Material.FLINT_AND_STEEL && itemStack.getDurability() == 0 )

{ randomizeDurability( itemStack ); }

}
But that might not work every time, so the priority is still legit.

Generated at Fri Apr 11 15:51:10 UTC 2025 using Jira 10.3.3#10030003-sha1:d220e3fefc8dfc6d47f522d3b9a20c1455e12b7b.