好的,我在这里有一个方法,当Entity点击地面时,它会保存位置和块内部的HashMap:
public static HashMap<Location, Material> blocks = new HashMap<Location, Material>();
然后在服务器上进行几次滴答,它会将块设置回原始类型,而不是在它刚刚变成空块时执行此操作。
@EventHandler
public void onProjecitle(ProjectileHitEvent event){
if(event.getEntity().getType() == EntityType.ENDER_PEARL){
Block block = event.getEntity().getLocation().getBlock();
for (int z = -1; z <= 1; z++) {
for (int x = -1; x <= 1; x++) {
for (int y = -1; y <= 1; y++) {
final Location loc = block.getRelative(x, y, z).getLocation();
if(loc.getBlock().getType() != Material.AIR){
Aure.blocks.put(loc.getBlock().getLocation(), block.getType());
loc.getBlock().setType(Material.WOOL);
Bukkit.getScheduler().runTaskLater(plugin, new Runnable(){
@Override
public void run() {
loc.getBlock().setType(Aure.blocks.get(loc.getBlock().getLocation()));
}
}, 40L);
}
}
}
}
}
}
答案 0 :(得分:1)
试试这个:
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable(){
而不是:
Bukkit.getScheduler().runTaskLater(plugin, new Runnable(){
runTaskLater
实际上正在安排异步任务,您应该尝试始终使用同步任务。
在Bukkit中使用异步任务的问题是,您的任务将安排在另一个线程上,而不是与正常服务器同步。使你所使用的任何Bukkit代码非常不安全,因此,作为一般的经验法则,每当你处理Bukkit
时,你应该总是使用同步任务,将在与Main
文件相同的线程上运行。所以,这是您的预定任务应该是什么样的:
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable(){
public void run(){
loc.getBlock().setType(Aure.blocks.get(loc)); //no need to use loc.getBlock().getLocation(), same thing as just using loc
}
}, 40L);
尝试创建重复任务时应用相同的规则,您应该使用scheduleSyncRepeatingTask
。
答案 1 :(得分:1)
关于你的代码的问题在于你得到了玩家脚的阻挡,所以它的材料显然是Material.AIR。您需要在播放器下方获取该块,因此您应该使用
Location theRealBlock = event.getEntity().getLocation().substract(0.0D, 1.0D, 0.0D);
而不是
event.getEntity().getLocation();