Delayed Regeneration method not working?

Discussion in 'Plugin Development' started by lewysryan, Jun 4, 2014.

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

    lewysryan

    So I want blocks to come back one after another after an explosion. So I tried this:
    Code:java
    1. package com.lewys.davies;
    2.  
    3. import java.util.HashMap;
    4.  
    5. import org.bukkit.Bukkit;
    6. import org.bukkit.Effect;
    7. import org.bukkit.Location;
    8. import org.bukkit.Material;
    9. import org.bukkit.Sound;
    10. import org.bukkit.block.Block;
    11. import org.bukkit.block.BlockState;
    12. import org.bukkit.event.EventHandler;
    13. import org.bukkit.event.Listener;
    14. import org.bukkit.event.entity.EntityExplodeEvent;
    15. import org.bukkit.plugin.java.JavaPlugin;
    16.  
    17. public class Main extends JavaPlugin implements Listener {
    18.  
    19. public void onEnable()
    20. {
    21. Bukkit.getPluginManager().registerEvents(this, this);
    22. task();
    23. }
    24.  
    25. HashMap<BlockState, Long> blocks = new HashMap<>();
    26.  
    27. public void task(){
    28. Bukkit.getScheduler().scheduleSyncRepeatingTask(this, new Runnable(){
    29.  
    30. @SuppressWarnings("deprecation")
    31. @Override
    32. public void run()
    33. {
    34. for(BlockState s : blocks.keySet())
    35. {
    36. long diff = (System.currentTimeMillis() - blocks.values().size()) / 1000;
    37.  
    38. if(diff < 0){
    39. s.update();
    40. blocks.remove(s);
    41.  
    42. Location loc = s.getBlock().getLocation();
    43. Block b = s.getBlock();
    44. loc.getWorld().playEffect(loc, Effect.STEP_SOUND, b.getTypeId());
    45.  
    46. return;
    47.  
    48. }
    49. }
    50. }
    51. }, 0, 20);
    52. }
    53.  
    54. @EventHandler
    55. public void blockblowup(EntityExplodeEvent e)
    56. {
    57. long time = 3;
    58.  
    59. for(Block b : e.blockList())
    60. {
    61. time++;
    62. final BlockState state = b.getState();
    63. blocks.put(state, time);
    64. }
    65. }
    66. }
    67.  


    With no luck. Anyone know why this doesn't work? Thanks for any help!
     
  2. Offline

    NathanWolf

    What does it do? Throw a ConcurrentModificationException? Not work? All of the above?

    Ah, ok, I think I see what you're after - this bit:

    Code:
    for(BlockState s : blocks.keySet())
                    {
                        long diff = (System.currentTimeMillis() - blocks.values().size()) / 1000;
    
    Is not doing what you want, I think. Should be more like

    Code:
    for(Map.Entry<BlockState, Long> entry : blocks.entrySet())
                    {
                        long diff = (System.currentTimeMillis() - entry.value()) / 1000;
    
    .. unless you were really trying to base a delay off of how big the list is- but I kind of think not?

    I'm also not sure you can modify a Map while iterating over it like that. And, finally, this is more of a design thing than an "it won't work thing" - this is kind of an abuse of Map, and a waste of the hashing it's doing under the hood. All you really want here is a List of objects that have a BlockState and timestamp.

    If you wanted to get really fancy, you could make an Object that implements Comparable (using the timestamp field as the sort key) and then store your data in a TreeSet. Using this method, you can stop iterating the first time you hit an object that's not ready to be restored, rather than having to loop through your whole list every time the scheduler fires.

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

    lewysryan

    NathanWolf
    I basicly want to do this:
    Code:java
    1.  
    2. //Credit to pogostickdev29, I just added the random regen times to try to explain what I mean
    3.  
    4. public class Main extends JavaPlugin implements Listener {
    5.  
    6. public void onEnable()
    7. {
    8. Bukkit.getPluginManager().registerEvents(this, this);
    9. }
    10. @EventHandler
    11. public void onEntityExplode(EntityExplodeEvent e) {
    12. for (final Block b : e.blockList()) {
    13.  
    14. final BlockState state = b.getState();
    15.  
    16. b.setType(Material.AIR);
    17.  
    18. int delay = (int) (Math.random() * (200 - 500 +1)) + 300;
    19.  
    20. if ((b.getType() == Material.SAND) || (b.getType() == Material.GRAVEL)) {
    21. delay += 1;
    22. }
    23.  
    24. Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
    25. @SuppressWarnings("deprecation")
    26. public void run() {
    27. state.update(true, false);
    28. b.getLocation().getWorld().playEffect(b.getLocation(), Effect.STEP_SOUND, b.getTypeId());
    29. }
    30. }, delay);
    31. }
    32. }
    33. }


    But at the end of the game for example. I want the blocks to generate back randomly like so with different delays. I have no idea the best way to do this or how to do it apart from delayed tasks. That's why I tried a hashmap to store the block state and the delay it should have to regenerate. Then Tried to have it in one repeating task rather than loads of delayed tasks to make it less ram hungry. It did not throw any errors but still did not regenerate.
     
  4. Offline

    NathanWolf


    The issue I pointed out above is going to prevent it from working- you're comparing a list size with a millisecond timing value to determine what to do, and that comparison doesn't make a whole lot of sense.

    Code:
    long diff = (System.currentTimeMillis() - blocks.values().size()) / 1000;
    if (diff < 0) ...
    
    "diff" is never going to be less than zero there, unless your list gets rediculously large.

    The solution I gave in my last post should work, if you want to ignore all else- it's a pretty simple change to your original code.
     
Thread Status:
Not open for further replies.

Share This Page