Skip to content
Advertisement

Alternatives for TimeUnit.SECONDS.sleep(1); SpigotMC/ SpigotMC event not running

I was trying to make a Minecraft plugin while having this problem, but I thought this would be more of a Java discussion

So I tried to make a spawner that would spawn a chicken every second (for testing, it would become every minute when I’m done), but while I was testing the event doesn’t seem to run (because TimeUnit.SECONDS.sleep() would block the MC thread). So may I have an alternative? The delay I’m using as for now is TimeUnit.SECONDS.sleep(*insert some number here*);
As shown here:

Note: I already tried using setTaskTimer and scheduleSyncRepeatingTask as shown in the answers, but they didn’t seem to work. Is this an event issue or a spawnEntity issue?

package com.TheRealBee.Bows.Event10;


import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.EntityType;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockPlaceEvent;

import java.util.concurrent.TimeUnit;


public class EventManager10 implements Listener {
        @EventHandler

        public void onNukePlace(BlockPlaceEvent e){


            // Return if it's not TNT, doesn't have ItemMeta or doesn't have a custom dispaly name
            if(!e.getBlock().getType().equals(Material.GOLD_BLOCK) || !e.getItemInHand().hasItemMeta() || !e.getItemInHand().getItemMeta().hasDisplayName())
                return;
            // Return if the item display name is not correct
            if(!e.getItemInHand().getItemMeta().getDisplayName().equals(ChatColor.WHITE+"Spawner"))
                return;
            // Create the explosion
            try {
                for (int i = 0; i < 300000000; i++) {
                    e.getBlock().getLocation().getWorld().spawnEntity(e.getBlock().getLocation(), EntityType.CHICKEN);
                    TimeUnit.SECONDS.sleep(1);
                }
            }
            catch(InterruptedException ex)
            {
                Thread.currentThread().interrupt();
            }
            
        }
}

Advertisement

Answer

You should use Bukkit.getScheduler().scheduleSyncRepeatingTask(...) in place of that for loop and TimeUnit.SECONDS.sleep

Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, new Runnable() {
    @Override
    public void run() {
        e.getBlock().getLocation().getWorld().spawnEntity(e.getBlock().getLocation(), EntityType.CHICKEN);
    }

}, 0L, 20L)

plugin should be the instance of your plugin

0L is the delay (in ticks) before the first task is run

20L is the delay (in ticks) before the next task is run

scheduleSyncRepeatingTask in the Spigot JavaDoc

As this is a spawner I assume you will want to stop spawning chickens when the block is broken. You can cancel a task using its taskID. The taskID is the integer that scheduleSyncRepeatingTask returns. You should save this taskID because you can cancel the task later (when the block breaks). To cancel the task you can use cancelTask:

Bukkit.getServer().getScheduler().cancelTask(taskID);

cancelTask in the Spigot JavaDoc

Save this taskID using for example a HashMap. When the block is place you should save the coordinates as key and the taskID as the value in the HashMap. When the block is broken (use the block break event) you should lookup the coordinates of the broken block in that HashMap. If the coordinates exist in the HashMap you should cancel the task and remove the entry from the HashMap.

User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement