Solved Breaking block with no drops

Discussion in 'Spigot Plugin Development' started by Rixterz, Jun 15, 2016.

  1. Hi

    I'd like to create the same effect with a plugin as breaking a block in creative; you see the block break, you see the particles, and there are no drops. Block#breakNaturally() still gives drops - how can I remove them?
     
  2. You could probably listen for BlockBreakEvent, cancel it and set the broken block's type to air.
     
    • Agree Agree x 1
  3. The BlockBreakEvent doesn't get fired from that


    FYI the class implements Listener
    it's been registered in the plugin manager
    and has @EventHandler above, so it definitely doesn't get fired
     
  4. I see, I misinterpreted your question. Let me search some more, will edit in a bit.

    Edit: I tried looking around some more, but I can, as of yet, not find anything. I'll hop on my PC in a short while to search again. Will edit then.
     
    #4 datdenkikniet, Jun 15, 2016
    Last edited: Jun 15, 2016
  5. You could probably give this method a shot: on block-interact get the block, use Block#getDrops().clear(), and then Block#breakNaturally() (not sure if it works, but it might have some effect)
     
  6. No players are breaking blocks. The breaking is done in code, so there is no interaction
     
  7. Then replace the "block-interact get block" part with your own way of getting the block that should be broken :)
     
  8. Block#setType(Material.AIR)
     
  9. You want the blocks to break like the players are in creative? So after one left-click? Then datdenkikniets way should work. The events name is PlayerInteractEvent. Check for left- or right-click: if(e.getAction() == Action.LEFT_CLICK_BLOCK)
    Then clear the drops and break the block in the code.
     
  10. Imagine a block just breaking in front of your eyes and having no drops. I want that to happen. No players are involved whatsoever, nobody is touching the blocks. I just want the block to break on its own through code, meaning have the block break particles, do the relevant sound etc
     
  11. I had a similar situation with one of my plugins, except I wanted the drops to drop, but I wanted to add metadata to them to contain the user's uuid that broke the block so I could prevent other players from picking up those drops. Sadly, there is no clean way to get ahold of these drops. Let me explain:

    Block#getDrops() returns a copy of what might drop. It's not a guarantee, and its most definitely not the items that actually drop. You can clear this list all day long if you want, but its not going to effect the actual dropped items. So thats out of the question.

    BlockBreakEvent doesnt have a way of getting the drops, either. The methods just simply dont exist. So thats a bummer.

    Block#breakNaturally() doesnt even return a list of drops either, which is highly annoying. You would think it would return that instead of a boolean. But oh well. Bad foresight on whoever made that method.

    So, what was my solution? The idea was simple, but the implementation is messy. Maybe someone can think of a better way (I'm all ears):

    What I did was add the Location of the block that's breaking to a Set, and I started a 5 tick timer (could probably be 1 or 2 ticks, but I left room for error). This timer would simply remove that Location from the Set when it fired. On the ItemSpawnEvent I simply checked the location the item is spawning at to see if its in that Set. If it is, this is a dropped item I wanted. This is where I simply added my metadata (my Set was actually a Map<Location, UUID>, but you dont need UUID so a Set is sufficient), but you would want to cancel it from ever spawning.

    Simple. Effective. Dirty.
     
    #11 BillyGalbreath, Jun 16, 2016
    Last edited: Jun 16, 2016
    • Informative Informative x 2
    • Useful Useful x 1
  12. Another possible way around this would be using the doTileDrops gamerule. You could set it to false, then break the block using Block#breakNaturally(), then set the gamerule back to true.
     
  13. Changing the gamerule back would have to be delayed by a tick or two (at minimum). The drops spawn after the BlockBreakEvent has fired (this is why there are no drop methods in the event). So changing the gamerule and then back in the event will have no effect other than adding cpu and disk i/o. Also, have to be careful because this is a global setting. If your goal is to be specific to something (like only working on 1 player or 1 tool used) you will accidentally be destroying drops from other players that may be breaking blocks at the exact same time elsewhere in the same world. ;)
     
    • Informative Informative x 1
  14. Block#breakNaturally() just gets rid of the chest. I want it to do the sound of being broken and also for the particles to appear. As if an invis player broke it
     
  15. You can play effects and sounds at will.

    http://wiki.vg/Protocol#Block_Break_Animation

    world.playSound(location, Sound.BLOCK_STONE_BREAK, 1F, 1F);
     
  16. Code (Text):
    World#playEffect(location, Effect.TILE_BREAK, material);
    This will show the particles of the block breaking, I don't think it plays a sound though.
     
  17. Effect.TILE_BREAK doesn't exist
     
  18. What jar file version are you using? I just decompiled a spigot 1.10 jar & it's definitely in there.