NMS Packetv1.0.0已發布

NMS 封包攔截器

NMS Packet Interceptor

透過 Netty ChannelDuplexHandler 注入玩家連線管線,攔截或修改 Clientbound 與 Serverbound 封包。

nmspacketnettyinterceptorchannel-handlerpipeline
更新:2026年4月19日GitHub

NMS Packet Interceptor

目的

在玩家的 Netty 連線管線中注入自訂 ChannelDuplexHandler,於封包進入或離開伺服器時進行讀取、修改或取消。常用於反外掛、封包記錄、自訂通訊協議。


平台需求

  • Paper 1.21 – 1.21.3
  • Paperweight userdev 1.7.2+
  • Netty 4.x(Paper 內建)

產生的代碼

PacketInterceptor.java(ChannelDuplexHandler)

public final class PacketInterceptor extends ChannelDuplexHandler {

    // Serverbound(客戶端 → 伺服器)
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg instanceof Packet<?> packet) {
            Packet<?> modified = inboundFilter.apply(player, packet);
            if (modified == null) return; // 取消封包
            msg = modified;
        }
        super.channelRead(ctx, msg);
    }

    // Clientbound(伺服器 → 客戶端)
    @Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
        if (msg instanceof Packet<?> packet) {
            Packet<?> modified = outboundFilter.apply(player, packet);
            if (modified == null) return; // 取消封包
            msg = modified;
        }
        super.write(ctx, msg, promise);
    }
}

InterceptorManager.java

// 注入(PlayerJoinEvent LOWEST)
channel.pipeline().addBefore("packet_handler", HANDLER_ID, interceptor);

// 移除(PlayerQuitEvent)
channel.eventLoop().execute(() -> channel.pipeline().remove(HANDLER_ID));

執行緒安全

  • channelRead / write 皆在 Netty IO thread 執行
  • 需存取 Entity/World → 用 Bukkit.getScheduler().runTask() 切回主執行緒
  • 移除 handler 必須透過 channel.eventLoop().execute()