Sponge Build: spongevanilla-1.12.1-7.0.0-BETA-314 Forge Build: (Ignore if using SpongeVanilla) Java Version: 1.8.0_131
Plugin Source:
@Listener
public void onPlayerCraft(ClickInventoryEvent event, @First Player player)
{
Inventory inventory = event.getTargetInventory();
for (SlotTransaction transaction : event.getTransactions())
{
Inventory craftInventory = inventory.query(CraftingInventory.class);
//craft manipulation here
}
}
Hello Everyone,
As mentioned in the title, I am trying to disable a craft operation. Specifically I am trying to make a ānewā set of items (represented by named gold nuggets, ingots, and blocks) that can be crafted into each other, but not other recipes that use typical gold.
However, I canāt seem to find a way to accomplish this task. Hereās a list of things I have tried/looked into:
Using the CraftItemEvent (seems to no longer exist)
Unregistering the vanilla craft recipe (can only register new recipes)
Using the ClickInventoryEvent (best lead so far, things Iāve tried inside below)
Getting CraftingInventory, GridInventory, etc using the Inventory Apiās query method using the click eventās inventory
Getting the above directly through the āclickingā playerās inventory
The snippet of code written above is a near copy of the code I found in a question similar to this one in 2016 but it seems to no longer work. Iāve tried everything I could think of short of using NMS or doing a PR. Of the two Iād prefer to take on the latter.
So, is there a better way to go about this or does sponge currently lack this ability? If sponge is lacking in this aspect, what unimplemented factor do I need to do a PR for to make this happen?
@Listener
public void onItemCraft(ClickInventoryEvent event, @Root Player player, @Getter("getTargetInventory") Inventory inventory) {
if (inventory.getArchetype() == InventoryArchetypes.PLAYER || inventory.getArchetype() == InventoryArchetypes.WORKBENCH) {
Inventory craftingOutputs = inventory.query(CraftingOutput.class);
craftingOutputs.slots().forEach(slot -> slot.peek().ifPresent(itemStack -> {
String itemId = itemStack.getItem().getType().getId();
if (!player.hasPermission("protectionperms.item.craft." + itemId)) {
event.setCancelled(true);
player.sendMessage(ChatTypes.ACTION_BAR, Text.of(TextColors.RED, "You don't have permission to craft " + itemId + '!'));
}
}));
}
}
You can see here that Iām specifically looking at the output slots to determine what was being crafted, but you could easily flip this around to examine the input slots to determine what is being put in, if any of the items donāt match what is allowed then you can simply cancel the event. Hope that helps!
Unfortunately, it appears your method only worked for the crafting output. Using CraftingInventory and CraftingGridInventory both returns empty inventories.
Looking into the values of inventory in the debugger I think I might poke around getting the specific slot numbers of the crafting input to work. If anyone else has a better idea of how to go about this, or what in sponge I could implement this to add it as a real feature, please let me know!
Input Slot appears to get me an instance of GridInventory oddly enough. Iāll fill out a bug report in a bit, though first I have an idea Iād like to try.
Please update with your results if they work, as I am trying to do something virtually identical - adding ācardboard box technologyā items (aka, imagination powered, not mod-powered) that makes copper ingots from bricks, and can be used in recipes to make special tools and items, but I donāt want someone consuming them accidentally making regular bricks, or prismarine blocks out of rare and expensive ājadeā, or a special tool from bricks instead of copper ingots (though I think I can register the recipes in such a way that covers that)
Ok so after some tinkering and testing Iāve learned a few things.
Zerthickās suggestion on the input slot works, but only for the crafting table (not the player menu crafting). Itāll give you a GridInventory of the 3 by 3 youāll find in the craft table (where 0, 0 is upper left corner, 0, 1 is the one below it, etc).
However, there isnāt a way to get this for the player inventory crafting as far as I could find, so Iāll have to rely on the bug report. Another thing to note is that Iām working on sponge 7.0.0 (to make use of the Recipe API ironically) so that may be some of my issue.
Iāll put in the bug report on that lack of crafting inventory and make a pr if I somehow manage to figure out a fix.
Hi all, I was attempting to try something similar, using @Zerthick 's onItemCraft method as an example. The code works fine in the player inventory, but throws an error in the workbench inventory. As a note, Iām using spongeapi:5.1.0 for minecraft 1.10.2.
Would depend on the build of sponge you are using, and implimentation.
Yes, that issue - if you get the same error - is due to a thing that was not fixed until early February 2017, if you are using a version from that long ago.
The 1.10.2 builds from long ago will contain that error, but the more recent builds should include that codefix in both SF and SV versions, and you may be looking at a different error.
Even the 1.10.2 Api 5.1 version seems to have had its last versions updated at the end of February, so they will either be including that code fix in them, or that code fix was added at the start of the 5.2 verisions
You were completely right I updated to the 5.2.0 series of versions and the error went away. Very embarrassing oops!
Iāve still been trying out the code, and it cancels the event when an item is put into the input slot that produces the output we are checking for. Is there a way to detect specifically if the transaction slot being clicked is the out put slot? I tried doing the below, but I think the output is added to the list of transactions. Would be happy to hear of best way to do so, as well as any better coding practices
boolean IsClickingOutput = false;
if ( event.getTransactions().get(0).getSlot().getProperty(SlotIndex.class, "slotindex") == slot.getProperty(SlotIndex.class, "slotindex") )
{
logger.info("Player is trying to craft the item " + itemId);
IsClickingOutput = true;
}