相关链接
对于ProtocolLib用法我摸索了很久才慢慢懂了(
从这里你可以学到:
- 了解ProtocolLib作用
- 了解Wiki的格式表
- 实践发送包-> 发送数据包盔甲架
-
实践监听包-> 交互数据包盔甲架
阅读前
-
请具备
Java
or
Kotlin
基础知识
了解ProtocolLib作用
在 Wiki 可以看到ProtocolLib可以做些什么
比如[ SPAWN ENTITY ],向某个玩家显示该实体而其它玩家没有看到(也就是说发送了[生成实体"SPAWN ENTITY"]包给某个玩家客户端,而服务器和未收到该包的玩家客户端不知道这个实体的存在)
引用 @梨子 : https://www.mcbbs.net/thread-568714-1-1.html
- 给玩家发送一个伪造的数据包
- 让服务端认为接收到了一个玩家发送的数据包
- 监听/修改 客户端发送给服务端 的数据包
-
监听/修改 服务端发送给客户端 的数据包
- 实际上,你可以不需要ProtocolLib进行发送数据包,但是你会受到版本限制,而ProtocolLib更新很快,而且兼容超多版本,并且提供了Wiki详细的数据包描述
- 拦截数据包
-
还有什么..?
发送欺骗服务端/客户端数据包
了解Wiki的格式表
看看Wiki数据包描述,以 [SPAWN ENTITY] 为例
该数据包目的:发送生成实体的数据包( 注 :纯发包的实体不能通过Bukkit获取实体,毕竟服务端不知道它的存在)
首栏解析
- Packet ID:在?还需要解释吗
- State:状态(这里是Play,其它还有Login等等)
- Bound To:发送目标(这里指发送给客户端)
- Field Name:字段名称
- Field Type:字段类型
-
Notes:显而易见,
别跟我说你不懂,雾
下面 必须用到 ,你可以想象,你要是不填,会发生什么事
- Entity ID [实体ID,唯一,否则直接覆盖] -> VarInt[int类型]
- Object UUID -> UUID (懂的都懂)
- Type [实体类型] -> 请在此处查找相关实体类型: https://wiki.vg/Entity_metadata#Mobs
- X [位置的X值] -> Double类型
- Y [位置的Y值] -> Double类型
-
Z
[位置的Z值] - > Double类型
- Pitch [向量] -> Angle值
- Yaw [向量] -> Angle值
- Data [数据] -> Int值,含义取决于 Type 值,相关内容请看: https://wiki.vg/Object_Data
- Velocity X [速度] -> Short值
- Velocity Y [速度] -> Short值
-
Velocity Z
[速度] -> Short值
实践发送包,以发送数据包盔甲架为例
既然了解了格式,那么如何使用呢?
2020/10/17 :本文基于 1.16.X预览版 (部分 不适用 于旧版)
Kotlin
-
我用Kotlin不反对吧?
(这样我可以防止Java复制党,滑稽) -
如果你是Java使用者,实际上你还是能看得出来,诸如
integers
在Java中是
getIntegers
-
fun spawnAS(player: Player, entityID: Int, loc: Location) { // 构造方法,在Java中是void型
-
val packet = PacketContainer(PacketType.Play.Server.SPAWN_ENTITY) // 示例一个PacketContainer
-
packet.modifier.writeDefaults() // 写入默认值
-
-
packet.integers.write(0, entityID) // 对integers的第0个写入实体ID,注意这里,实体ID不要重叠,否则会被覆盖
-
packet.uuiDs.write(0, UUID.randomUUID()) // 对UUID的第0个写入UUID值,这里使用了随机生成UUID值
-
packet.entityTypeModifier.write(0, EntityType.ARMOR_STAND) 对entityType的第0个写入实体类型,这里写入了盔甲架类型
-
packet.doubles.write(0, loc.x) // 对Double的第0个写入位置的X值,不写的话,你知道它在哪个角落躲着吗
-
packet.doubles.write(1, loc.y) // 对Double的第1个写入位置的Y值
-
packet.doubles.write(2, loc.z) // 对Double的第2个写入位置的Z值,这些顺序参照格式表(自己回去看格式表,第三个出现的Double就是位置的Z值)
-
-
sendServerPacket(player, packet) // 发送数据包
-
}
-
-
fun sendServerPacket(player: Player, packet: PacketContainer) { // 发送数据包方法
-
ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet)
- }
- ForceAsync:数据包是否必须异步处理
- Handshake:握手时发送的数据包
- Login:登录时发送和接收的数据包
- Play:在游戏时发送和接收的数据包
- Protocol:不同的协议或连接状态
- Sender:数据包类型的发送者
-
Status:[不太懂the multiplayer menu指什么菜单
?
]
- Client:来自客户端的数据包
-
Server:来自服务端的数据包
-
private ProtocolManager protocolManager;
-
-
public void onLoad() {
-
protocolManager = ProtocolLibrary.getProtocolManager();
- }
-
protocolManager.addPacketListener(
-
new PacketAdapter(主类, ListenerPriority.NORMAL, /*监听器级别*/
-
PacketType.Play.Server.NAMED_SOUND_EFFECT/*数据包类型,具体看wiki*/) {
-
@Override // 覆写发送的包,必须是onPacketSending,不然叫什么覆写
-
public void onPacketSending(PacketEvent event) { // 监听服务器发送数据包
-
if (event.getPacketType() == PacketType.Play.Server.NAMED_SOUND_EFFECT) { // 判断数据包类型,若是音乐数据包
-
event.setCancelled(true); // 取消该事件,也就是说,服务器发送的音乐数据包被被拦截,客户端不会收到该数据包
-
}
-
}
- });
-
https://ci.dmulloy2.net/job/ProtocolLib/javadoc/com/comphenix/protocol/events/PacketEvent.html
-
https://www.mcbbs.net/thread-568714-1-1.html
这里以 交互数据包盔甲架 为例子
Kotlin (喂?Java呢?你看上面不就行吗,只是有一些不同罢了
和上面一样,需要被onEnable调用
在此之前,请翻阅wiki: https://wiki.vg/Protocol#Interact_Entity
-
protocolManager.getProtocolManager().addPacketListener(object :
-
PacketAdapter(主类,
-
ListenerPriority.NORMAL,
-
PacketType.Play.Client.USE_ENTITY) { // 数据包类型为交互实体
-
override fun onPacketReceiving(ev: PacketEvent) { // 覆写接收的包,必须是onPacketReceiving,不然叫什么覆写
-
val packet = ev.packet // 获得数据包
-
packet.integers.read(0) // 读取数据包
-
if (packet.entityUseActions.values[0] != EnumWrappers.EntityUseAction.INTERACT) return // 判断交互动作
-
// 做你想做的事情
-
}
- })
注意 值得一提的是,若数据包盔甲架关闭了碰撞箱,是不会被交互,无法监听到
来自群组: Server CT
