0

Here's my snippet of code. I have Lists for the blocks and player. All I need is for after the five seconds in that runnable is up, it'll replace the blocks that were previously replaced, assigning a player to get the blocks.

    @EventHandler
public void onSnowballHit(ProjectileHitEvent e) {
    // If it's a snowball...
    if (e.getEntity() instanceof Snowball) {
        Snowball snowball = (Snowball) e.getEntity();

        final Player p = (Player) snowball.getShooter();

        // ...if a player threw it...
        if (snowball.getShooter() instanceof Player) {
            // Make a Player from the Entity

                        BlockIterator iterator = new BlockIterator(e.getEntity().getWorld(),
                                e.getEntity().getLocation().toVector(), e.getEntity().getVelocity().normalize(),
                                0.0D, 4);

                        // Make a block
                        Block hitBlock = null;

                        // Loop through possible blocks
                        while (iterator.hasNext()) {
                            // Set the hitBlock to the current block we're checking
                            hitBlock = iterator.next();

                            // If it's not air, STOP!
                            if (!hitBlock.getType().equals(Material.AIR)) {
                                break;
                            }
                        }
                        int min = 1;
                        int max = 15;
                            Random r = new Random();

                            byte clayBlocks = (byte) (r.nextInt(max - min + 1) + min);

                            paintBlockList.add(hitBlock);
                            painters.add(p);
                            // Set it to stained clay
                            hitBlock.setType(Material.STAINED_CLAY);

                            // red = 14, blue = 11 (data values)
                            hitBlock.setData(clayBlocks);
                            Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
                                public void run(){
                                    if(painters.contains(p)){
                                        painters.remove(p);

                                    }
                                }
                            }, 100);

                     }
                   }    
                }
Unihedron
  • 10,902
  • 13
  • 62
  • 72

1 Answers1

0

You could do it the same way you remove the Player from the painters list. Once you've found the first solid block (hitBlock) create a new final reference so that you can access it in the Runnable, for example like this:

final Block solidBlock = hitBlock;

To return the block to the state it was before you changed its type and data, you could keep track of those attributes:

final byte previousData = solidBlock.getData();
final Material previousType = solidBlock.getType();

Then in your run() method you can simply change the block back if it is still at that point different like so:

if (solidBlock.getType() != previousType) {
    solidBlock.setType(previousType);
}

if (solidBlock.getData() != previousType) {
    solidBlock.setData(previousData);
}

I'm sure there's a cleaner, nicer way to do it but this might be good enough for your purposes (I did find a glitch where if you throw two snowballs at the same block, it won't revert to the true original block but to a stained clay block because of the way the future Runnable tasks are written here, to fix this you'd need to write this completely differently and keep track of more things).

Adrian Sohn
  • 1,271
  • 8
  • 10
  • intresting, is their a specific reason these variables are finals? Does bukkit require this? – Ashwin Gupta Dec 01 '15 at 04:29
  • Java requires it as far as I understand it, here's an answer on SO that might help: http://stackoverflow.com/questions/11424753/why-do-variables-passed-to-runnable-need-to-be-final – Adrian Sohn Dec 01 '15 at 04:31
  • oh okay thanks. I never realized that. I guess its because I never passed a variable through Runnable. (New to multithreading, plus I normally just extend Thread) – Ashwin Gupta Dec 01 '15 at 04:33
  • I'll try this later. Will I need to store the solidBlocks in a List though? – AppleBabies Dec 01 '15 at 18:10
  • Depends! :) Like mentioned in the answer, there is a glitch/race condition with this method but if that's not a big problem you won't need any lists. If you want to remove that glitch you'll probably need more than just a list. – Adrian Sohn Dec 03 '15 at 08:12