Multiple shaped recipe

Discussion in 'Plugin Development' started by Oka, Jul 25, 2019.

Thread Status:
Not open for further replies.
  1. Offline

    Oka

    Hi,

    I want to introduce new shaped recipe on my server with wood planks, but I would like it to not depend on the type of wood used.

    knowing that I use 5 block, it would make 7776 recipes to write...

    Is there any faster way ?
     
  2. Offline

    Machine Maker

    Ha! Let me know if you find one. The only thing I can think of is maybe you can use inventory click events in a crafting table to possibly set the output slot of a crafting table to something.
     
  3. Offline

    Kars

    You can do it in code more easily.
    Code:Java
    1. @EventHandler
    2. public void handleCustomCrafting(PrepareItemCraftEvent event) {
    3. CraftingInventory inventory = event.getInventory();
    4.  
    5. for (ItemStack item : inventory.getMatrix()) {
    6. // do checks here
    7. }
    8.  
    9. // If some condition
    10. event.getInventory().setResult(/*whatever*/);
    11. }

    You could make a boolean function that checks if a slot is any type of wood, this way you have to call that function only 9 times maximum.

    You can use this code to find out which slot in a crafting table corresponds to which index in the matrix.
    Code:Java
    1. CraftingInventory inventory = event.getInventory();
    2. ItemStack[] items = inventory.getMatrix();
    3.  
    4. for (int i = 0; i < items.length; i++) {
    5. String msg = (items == null)
    6. ? i + " is null"
    7. : i + " is " + items[I].getType;
    8. Bukkit.broadcastMessage(msg);
    9. } //[/I]
     
    Last edited: Jul 25, 2019
  4. Offline

    Machine Maker

    Yeah that's essential what I was thinking of with just using the event instead of creating a ShapedRecipe
     
  5. Offline

    Oka

    @X1machinemaker1X @Kars

    Ok here is a working exemple


    PHP:
        @EventHandler
        
    public void craftingModifier(PrepareItemCraftEvent event) {
            
    CraftingInventory inventory event.getInventory();
            
    ItemStack[] items inventory.getMatrix();
            if (
    data.is(items[4], "STICK") && data.is(items[7], "STICK") && data.isAtLeast(items[0], "PLANKS") && data.isAtLeast(items[1], "PLANKS") && data.isAtLeast(items[2], "PLANKS") && data.isAtLeast(items[3], "PLANKS") && data.isAtLeast(items[5], "PLANKS") && data.isNull(items[6]) && data.isNull(items[8])) {
                
    inventory.setResult(new ItemStack(Material.DIAMOND));
            }      
        }
    is method is boolean checking the Type after checking if it's null

    isAtleast is boolean checking if the type contains the given string (little shortcut to avoid longer code)

    isNull is boolean checking if the itemStack is null...

    EDIT : not working in fact, for some strange reason when I put more ingredient than necessary, and doing the craft all ingredient's quantity all doubling for some unknown reason

    Up, any help for this last problem ?

    EDIT :

    Tried some kind of "bruteforce" method


    Code:
    for (int i = 0 ; i < 6 ; i++) {
                for (int j = 0 ; j < 6 ; j++) {
                    for (int k = 0 ; k < 6 ; k++) {
                        for (int l = 0 ; l < 6 ; l++) {
                            for (int m = 0 ; m < 6 ; m++) {
                                ShapedRecipe woodenTrollAxeRecipe = new ShapedRecipe(new NamespacedKey(this, "WoodenTrollAxe" + Integer.toString(i) + Integer.toString(j) + Integer.toString(k)+ Integer.toString(l) + Integer.toString(m)), woodenTrollAxe);
                                woodenTrollAxeRecipe.shape("012","3s4","vsv");
                                woodenTrollAxeRecipe.setIngredient('0', woodList[i]);
                                woodenTrollAxeRecipe.setIngredient('1', woodList[j]);
                                woodenTrollAxeRecipe.setIngredient('2', woodList[k]);
                                woodenTrollAxeRecipe.setIngredient('3', woodList[l]);
                                woodenTrollAxeRecipe.setIngredient('4', woodList[m]);
                                woodenTrollAxeRecipe.setIngredient('s', Material.STICK);
                                getServer().addRecipe(woodenTrollAxeRecipe);
                            }
                        }   
                    }
                }
            }
    but I have a bad packet message on login...

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jul 25, 2019
  6. Offline

    Kars

    @Oka You're gonna want to check every slot once, then have a function that checks if a single slot is planks. If the values change when you put other items, you are doing something wrong.
     
  7. Offline

    Oka

    @Kars

    Apparently solved for me.

    I did it by dynamically adding recipes on InventoryClickEvent checking all the slot and if the recipe has already been added, if someone wants the code just ask.

    However, this issues was posted one year ago https://hub.spigotmc.org/jira/browse/SPIGOT-4027

    To the opposite of what is said you can easily reproduce it (Just google "Item duplication PrepareItemCraftEvent"), even by using the recipe API you can see that ingredients are doubling and going back to normal really quickly, so I guess there is an issue with the system of custom craft.

    I don't have a Jira account and I don't know how to report bug correctly so if someone feels brave enough feel free.
     
  8. Offline

    Kars

    @Oka
    Does getMatrix return all the items that are currently on the crafting table?
     
  9. Offline

    Machine Maker

  10. Offline

    Kars

    Well then,
    @Oka You are doing something wrong.

    You want to check the contents of the crafting inventory when the event is fired. This check is stateless, meaning you get the same outcome for the same input every time. There is nothing you need to keep track of. I don't understand how you got that from all of this?
     
  11. Offline

    Oka

    @Kars

    In my case I add the event.getCursor() (ItemStack) from InventoryClickEvent into the array from getMatrix() and than I create the recipe if the conditions are right. So I guess getMatrix work that way

    EDIT : What I am doing wrong?
     
  12. Offline

    Kars

    Everything.

    The event gets fired every time. But as with normal crafting, you only get a result of the ingredients are right. We are on the same page so far.

    I am assuming that getMatrix returns an array of length 9. The 9 entries correspond to the slots of the crafting table. I'll give you an example.
    Assuming 0 is the top left, and 9 is the bottom right, say you want to make a wooden pick. When the event gets fired, you check if entries 0, 1 and 2 are any form of planks. Then you check if 4 is null (empty), 5 is a stick, 6 is null and so on.
    There's no need to remember anything. If all the conditions are met you setResult. That's it.
     
  13. Offline

    Oka

    @Kars

    I did it what you say but this is not a regular craft, this is a new craft. Using this way result in this bug:
    https://hub.spigotmc.org/jira/browse/SPIGOT-4027

    And there is no way to avoid it if the craft doesn't exist.

    Your method is really good to do a custom craft with NBT data or to modify existing craft, but when this is about new craft, this bug ruin everything.
     
  14. Offline

    Kars

    @Oka
    Okay you're right. I tested it and it doesn't take away the ingredients when you take out a custom item, making the result infinite. I might look into the best method for this later.
     
  15. Offline

    Oka

    @Kars

    If what you need to do is too big for the brute-force method (I suspect 2000 recipe is the hard limit, so limited to 4 wood planks) I have a big workaround using InventoryClickEvent as I said before.

    The aim is to know when the recipe is about to be completed listening to InventoryClickEvent, once we know it we just need to add the recipe on this moment, when the last ingredient will be put on the table the recipe will be added and the result will appear.

    Maybe it will help random google people :

    Code (open)

    Code:
    public void onItemClick(InventoryClickEvent event) {
            if (event.getClickedInventory() instanceof CraftingInventory && event.getSlot() < 10 && event.getSlot() > 0) {
                CraftingInventory inventory = (CraftingInventory) event.getInventory();
                ItemStack[] items = inventory.getMatrix();
                items[event.getSlot() - 1] = event.getCursor();
                if (items[0].getType() == bla bla bla && ... && ... && ... && list.contains(namespacedKey)) {
                  //add the shaped recipe here 
                  // the namespacedkey is unique by putting all the item[x].getType().toString() inside it 
                 // add the namespacedkey to a map or a list and check before in the if or you will have duplicate recipe exception
                }
    }
     
  16. Offline

    Machine Maker

    Yeah thats kinda what I had in mind in my initial comment. It would be much simpler
     
Thread Status:
Not open for further replies.

Share This Page