当我去运行我创建的spigot插件时,当玩家完成某些操作时,他们将被踢。由于某种原因,当它们发送某些数据包 20 次后,它不会踢它们,而是给出一个错误:
[TenKAC] Unhandled exception number 64 occurred in onPacketReceiving(PacketEvent) for TenKAC java.lang.IllegalStateException: Asynchronous player kick! at org.spigotmc.AsyncCatcher.catchOp(AsyncCatcher.java:14) ~[spigot.jar:git-Spigot-21fe707-741a1bd] at org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer.kickPlayer(CraftPlayer.java:214) ~[spigot.jar:git-Spigot-21fe707-741a1bd] at cc.funkemunky.tenkac.checks.Check.flag(Check.java:57) ~[tenkac.jar:?] at cc.funkemunky.tenkac.checks.movement.Killaura.access$000(Killaura.java:23) ~[tenkac.jar:?] at cc.funkemunky.tenkac.checks.movement.Killaura$1.onPacketReceiving(Killaura.java:33) ~[tenkac.jar:?] at com.comphenix.protocol.injector.SortedPacketListenerList.invokeReceivingListener(SortedPacketListenerList.java:122) [ProtocolLib.jar:?] at com.comphenix.protocol.injector.SortedPacketListenerList.invokePacketRecieving(SortedPacketListenerList.java:75) [ProtocolLib.jar:?] at com.comphenix.protocol.injector.PacketFilterManager.postPacketToListeners(PacketFilterManager.java:557) [ProtocolLib.jar:?] at com.comphenix.protocol.injector.PacketFilterManager.invokePacketReceiving(PacketFilterManager.java:521) [ProtocolLib.jar:?] at com.comphenix.protocol.injector.netty.manager.NetworkManagerInjector.onPacketReceiving(NetworkManagerInjector.java:118) [ProtocolLib.jar:?] at com.comphenix.protocol.injector.netty.channel.NettyChannelInjector.processInboundPacket(NettyChannelInjector.java:500) [ProtocolLib.jar:?] at com.comphenix.protocol.injector.netty.channel.InboundPacketInterceptor.channelRead(InboundPacketInterceptor.java:33) [ProtocolLib.jar:?] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:333) [spigot.jar:git-Spigot-21fe707-741a1bd] at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:319) [spigot.jar:git-Spigot-21fe707-741a1bd] at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:163) [spigot.jar:git-Spigot-21fe707-741a1bd] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:333) [spigot.jar:git-Spigot-21fe707-741a1bd] at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:319) [spigot.jar:git-Spigot-21fe707-741a1bd] at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:163) [spigot.jar:git-Spigot-21fe707-741a1bd] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:333) [spigot.jar:git-Spigot-21fe707-741a1bd] at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:319) [spigot.jar:git-Spigot-21fe707-741a1bd] at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:163) [spigot.jar:git-Spigot-21fe707-741a1bd] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:333) [spigot.jar:git-Spigot-21fe707-741a1bd] at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:319) [spigot.jar:git-Spigot-21fe707-741a1bd] at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103) [spigot.jar:git-Spigot-21fe707-741a1bd] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:333) [spigot.jar:git-Spigot-21fe707-741a1bd] at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:319) [spigot.jar:git-Spigot-21fe707-741a1bd] at io.netty.handler.timeout.ReadTimeoutHandler.channelRead(ReadTimeoutHandler.java:150) [spigot.jar:git-Spigot-21fe707-741a1bd] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:333) [spigot.jar:git-Spigot-21fe707-741a1bd] at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:319) [spigot.jar:git-Spigot-21fe707-741a1bd] at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:787) [spigot.jar:git-Spigot-21fe707-741a1bd] at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:130) [spigot.jar:git-Spigot-21fe707-741a1bd] at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:511) [spigot.jar:git-Spigot-21fe707-741a1bd] at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:468) [spigot.jar:git-Spigot-21fe707-741a1bd] at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:382) [spigot.jar:git-Spigot-21fe707-741a1bd] at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:354) [spigot.jar:git-Spigot-21fe707-741a1bd] at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:116) [spigot.jar:git-Spigot-21fe707-741a1bd] at java.lang.Thread.run(Unknown Source) [?:1.8.0_301]
我需要知道如何在玩家“标记”20x 后踢他们。我可以看到玩家在 19 倍之前被标记,但在 20 倍时,当玩家应该被踢出时会出现一条错误消息:这是我的代码,一旦玩家被标记,就应该踢出玩家:
package cc.funkemunky.tenkac.checks.movement;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;
import cc.funkemunky.tenkac.AntiCheat;
import cc.funkemunky.tenkac.checks.Check;
import cc.funkemunky.tenkac.checks.CheckType;
import cc.funkemunky.tenkac.data.DataPlayer;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.events.PacketListener;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import static org.bukkit.Bukkit.getScheduler;
import static org.bukkit.Bukkit.getServer;
public class Killaura extends Check {
private int buffer = 0;
public Killaura(String name, CheckType type, boolean enabled, boolean punishable, int max) {
super(name, type, enabled, punishable, max);
ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(AntiCheat.getInstance(),
PacketType.Play.Client.POSITION, PacketType.Play.Client.POSITION_LOOK, PacketType.Play.Client.LOOK, PacketType.Play.Client.FLYING, PacketType.Play.Client.USE_ENTITY) {
@Override
public void onPacketReceiving(PacketEvent event) {
DataPlayer data = AntiCheat.getInstance().getDataManager().getDataPlayer(event.getPlayer());
if (event.getPacketType().equals(PacketType.Play.Client.USE_ENTITY)) {
flag(event.getPlayer(), "Player sent flying packet too late: " + Math.abs(System.currentTimeMillis() - data.lastFlying) + "ms!",
"Flagged player may be using: &3♦ &l&f&lF&e&ll&6&ly &3♦ &l&9&lK&1&li&5&ll&d&ll&b&la&3&lu&9&lr&1&la");
if ((Math.abs(System.currentTimeMillis() - data.lastFlying) == 0) || (Math.abs(data.lastFlying) == 0) || (Math.abs(System.currentTimeMillis()) == 0)) {
} else if (Math.abs(System.currentTimeMillis() - data.lastFlying) < 5) {
++buffer;
getServer().getConsoleSender().sendMessage(ChatColor.GREEN + "A player sent a fly packet too late! The packet was: " + (5 - (Math.abs(System.currentTimeMillis() - data.lastFlying))) + "ms too late!");
if (buffer > 1) {
flag(event.getPlayer(), "Player sent flying packet too late: " + Math.abs(System.currentTimeMillis() - data.lastFlying) + "ms!",
"Flagged player may be using: &3♦ &l&f&lF&e&ll&6&ly &3♦ &l&9&lK&1&li&5&ll&d&ll&b&la&3&lu&9&lr&1&la");
}
} else {
if (buffer > 0) {
getServer().getConsoleSender().sendMessage(ChatColor.GREEN + "Player's late fly packet has been buffered!");
}
buffer = 0;
}
} else {
data.lastFlying = System.currentTimeMillis();
}
}
});
}
}
和
package cc.funkemunky.tenkac.checks;
import cc.funkemunky.tenkac.AntiCheat;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.WeakHashMap;
import java.util.concurrent.TimeUnit;
import static org.bukkit.Bukkit.getServer;
public abstract class Check implements Listener {
protected String name;
protected CheckType type;
protected boolean enabled;
protected boolean punishable;
protected int max;
public Map<Player, Integer> violations = new WeakHashMap<>();
public Check(String name, CheckType type, boolean enabled, boolean punishable, int max) {
this.name = name;
this.type = type;
this.enabled = enabled;
this.punishable = punishable;
this.max = max;
Bukkit.getPluginManager().registerEvents(this, AntiCheat.getInstance());
}
synchronized protected void flag(Player player, String... information) {
int violations = this.violations.getOrDefault(player, 0) + 1;
if (information != null) {
StringBuilder formattedInfo = new StringBuilder();
for (String string : information) {
formattedInfo.append(string).append(", ");
}
for (Player staff : Bukkit.getOnlinePlayers()) {
if (staff.hasPermission("anticheat.staff")) {
staff.sendMessage(ChatColor.translateAlternateColorCodes('&', "&1[&b&lPvPCamp&1] &9" + player.getName() + " &7has been detected for &9" + name + " &1[&3" + formattedInfo.toString() + "&1]" + "&1(&b" + violations + "&1)"));
}
}
} else {
}
if (violations > max) {
try {
TimeUnit.MILLISECONDS.sleep(50);
} catch (InterruptedException e) {
}
player.kickPlayer("You have been kicked for " + name);
}
this.violations.put(player, violations);
if (violations > 0) {
getServer().getConsoleSender().sendMessage(ChatColor.DARK_PURPLE + player.getName() + " has " + violations + " violations!");
}
}
}
但是它只是给出了上面的错误。
某些操作不允许根据主服务器线程异步执行。主要是世界行动,有时与玩家相关,如开放库存和踢球。
BukkitScheduler#runTask
“返回主线程”,如下所示:
Bukkit.getScheduler().runTask(AntiCheat.getInstance(), () -> player.kickPlayer("You have been kicked for " + name));
此外,请勿将
TimeUnit.MILLISECONDS.sleep(50)
与插口一起使用。这是不适应的,spigot有自己的API等。如果你想在 X 秒内踢掉玩家,你可以像这样使用 BukkitScheduler#runTaskLater
:Bukkit.getScheduler().runTaskLater(AntiCheat.getInstance(), () -> {}, 20);
(这将等待 20 个刻度,所以 1 秒)