Solved BlockBreakEvent remove drops without canceling?

Discussion in 'Plugin Development' started by Snowybearr, Jun 23, 2014.

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

    Snowybearr

    So the title pretty much says it all. Is it possible to remove drops from a BlockBreakEvent without canceling the event?

    Here is what I am using currently:
    Code:java
    1. event.setCancelled(true);
    2. event.getBlock().setTypeId(Material.BEDROCK.getId());

    But it breaks 2 other plugins we have that must have (ignoreCancelled = true). So it can't cancel the event.

    I've gone through many topics asking this same question with it never being solved, so wasn't sure it was even possible but figured I would ask.
     
  2. Offline

    qlimax5000

    Try:
    Code:java
    1. event.getBlock().getDrops().clear();
     
  3. Offline

    St3venAU

    I don't think there is a super easy way to change the drops from within the BlockBreakEvent. One way I can think of doing it is to record what the drops will be and remove any of those drops close to the block's location a very short time after the block break. Something like this (untested, so it may need tweaking):
    Code:java
    1. final Block block = event.getBlock();
    2. final Collection<ItemStack> drops = block.getDrops();
    3. new BukkitRunnable() {
    4. @Override
    5. public void run() {
    6. Entity e = block.getWorld().spawnEntity(block.getLocation(), EntityType.WITHER_SKULL);
    7. for(Entity ent : e.getNearbyEntities(1.0, 1.0, 1.0)) {
    8. if(ent instanceof Item && drops.contains(((Item)ent).getItemStack())) {
    9. ent.remove();
    10. }
    11. }
    12. e.remove();
    13. }
    14. }.runTaskLater(plugin, 1L);

    The wither skull entity is only spawned so that we can easily get the nearby entities. I wish the Location class also had a getNearByEntities method.

    I believe that getDrops() only return a copy of the list of drops and that modifying it has no effect.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 9, 2016
  4. Offline

    Snowybearr

    qlimax5000
    As St3venAU said, it is indeed just a copy sadly.

    St3venAU
    So there isn't really a 'clean' way of doing it then huh? I'm pretty surprised honestly, there is just dozens of threads related to this issue, when it comes to block drops and removing them. People always have to do it in an odd or sloppy kind of way, you'd think Bukkit would have more support for it at this point.
     
  5. Offline

    Protophite


    Horrible way to do it... Just do this:


    Code:
        @EventHandler
        public void test(BlockBreakEvent e){
            Location l = e.getBlock().getLocation();
            e.getPlayer().getWorld().getBlockAt(l).setType(Material.AIR);
        }
    Snowybearr

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 9, 2016
    Snowybearr likes this.
  6. Offline

    St3venAU

    I considered this method but I believe that it may interfere with protection plugins, if a protection plugin cancels the event due to the player not having permission to break the block it will already be too late because the block has already been deleted.
     
  7. Offline

    RawCode

    St3venAU
    this is special case, read javadocs or source.
     
  8. Offline

    desht

    Define your event handler with ignoreCancelled=true and priority=EventPriority.MONITOR. Any event which reaches the MONITOR phase without being cancelled can be considered as definitely going to happen.
     
  9. Offline

    RawCode

    desht
    Bukkit still allows to change event outcome at monitor stage, it will fefinely happen only if all installed plugins follow the rules.
     
  10. Offline

    desht

    Yeah, but any plugin which modifies an event outcome in the MONITOR phase can go die in a fire as far as I'm concerned :)

    In other words: you should feel absolutely free to rely on uncancelled events actually happening once you're in the MONITOR phase; if some other plugin is breaking the rules, the problem is with that plugin, and not your plugin. The possibility that a few foolish developers may break the rules should not prevent anyone from writing code that takes advantage of said rules.
     
  11. Offline

    Protophite

    You're right, it does interfere with worldguard. :S I'm sure there's an easier way to do it, then the one you posted.

    1Rogue is there a way to do it without intefering with worldguard or any other protection plugin?

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 9, 2016
  12. Offline

    St3venAU

    I agree, it's not elegant, but it was the only way I could think to do it without the possibility of breaking other plugins.
     
  13. Offline

    RawCode

    setting priority over worldguard or other plugin that does same and ignoring cancelled events....

    i will repeat - read javadocs on bbevent and related things.
     
  14. Offline

    Protophite

    Found a solution so the event doesn't interfere with protection plugins. St3venAU Snowybearr
    Code:
    @EventHandler (priority = EventPriority.MONITOR)
    public void bbevent(BlockBreakEvent e){
        if(e.isCancelled()) return;
        e.getPlayer().getWorld().getBlockAt(e.getBlock().getLocations()).setType(Material.AIR);
    }
     
  15. Offline

    desht

Thread Status:
Not open for further replies.

Share This Page