MucaP MucaP - 17 days ago 9
Java Question

bukkit - Drop prevention not working?

In my Bukkit plugin I want to remove player's capacity to drop certain itens, but I also want to clean all the drops except por the ones that I want to cancel, for example: The player can't drop a sword, but when he drops a Mushroom Soup empty bowl, then clean the drop. I have two listener classes registered on the main.

Listeners:

@EventHandler
public void onPlayerDropItem(PlayerDropItemEvent e) {
e.getItemDrop().remove();
}


PreventDropping:

@EventHandler(priority = EventPriority.HIGH, ignoreCancelled=false)
public void onPlayerDropItem(PlayerDropItemEvent e) {
if(e.getItemDrop().equals(new ItemStack(Material.MUSHROOM_SOUP))
|| (e.getItemDrop().equals(new ItemStack(Material.DIAMOND_SWORD)))
|| (e.getItemDrop().equals(new ItemStack(Material.IRON_SWORD)))
|| (e.getItemDrop().equals(new ItemStack(Material.TNT)))
|| (e.getItemDrop().equals(new ItemStack(Material.ARROW)))
|| (e.getItemDrop().equals(new ItemStack(Material.BOW)))
|| (e.getItemDrop().equals(new ItemStack(Material.WOOD_SWORD)))
|| (e.getItemDrop().equals(new ItemStack(Material.STONE_SWORD))))
{
e.setCancelled(true);
}
}


Main (onLoad part):

@Override
public void onEnable() {
System.out.println("Main plugin enabled");
getCommand("pvp").setExecutor(new PvP(this));
getCommand("instakiller").setExecutor(new InstaKiller(this));
getCommand("wizard").setExecutor(new Wizard(this));
getCommand("archer").setExecutor(new Archer(this));

getServer().getPluginManager().registerEvents(new Listeners(this), this);
getServer().getPluginManager().registerEvents(new PreventDropping(this), this);
}


Sadly the server just ignores my second listener, and cleans all drops instead of making it impossible to drop the itens listed in PreventDropping. What is wrong?

Additional question: Arrows bug, as described in the comments.

@EventHandler
public void onPlayerDropItem(PlayerDropItemEvent e) {
if(e.getItemDrop().getItemStack().getType() == Material.DIAMOND_SWORD ||
(e.getItemDrop().getItemStack().getType() == Material.IRON_SWORD) ||
(e.getItemDrop().getItemStack().getType() == Material.STONE_SWORD) ||
(e.getItemDrop().getItemStack().getType() == Material.WOOD_SWORD) ||
(e.getItemDrop().getItemStack().getType() == Material.TNT) ||
(e.getItemDrop().getItemStack().getType() == Material.BOW) ||
(e.getItemDrop().getItemStack().getType() == Material.ARROW) ||
(e.getItemDrop().getItemStack().getType() == Material.BLAZE_ROD)) {
e.setCancelled(true);
} else {
e.getItemDrop().remove();
}
}

Answer

If I understood you right, you want to disable the function to drop example mushroom soup, and remove all other items a player tries to drop. If so, why use two PlayerDropItemEvent? Also there is no need to create a new ItemStack object everytime you want to make the check, simply use:

@EventHandler
public void onPlayerDropItem(PlayerDropItemEvent e) {
    if(event.getItemDrop().getItemStack().getType() == Material.MUSHROOM_SOUP)) 
        ... bla bla ...
    {
        e.setCancelled(true);
    } else {
        e.getItemDrop().remove();
    }
}

This code will cancel the drop event if the item is a mushroom soup, else it will remove the drop.

The problem with your code is that both listeners will run no matter what. This means the drop will be removed even though it's a mushroom soup.