Solved Double timer

Discussion in 'Plugin Development' started by Lan3, Nov 22, 2021 at 9:42 AM.

  1. Offline

    Lan3

    Hello.
    I need to create a double timer. It should work like this: first 1 timer passes, then 2 starts. At the end of the second timer, the step moves to the first.

    I tried to do something similar, but at the end of 2 timers, there is no return to the first one. Here is my code:
    Code:
    @Override
    public void onEnable()
    {
    Bukkit.getScheduler().runTaskLater(this, new Runnable()
            {
                @Override
                public void run()
                {
                    World world = Bukkit.getWorld("world");
                    Integer x = (new Random().nextInt(3000 - 0));
                    Integer z = (new Random().nextInt(3000 - 0));
                    Integer y = world.getHighestBlockYAt(x, z);              
                    Location loc = new Location(world, x,y,z);
                    Block b = (world.getBlockAt(loc));                         
                    b.setType(Material.GOLD_BLOCK);
                    placer(b);
                }
            },120);
    
    public void placer(Block b)
        {
            Bukkit.getScheduler().runTaskLater(this, new Runnable()
            {
                @Override
                public void run()
                {
                    b.setType(Material.AIR);
                }
            }, 60);
        }
    }
    
    If possible, could you give ideas for improving this piece of code in general.

    Thank you in advance.
    I appreciate your time.
     
    Last edited by a moderator: Nov 22, 2021 at 9:52 AM
  2. Offline

    timtower Administrator Administrator Moderator

    @Lan3 Why not have a single timer on 60 ticks? Then you can just count to 3.
     
    Lan3 likes this.
  3. Offline

    Lan3

    There is such a thing. In "public void placer()"
    Or maybe I misunderstood you?
     
  4. Offline

    timtower Administrator Administrator Moderator

    @Lan3 1 runnable instead of 2.
     
  5. Offline

    Lan3

    That's what I planned. First, I run the code with a delay of 120 ticks. After it, I call 2 timer with a delay of 60. And it works. But after the end of 2 timers, I do not start 1 again.
     
  6. Offline

    timtower Administrator Administrator Moderator

    @Lan3 Then you still have 2 timers, I am talking about a single one.
    Not 2 that call each other.
     
    Strahan likes this.
  7. Offline

    Strahan

    Exactly. There is no need for two timers. For this simple 120 second / 60 second cycle, one could do:
    Code:
    new BukkitRunnable() {
      boolean isDestroying = false;
      World w = Bukkit.getWorld("newworld");
      Location blockLocation;
    
      @Override
      public void run() {
        if (w == null) {
          getLogger().info("Could not get world object!");
          cancel(); return;
        }
     
        if (isDestroying) {
          Block b = w.getBlockAt(blockLocation);
          b.setType(Material.AIR);
          isDestroying = false;
          return;
        }
    
        int x = ThreadLocalRandom.current().nextInt(3000);
        int z = ThreadLocalRandom.current().nextInt(3000);
        Block b = w.getHighestBlockAt(x, z).getRelative(0, 1, 0);
        blockLocation = b.getLocation();
        b.setType(Material.GOLD_BLOCK);
        isDestroying = true;
      }
    }.runTaskTimer(this, 0, 1200L);
    Though bear in mind 20 ticks = 1 second is only the ideal. It may fluctuate based on what the server is doing and thus cause some slight time dilation. Also I'd never actually use this code in production. If I were really going to do this, I'd not hardcode anything I'd use config and I'd use a 20 tick loop and a seconds incrementor so as to be able to support multiple instances of block spawning at varied intervals. I'd also add some logic to validate what I'm spawning the block on, so I don't end up putting it on top of weird things like tall grass or rails or such.

    PS you'll also notice I yanked your new Random()s. Don't use new Random like that. ThreadLocalRandom is an already created randomizer, it's much better to use that than to keep generating Random instances all the time.
     
    Lan3 likes this.
  8. Offline

    Lan3

    Thank you so much for your help. But, the main task of this timer has not been completed. After the block is placed, the timer should start for a time that is less than the waiting time for the block to be installed.
     
  9. Offline

    Strahan

    I thought the idea was a block gets placed, then after X amount of time it gets removed and after Y amount of time, the cycle repeats.

    In my example, that's exactly what it does. The block gets placed then after a time (60s) that is less than the overall block place time (120s) passes it gets removed. In my example, a block is placed every two minutes and once placed, it gets removed in one minute.
     
    Lan3 and Quantico like this.
  10. Offline

    Lan3

    Hmm, maybe something is wrong? But I have the same amount of time after the place of the block as it takes after the destroy of the block. Not 120s. Only 60 and 60
     

Share This Page