用BukkitRunnable做一个简单的定时距离检测插件

    技术2022-07-10  102

    由于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; } } } }

    很简单的小插件,主要是遍历玩家+重复运行逻辑的实现

    Processed: 0.025, SQL: 9