TimeUnit.SECONDS.sleep(1) 的备选方案; SpigotMC/SpigotMC 事件不是 运行
Alternatives for TimeUnit.SECONDS.sleep(1); SpigotMC/ SpigotMC event not running
我在尝试制作 Minecraft 插件时遇到了这个问题,但我认为这更像是一个 Java 讨论
所以我尝试制作一个每秒生成一只鸡的生成器(为了测试,当我完成时它会变为每分钟生成一次),但是在我测试时事件似乎没有 运行(因为 TimeUnit.SECONDS.sleep()
会阻塞 MC 线程)。那么我可以有其他选择吗?
我现在使用的延迟是 TimeUnit.SECONDS.sleep(*insert some number here*);
如下所示:
注意:我已经尝试使用 setTaskTimer
和 scheduleSyncRepeatingTask
如答案所示,但它们似乎没有用。这是事件问题还是 spawnEntity
问题?
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();
}
}
}
您应该使用 Bukkit.getScheduler().scheduleSyncRepeatingTask(...)
代替 for 循环和 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
应该是你插件的实例
0L
是第一个任务 运行
之前的延迟(以滴答为单位)
20L
是下一个任务 运行
之前的延迟(以滴答为单位)
scheduleSyncRepeatingTask in the Spigot JavaDoc
因为这是一个生成器,所以我假设您希望在方块被破坏时停止生成小鸡。您可以使用任务 ID 取消任务。 taskID是scheduleSyncRepeatingTask
returns的整数。您应该保存此 taskID,因为您可以稍后取消任务(当块中断时)。要取消任务,您可以使用 cancelTask
:
Bukkit.getServer().getScheduler().cancelTask(taskID);
cancelTask in the Spigot JavaDoc
使用例如 HashMap 保存此 taskID。放置块后,您应该将坐标保存为键,将任务 ID 保存为 HashMap 中的值。当块被破坏时(使用 block break 事件),您应该在该 HashMap 中查找被破坏块的坐标。如果 HashMap 中存在坐标,则应取消任务并从 HashMap 中删除条目。
As , you could use a runnable. Bukkit has baked in methods 以利用此 Java 功能。这是首选,因为使用 Thread.sleep()
(TimeUnit.SECONDS.sleep()
包装)将暂停 Minecraft 所在的主线程 运行;调用将暂停所有内容(玩家移动、其他插件、世界生成等),如果时间延长,将导致客户端断开连接。
为了得到你想要的结果;重复操作,您应该使用 runTaskTimer
调度程序。有几种调用此调度程序的方法,但到目前为止最简单的方法如下:
Bukkit.getScheduler().runTaskTimer(plugin, () -> e.getBlock().getLocation().getWorld().spawnEntity(e.getBlock().getLocation(), EntityType.CHICKEN), 0L, 100L);
其中 plugin
是您的插件实例,() -> ...
是 lambda expression to call the one action we want to execute, 0L
is the delay to start the task (where L
represents a long) 最后 100L
是 5 秒的滴答。每秒有 20 个滴答声,因此您可以执行 seconds * 20
以获得您想要的延迟滴答声(例如 60 * 20 = 1200L 1 分钟)。
当您希望鸡停止产卵时,runTaskTimer
将 return BukkitTask
that you can store and then later cancel 的一个实例。
有几种方法可以获取您的插件实例,但一种方法是在您从 main 调用它时简单地将实例传递给侦听器,例如:
Bukkit.getPluginManager().registerEvents(new EventManager10(this), this);
然后你会在 EventManager10
:
中将默认的 constructor 换成你自己的
private final JavaPlugin plugin;
public EventManager10(JavaPlugin plugin){
this.plugin = plugin;
}
总的来说,EventManager10
不符合Java naming conventions,也许可以阅读这些,因为它对您的项目扩展有帮助。
我在尝试制作 Minecraft 插件时遇到了这个问题,但我认为这更像是一个 Java 讨论
所以我尝试制作一个每秒生成一只鸡的生成器(为了测试,当我完成时它会变为每分钟生成一次),但是在我测试时事件似乎没有 运行(因为 TimeUnit.SECONDS.sleep()
会阻塞 MC 线程)。那么我可以有其他选择吗?
我现在使用的延迟是 TimeUnit.SECONDS.sleep(*insert some number here*);
如下所示:
注意:我已经尝试使用 setTaskTimer
和 scheduleSyncRepeatingTask
如答案所示,但它们似乎没有用。这是事件问题还是 spawnEntity
问题?
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();
}
}
}
您应该使用 Bukkit.getScheduler().scheduleSyncRepeatingTask(...)
代替 for 循环和 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
应该是你插件的实例
0L
是第一个任务 运行
20L
是下一个任务 运行
scheduleSyncRepeatingTask in the Spigot JavaDoc
因为这是一个生成器,所以我假设您希望在方块被破坏时停止生成小鸡。您可以使用任务 ID 取消任务。 taskID是scheduleSyncRepeatingTask
returns的整数。您应该保存此 taskID,因为您可以稍后取消任务(当块中断时)。要取消任务,您可以使用 cancelTask
:
Bukkit.getServer().getScheduler().cancelTask(taskID);
cancelTask in the Spigot JavaDoc
使用例如 HashMap 保存此 taskID。放置块后,您应该将坐标保存为键,将任务 ID 保存为 HashMap 中的值。当块被破坏时(使用 block break 事件),您应该在该 HashMap 中查找被破坏块的坐标。如果 HashMap 中存在坐标,则应取消任务并从 HashMap 中删除条目。
As Thread.sleep()
(TimeUnit.SECONDS.sleep()
包装)将暂停 Minecraft 所在的主线程 运行;调用将暂停所有内容(玩家移动、其他插件、世界生成等),如果时间延长,将导致客户端断开连接。
为了得到你想要的结果;重复操作,您应该使用 runTaskTimer
调度程序。有几种调用此调度程序的方法,但到目前为止最简单的方法如下:
Bukkit.getScheduler().runTaskTimer(plugin, () -> e.getBlock().getLocation().getWorld().spawnEntity(e.getBlock().getLocation(), EntityType.CHICKEN), 0L, 100L);
其中 plugin
是您的插件实例,() -> ...
是 lambda expression to call the one action we want to execute, 0L
is the delay to start the task (where L
represents a long) 最后 100L
是 5 秒的滴答。每秒有 20 个滴答声,因此您可以执行 seconds * 20
以获得您想要的延迟滴答声(例如 60 * 20 = 1200L 1 分钟)。
runTaskTimer
将 return BukkitTask
that you can store and then later cancel 的一个实例。
有几种方法可以获取您的插件实例,但一种方法是在您从 main 调用它时简单地将实例传递给侦听器,例如:
Bukkit.getPluginManager().registerEvents(new EventManager10(this), this);
然后你会在 EventManager10
:
private final JavaPlugin plugin;
public EventManager10(JavaPlugin plugin){
this.plugin = plugin;
}
总的来说,EventManager10
不符合Java naming conventions,也许可以阅读这些,因为它对您的项目扩展有帮助。