List<Block> size returning 0..

Discussion in 'Plugin Development' started by Cryices, Feb 3, 2014.

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

    Cryices

    Hello, I've had some problems with this. for some reason, my removed.size() gives me 0, when I know that the explosion destroyed some blocks! any help?
    The error I'm getting is
    Code:
     java.lang.IllegalArgumentException: n must be positive
    at java.util.Random.nextInt(Unknown Source) ~[?:1.7.0_21] 
    This is the code:

    Code:
        @EventHandler
        public void onEntityExplode(EntityExplodeEvent e) {
            final List<Block> removed = e.blockList();
            new BukkitRunnable() {
                public void run() {
                        Random random = new Random();
                        int choice = random.nextInt(removed.size());
                        Block block = removed.get(choice);
                        //Do stuff with block
                }
            }.runTaskTimer(this, 0L, 10L);
        }
    I know that the returned list size is 0 because when I add in if(removed.size() > 0){, nothing happens
     
  2. Offline

    Superckl1

    Cryices

    Why are you running it in a timer? I would imagine that could cause your problem. Are you trying to wait until after the explosion event is done?
     
  3. Offline

    Cryices

    I want to slowly regen the blocks, so that's why I have the delay for each block being put back :)
     
  4. Offline

    Superckl1

    I imagine that after the event is done, the blocklist is cleared. Try changing your removed List to:
    Code:java
    1. new LinkedList<Block>(e.blockList());

    This creates a "defensive" copy of the list that won't be affected by the original list being cleared by Minecraft.

    Keep in mind, I'm just guessing. :p
     
  5. Offline

    Cryices

    Thanks, but I don't think that'll fix the problem I'm having :p
     
  6. Offline

    Superckl1

    Did you even try it :confused:

    In your Runnable and at the beginning of the method, print out the size of the list. Is it 0 initially or 0 when the Runnable runs? I think a delay of 0 will cause the Runnable to run the next tick (I know calling runTask does).
     
  7. Offline

    Cryices

    Fail :p I tried both, it turns out it's not returning 0, it's just not doing anything xP it's weird though, it returns 52 each time.. I don't know why that is, there's no way it could be destroying 52 blocks
     
  8. Offline

    Superckl1

    Cryices
    Can I see your code to restore the blocks?
     
  9. Offline

    Cryices

    Code:
        public static void regenerate(Block block){
            final Material type = block.getType();
            final byte data = block.getData();
            final Location loc = block.getLocation();
            final int id = type.getId();
            new BukkitRunnable(){
                @Override
                public void run(){
                    loc.getBlock().setTypeIdAndData(id, data, false); //Setting the block type
                }
            };
        };
    :p
    I'm going to instead of saving the blocks in a list, try saving the blockstate in an arraylist..
     
  10. Offline

    Superckl1

    Cryices

    Here's another hypothesis:

    Blocks are objects that are not garbage collected until they are unloaded. The type id is simply changed. You will have to copy the original type id of the block into a collection for use in your Runnable (Do it in the event listener, not in the runnable). Right now, you are just setting the block to air. Perhaps a Map of Location to Integer or something similar?
     
  11. Offline

    The_Doctor_123

  12. Offline

    Superckl1

    The_Doctor_123

    The Blocks will still reference the original ones...
     
  13. Offline

    Cryices

    Just an update, I tried saving the BlockState to an arraylist, just incase saving the block that way wasn't working somehow, but it still didn't work :/
     
  14. Offline

    Superckl1


    Code:java
    1. @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
    2. public void onEntityExplode(EntityExplodeEvent e){
    3. final List<BlockState> removed = new LinkedList<BlockState>();
    4. for(Block block:e.blockList())
    5. removed.add(block.getState());
    6. new BukkitRunnable() {
    7.  
    8. private Random random = new Random();
    9.  
    10. @Override
    11. public void run() {
    12. int i = random.nextInt(removed.size());
    13. BlockRegen.this.regenerate(removed.get(i));
    14. removed.remove(i);
    15. }
    16. }.runTaskTimer(this, 1L, 10L);
    17. }
    18.  
    19. public void regenerate(BlockState state){
    20. Block block = state.getLocation().getBlock();
    21. block.setType(state.getType());
    22. block.setData(state.getData().getData());
    23. }

    Tested and working. Not sure why yours isn't.
     
  15. Offline

    Cryices

    Well thanks, I just will use yours, and also for future reference I'm sure you just forgot it, but make sure to cancel the runnable xD, in this case I used if(removed > 0){}else this.cancel();
     
  16. Offline

    Superckl1

    Cryices

    I wrote it in a rush. :p Glad I could help.
     
    Cryices likes this.
  17. Offline

    Cryices

    Sorry to ask more of this, but now I need to do a bukkitrunnable again :p, but a little while after the first one, I tried many different ways, but the closest I got was this, by closest I got I mean no errors, I tried to do like event.wait(time..) and Thread.sleep(time..) but neither of those work, this is the code I have now
    Code:
                Bukkit.getScheduler().runTaskLater(this, (Runnable) new BukkitRunnable() {
                    private Random random = new Random();
                    @Override
                    public void run() {
                        if(items.size() > 0){
                            int i = random.nextInt(items.size());
                            regenerate(items.get(i));
                            items.remove(i);
                        }else
                            this.cancel();
                       
                    }
                }.runTaskTimer(this, 1L, 10L)
            , 1200L);
            }
    suggestions on how to fix anyone?.
     
  18. Offline

    Superckl1

    Cryices
    Don't call sleep or wait on the main thread! I cringe when people do that :p

    I'm a little confused by your question. What do you mean after the first one? Right now it looks like you are just running the first one a bit later. What exactly are you trying to do?
     
  19. Offline

    Cryices

    well I have that first Bukkit runnable that regens the blocks, but now I need another one, and this one is for another list, and its supposed to happen after the first runnable is over.
     
  20. Offline

    Superckl1

    Cryices
    When you call cancel in the first Runnable, schedule the next one?
     
  21. Offline

    Cryices

    I tried that, it wasn't pretty..there were alot of errors with the this.plugin or where "this" is, and also, it didn't work, if you really think about it, you know why :p
     
  22. Offline

    Superckl1

    Cryices
    I've done it before. If you are in an Runnable, do ClassName.this.object to reference objects in the enclosing class.
     
Thread Status:
Not open for further replies.

Share This Page