由于Spigot等MineCraft服务器是单线程的,因此,要实现定时执行操作的话,需要在插件中用到一个类似Runnable的类来执行相关操作。‘
定义一个实现BukkitRunnable接口的类:
将要延时执行,或者重复执行的内容放在这个类的run方法里。在它被实例化后,便可以用一系列属于BukkitRunnable的方法,灵活地调用run方法。
传入plugin是因为通过plugin可以得到对应的服务器,利用服务器可以做各种其他操作,比如最常见的广播。
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable;
public class ExampleTask extends BukkitRunnable {
private final JavaPlugin plugin;
public ExampleTask(JavaPlugin plugin) {
this.plugin = plugin;
}
@Override
public void run() {
// 你需要在运行的时候执行的内容放这
plugin.getServer().broadcastMessage("Welcome to Bukkit! Remember to read the documentation!");
}
}
接下来在就是在某个地方实例化这个类,并用这个类的相关方法调用run。这里Bukkit主流的教程定义了一个监听器,我们直接一点,就在onEnable方法中实例化和调用
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scheduler.BukkitTask;
public final class ExamplePlugin extends JavaPlugin {
@Override
public void onEnable() {
new ExampleListener(this);
}
}
class ExampleListener implements Listener {
private final ExamplePlugin plugin;
public ExampleListener(ExamplePlugin plugin) {
this.plugin = plugin;
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@EventHandler
public void onJoin(PlayerJoinEvent event) {
// 创建定时任务
BukkitTask task = new ExampleSelfCancelingTask(this.plugin, 5).runTaskTimer(this.plugin, 10, 20);
}
}
以下为插件源码:
这个文件很简单,直接new一个Runnable实例,接着调用就好了。
DisTest.java
package com.mcbbs.DisTest;
import java.util.HashMap;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitTask;
public class DisTest extends JavaPlugin {
static public HashMap<String,Player> playerList;
@Override
public void onEnable() {
getLogger().info("DisTest enable!");
//new出任务,延时0L,每20L执行一次
BukkitTask task=new UpdateDis(this).runTaskTimer(this, 0, 20L);
}
}
这个地方主要是两步。首先要一直查找主玩家。主玩家没到是不进行计算的。
接着对所有在线玩家计算他们与主玩家之间的欧拉距离,每次计算的时候更新一下最小值。
UpdateDis.java
package com.mcbbs.DisTest;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable;
public class UpdateDis extends BukkitRunnable {
private final JavaPlugin plugin;
private Player mainPlayer;//主玩家
private double minDis;//每次检测的最小距离
//构造函数
public UpdateDis(JavaPlugin plugin) {
minDis=99999;
this.plugin=plugin;
}
//run中写每次执行的逻辑
@Override
public void run() {
//找主玩家
if(Bukkit.getServer().getPlayer("jie")==null) {
//主玩家没有到服务器
Bukkit.getLogger().info("finding jie...");
return;
}
else {
Bukkit.getLogger().info("found jie!");
mainPlayer=Bukkit.getServer().getPlayer("jie");
}
//更新主玩家与所有玩家中的最小的距离
updateDis();
//广播最小距离
plugin.getServer().broadcastMessage("the min dis from jie is"+minDis);
}
//更新最小距离
public void updateDis() {
minDis=99999;
double mx=mainPlayer.getLocation().getX();
double my=mainPlayer.getLocation().getY();
double mz=mainPlayer.getLocation().getZ();
//遍历当前所有玩家
for(Player player:Bukkit.getServer().getOnlinePlayers()) {
if(player.getUniqueId().equals(mainPlayer.getUniqueId())) {
continue;
}
double px=player.getLocation().getX();
double py=player.getLocation().getY();
double pz=player.getLocation().getZ();
double currentDis=Math.sqrt((px-mx)*(px-mx)+(py-my)*(py-my)+(pz-mz)*(pz-mz));
if(currentDis<minDis) {
minDis=currentDis;
}
}
}
}
很简单的小插件,主要是遍历玩家+重复运行逻辑的实现