Few questions about items and drops

Discussion in 'Plugin Development' started by Rddi, Mar 11, 2020.

Thread Status:
Not open for further replies.
  1. Hello everybody!
    I have a few questions about items and drops .

    First question:
    Is it possible to edit the ItemMeta of drops of blocks? I already tried this one:
    Code:
    e.setCancelled(true);
                        Material mat = e.getBlock().getType();
                        Location loc = e.getBlock().getLocation().add(0.5, 0, 0.5);
                        byte data = e.getBlock().getData();
                        e.getBlock().setType(Material.AIR);
                        if(player.getGameMode() != GameMode.CREATIVE){
                            loc.getWorld().dropItemNaturally(loc, new ItemAPI(mat, (byte)data, 1, "§8§m------------", "§a§lNormal").build());
                        }
    This is code from the BlockBreakEvent. I tried to add a lore to the items, that I broke, but if I break grass with my hand I get a grass block. How can you make sure that you get the natural drops and not the block itself?
    So instead of grass a dirt block? But the block must have the lore.

    Second question:
    How can I set the lore to items, that will be crafted (CraftItemEvent)? So if I put 4 planks in my crafting field the workbench should already have the lore in the output field.
    I tried this but it doesn't work:
    Code:
    ItemMeta itemMeta = e.getRecipe().getResult().getItemMeta();
                        List<String> lore = new LinkedList<>();
                        lore.add("§8§m------------");
                        lore.add("§a§lNormal");
                        itemMeta.setLore(lore);
                        e.getRecipe().getResult().setItemMeta(itemMeta);
                        player.updateInventory();
    And one last question:
    How can I make custom recipes for items with more than one item per itemstack? Because I cant set an amount for the ingredients (ShapedRecipe):
    Code:
    r.setIngredient('#', Material.DIRT);
    I could not find anything about it on the internet.

    I know, thats a lot of questions. But it would be really nice if someone could help me.
    And sorry about my english.. Its not that good.
     
  2. Offline

    CraftCreeper6

    @Rddi
    For the first question:
    Block.getDrops() might be a way to do it, though I'm not sure how well this would work with things like gravel which also drop flint.

    As for the last question:
    I don't think this is possible in a nice way. The best way I can think is listen for InventoryClickEvent (or maybe even PrepareItemCraftEvent but I'm not sure about that one) and check the itemstacks that way.
     
  3. @CraftCreeper6
    Thanks for your answer. But how can I change the ItemMeta of drops of .getDrops()? I've read on the Internet that this probably won't work.
     
  4. Offline

    CraftCreeper6

    @Rddi
    Create a new ItemStack with the same material and amount; then set the lore from there and use World.dropItemNaturally() to drop the item like breaking the block would.
     
  5. @CraftCreeper6
    Okay, but then I have to do this for every single block in minecraft
     
  6. Offline

    CraftCreeper6

    @Rddi
    Not true, get the block using event#getBlock()#getDrops(), iterate over each one, create a new ItemStack with the same type as the iterative value and same quantity too, then set the lore etc... and drop that item.
     
  7. @CraftCreeper6
    I think I did something wrong. Sorry, I have never done something like this before.
    This is my current code:
    Code:
    e.setCancelled(true);
                        e.getBlock().setType(Material.AIR);
                        Material mat = e.getBlock().getType();
                        Location loc = e.getBlock().getLocation().add(0.5, 0, 0.5);
                        byte data = e.getBlock().getData();
                        for(ItemStack i : e.getBlock().getDrops()){
                            ItemMeta meta = i.getItemMeta();
                            List<String> lore = new LinkedList<>();
                            lore.add("§8------------");
                            lore.add("§f§lNormal");
                            meta.setLore(lore);
                            i.setItemMeta(meta);
                            if(player.getGameMode() != GameMode.CREATIVE){
                                loc.getWorld().dropItemNaturally(loc, i);
                            }
                        }
     
  8. Offline

    CraftCreeper6

    @Rddi
    Create a copy of the ItemStack, and typically, an ArrayList rather than a LinkedList would be better.
     
  9. I probably didn't do it right again. What do you mean with copy? A new ItemStack like "ItemStack new = old"?:
    Code:
    e.setCancelled(true);
                        e.getBlock().setType(Material.AIR);
                        Material mat = e.getBlock().getType();
                        Location loc = e.getBlock().getLocation().add(0.5, 0, 0.5);
                        byte data = e.getBlock().getData();
                        for(ItemStack i : e.getBlock().getDrops()){
                            ItemStack copy = i;
                            ItemMeta meta = copy.getItemMeta();
                            List<String> lore = new ArrayList<>();
                            lore.add("§8------------");
                            lore.add("§f§lNormal");
                            meta.setLore(lore);
                            i.setItemMeta(meta);
                            if(player.getGameMode() != GameMode.CREATIVE){
                                loc.getWorld().dropItemNaturally(loc, i);
                            }
                        }
    It happens nothing. The block will be removed but nothing will drop..
     
  10. Offline

    caderapee

    @Rddi use itemstack.clone()
     
  11. Offline

    CraftCreeper6

    @Rddi
    Do as @caderapee suggested, but also, make sure you're not in creative mode :)

    Consider adding debugs if all else fails.
     
  12. Offline

    Machine Maker

    @Rddi Regarding your question about setting the output of crafting to have lore (or any item meta), using e.getRecipe().getResult() just gets a copy of the result, not the actual result. So yes, what you could do, is change the actual recipe to give the item stack as a result. But that wouldn't be that dynamic (which idk if you need).
     
  13. @caderapee , @CraftCreeper6
    I think I am too stupid for doing this. This is my current code but it still doesn't work:
    Code:
    e.setCancelled(true);
                        e.getBlock().setType(Material.AIR);
                        Material mat = e.getBlock().getType();
                        Location loc = e.getBlock().getLocation().add(0.5, 0, 0.5);
                        byte data = e.getBlock().getData();
                        for(ItemStack i : e.getBlock().getDrops()){
                            ItemStack copy = i.clone();
                            ItemMeta meta = copy.getItemMeta();
                            List<String> lore = new ArrayList<>();
                            lore.add("§8------------");
                            lore.add("§f§lNormal");
                            meta.setLore(lore);
                            copy.setItemMeta(meta);
                            if(player.getGameMode() != GameMode.CREATIVE){
                                loc.getWorld().dropItemNaturally(loc, copy);
                            }
                        }
    I guess I didn't do the clone of the itemstack right. And I am sure that I am not in creative mode.
     
  14. Online

    timtower Administrator Administrator Moderator

    @Rddi Does it fire at all? Could you add a printline with the dropItemNaturally call?
     
  15. Offline

    CraftCreeper6

    @Rddi
    These are theoretical and likely not the problem but still worth a try:
    Cancel the event after you run the code.
    Set the block to air after you run the code, not before.
     
  16. Online

    timtower Administrator Administrator Moderator

    Then print what gamemode the user is in before the gamemode check gets called.
     
  17. @timtower
    I added some messages in my code:
    Code:
    e.getBlock().setType(Material.AIR);
                        player.sendMessage("a");
                        Material mat = e.getBlock().getType();
                        Location loc = e.getBlock().getLocation().add(0.5, 0, 0.5);
                        byte data = e.getBlock().getData();
                        for(ItemStack i : e.getBlock().getDrops()){
                            player.sendMessage("b");
                            ItemStack copy = i.clone();
                            ItemMeta meta = copy.getItemMeta();
                            List<String> lore = new ArrayList<>();
                            lore.add("§8------------");
                            lore.add("§f§lNormal");
                            meta.setLore(lore);
                            copy.setItemMeta(meta);
                            player.sendMessage("Gamemode:" + player.getGameMode().name());
                            if(player.getGameMode() != GameMode.CREATIVE){
                                loc.getWorld().dropItemNaturally(loc, copy);
                                player.sendMessage("c");
                            }
                        }
    Only message "a" is sent.
     
  18. Online

    timtower Administrator Administrator Moderator

    @Rddi Try looping over the drops of the event instead.
    Apparently the block has no drops.
     
  19. @timtower How can I do this? The block I broke was a clay block. It should drop clay.
     
  20. Online

    timtower Administrator Administrator Moderator

    That the method exists, does not mean that it is fully implemented.
    What event are we even looking at?
     
  21. @timtower we are looking at the BlockBreakEvent.
     
  22. Offline

    CraftCreeper6

    @Rddi
    The problem is exactly as I predicted here
    When you set the block to air, it also updates the reference that the event holds, for this reason, the block will always drop nothing as it's air. So, all you need to do is move the
    Code:
    block#setType(Material#AIR)
    after you run everything else and it will work. (I just tested it!)
     
    timtower likes this.
  23. Online

    timtower Administrator Administrator Moderator

    Nice catch there, didn't even think of that one.
     
    CraftCreeper6 likes this.
Thread Status:
Not open for further replies.

Share This Page