方法是
有两种方式,一个是使用PacketListener接口(就跟Bukkit的Listener差不多),还有一个是PL用来简化PacketListener的PacketAdapter抽象类,这里只介绍第二种
PacketAdapter有很多构造器,最优雅(推荐)的方法是使用PacketAdapter(AdapterParameteters params)。这个AdapterParameteters其实就是一个用于创建参数的Builder。在PacketListener法里,AdapterParameteters表现为ListeningWhitelist,也是使用Builder创建的。初始化一个AdapterParameterers的方法是PacketAdapter.params()。
(这个结构可能有些人看着不习惯,但很“优雅”
)
在AdapterParameteters的链式Builder中,只有plugin和types是必须的。其他的,如果你不显式指定,都有默认值,具体请看javadoc
还有一些方法,要不就是跟已存在的方法是一个功能,要不就是我也不知道啥意思咯,PL的坑这么深,很多方法我还没摸索出来
对了,在讲GamePhase时少了个Handshake表示握手包(请求motd和进入服务器之前发送的包),GamePhase.LOGIN = HANDSHAKE+LOGIN+STATUS就不改图片了。
注意: onPacketReceiving和onPacketSending的重写是可选的。但如果有clientSide,就必须重写onPacketReceiving否则报错。如果有serverSide,必须重写onPacketSending否则报错。
PacketTypePL把目前已知的所有包的类型都包装成了PacketType。PacketType并不代表包本身,只是身份证一样的东西,就像面向对象的Class不能等同实例。
注意PacketType不是一个enum,虽然看起来很像...
PacketType中有很多顾名思义的静态方法,相信都看得懂,我就不讲了。重点要讲的是其中的子类这些就是GamePhase,之前解释过了
上面的4个子类里,每个子类又有2个子类 (子孙满堂啊这又是把GamePhase进一步细分了。
CLIENT或SERVER的里面才是真正的包类型。例如PacketType.Play.Client.FLYING = net.minecraft.server.XXX.PacketPlayInFlying 类
要查看PacketType对应的NMS class可以使用getPacketClass()方法
另外PacketType里还有一个Legacy类,储存了1.6.4之前MC通讯协议大规模改版之前的数据包类型。
如何愉快的使用PacketEvent操作拦截到的数据包我目前搞得懂的方法,除了图中的getPacket()等,还有
如何愉快的获取数据包内的数据首先啊我们要举个梨子。
假如我们要获取的是PacketType.Play.Client.FLYING数据包
在愉快的读取其中的数据之前,我们需要找到这个数据包在NMS中是哪个类。NMS中数据包类名的命名规则如下
net.minecraft.server.XXX.PacketPlayInFlying
Packet = 这是一个数据包
Play = GamePhase不解释
In = 服务端收到的包,也就是客户端发出的包
Flying = 不解释
使用反编译器(我用的是jd-gui)找到这个类,打开(注意这个类只在核心里,bukkitapi里肯定是没有的,不然还要ProtocolLib干嘛!)
红框部分是重点(数据包类中的字段)
我们要弄明白哪个字段对应的是什么意思,储存的是什么内容。如果运气好的话,可以根据名词猜出来,,运气不好被混淆了,那就是abcd了。其中x、y、z、yaw、pitch、hasPos、hasLook都是顾名思义的。但f是什么?这个时候你有两个选择:
借助MCP。MCP一般会把字段的名字还原或加上注释的。不过MCP中数据包类名的格式可有点不一样。梨如PacketPlayInKeepAlive在1.8的MCP里是net.minecraft.network.play.client.C00PacketKeepAlive- wiki.vg/Protocol 里面有MC通讯协议的数据包描述。例如PacketPlayInFlying在这里,它告诉我们
唔,明白了,这么说那个f是onGround咯 - 把未知字段的值输出,根据客户端/服务端正在执行的操作,猜!
然后就好办了
注意:顺序很重要
够简单吧?相信都看得懂
Sending的数据包同理。修改和读取数据包的操作,在发送数据包时也要用到。
刚刚这个数据包里,字段都是基本类型。那如果是NMS中特有的类呢?总不能import吧。其实不用担心,PL都替我们想好了。
几乎所有的NMS类,在PL中都有包装。例如,GameProfile包装为WrappedGameProfile。举个梨子吧
BlockPosition类和ItemStack类(注意这个不是bukkit中的ItemStack而是在net.minecraft.server.XXX包下的ItemStack)都是NMS成员,既然不能import那怎么修改呢?
注意这个BlockPosition可不是nms中的BlockPosition,而是
NMS的包装类。还有比如NMS的IChatBaseComponent可以通过WrappedChatComponent类中的静态方法或构造器创建。所有的包装类都在com.comphenix.protocol.wrappers下,你会发现那里面还可以操作nbt=w=
PacketContainer里提供的方法,可以用于修改目前所有已知数据包的字段。里面还包括数组,List等的StructureModifier。那如果很不幸,有一个类型的字段,这里面没有提供呢?还是有办法——- StructureModifier<T> packet.getSpecificModifier(Class<T> primitiveType)
复制代码 这个方法可以获得任意类型的修改器。举个梨子,例如Pear类型的就是- packet.getSpecificModifier(Pear.class).write(0,new Pear("andylizi"));
复制代码 23333 |