Solved Delayed Block Regeneration after explosion

Discussion in 'Spigot Plugin Development' started by jacklin213, Feb 14, 2019.

  1. Hey guys,

    Just trying to figure out how I can do a delayed block regeneration after an explosion. I believe I can use BlockExplodeEvent#blockList to get the blocks that were destroyed. But I am unsure as to how I would restore it. BlockState? BlockData? or Both

    Regards
    Jack
     
  2. I think you should use BlockState.

    Probably just create a bukkit runnable that iterates through a list of exploded blocks and from there you'd set the blocks back to their type.
     
  3. Create a class "BlockRestorer" make it extend thread then on BlockExplodeEvent get the block list pass it to blockrestorer and then start it (I assume you know how to use threads?)
    in the run function do a loop through the blocklist restoring the block with the lowest y vaules first (You can use wait(100); to delay 1/10th of a second)
    You can also use a runnable but i always used threads but i imagine its better to use runnables
     
    • Like Like x 1
  4. something like this?
    Code (Java):
    final List<Block> blockList = event.blockList();
    Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
        @Override
        public void run() {
            for (Block block : blockList) {
                block.setType(block.getState().getType());
            }
        }
    }, 100);
     
    • Agree Agree x 1
  5. Try it?
     
    • Like Like x 1
  6. I'll give it a go once i get home :), currently coding on a phone LOL
     
  7. That should work tho, if it don't try to save the location instead. Because the affected block is no longer on the world it could throw npe
     
  8. Yes, it will not work because block#getType = AIR. You need to store the state (type+data+extra) with the location or block in a hashmap and use this variable to restore state;
     
    • Agree Agree x 1
  9. Just store the BlockState instead, in a List, and call BlockState::update to restore the block.
     
    • Informative Informative x 1
  10. Use EntityExplodeEvent instead of BlockExplodeEvent, this event will be called by every exploding entities (creeper/tnt/tnt minecart)
     
    • Informative Informative x 2
  11. Thanks but I don't think I would use that in this case because I am generating the explosion myself using World#createExplosion method
     
    • Agree Agree x 1
  12. For anyone that wanted to know the solution to the problem it was as follows
    Code (Java):
    @EventHandler
        public void onExplosion(BlockExplodeEvent event) {
            final List<BlockState> destroyedBlockStates = event.blockList().stream().map((Function<Block, BlockState>) block -> {
                return block.getState();
            }).collect(Collectors.toList());

            Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
                @Override
                public void run() {
                    for (BlockState state : destroyedBlockStates) {
                        state.update(true);
                    }
                }
            }, 100);
        }
    Tested and works for signs, chests (with items in it). There is probably a better way around this. But i found after testing that this was the most simple way.

    Open to discussion
     
  13. Do you now that you can just use clear() ;
     
  14. He just want to regenerate destroyed area later not "cancel" it
    Btw @jacklin213 your code can be "minimized"

    Code (Java):
    @EventHandler
    public void onBlockExplode(BlockExplodeEvent e)
    {
        List<BlockState> states = e.blockList().stream().map(Block::getState).collect(Collectors.toList());
        Bukkit.getScheduler().runTaskLater(this, () ->
        {
            for (BlockState state : states)
            {
                state.update(true);
            }
        }, 100L);
    }
     
    #14 FrozenLegend, Feb 20, 2019
    Last edited: Feb 20, 2019
  15. Or you can just clear the block list lol
     
  16. What don't you understand in "Delayed Block Regeneration"
     
  17. RunTaskLater? Loop through a list of the blocks and set them back?