本帖最后由 狡诈师 于 2021-2-8 21:48 编辑

[ ! ] 阅读本文需要具备
- Kotlin 编程语言
- 熟悉Bukkit开发
- 搭起TabooLib为基础的项目
[ ! ] 相关链接
- [前置][开源][PCD]TabooLib —— 老坏黑的祖传病毒 [1.8-1.16]
- TabooLib Doc
- [SCT]玩转ProtocolLib数据包发包,将它玩出花样吧[发包|监听]
[ ! ] 本文采用
- 编程语言:Kotlin
- 内置依赖:TabooLib
- 游戏版本:1.16.4
相信有一部分的人愁于
那么,一个强大的TabooLib值得你拥有
为什么呢?
前言
我是翻阅一些基于TabooLib相关数据包项目找到规律的,自己动手后发现并不难,并且于ProtocolLib的Wiki有很大的相关性,当然,NMS也不例外
此教程初衷让开发者学被会感利染用TabooLib NMS发包
包名、类名没有特别要求
复制代码另外,Reflex反射工具不在TabooLib本体项目而在另一个项目,其中关于 Reflex 源码在:https://github.com/TabooLib/Tabo ... ib/kotlin/Reflex.kt
拿生成数据包盔甲架为例吧
我在 [SCT]玩转ProtocolLib数据包发包,将它玩出花样吧[发包|监听] 写过有关发送生成数据包盔甲架例子:
复制代码
从中可以看到需要最基本东西是 Player、EntitiID、UUID、X、Y、Z
不过,在抽象方法中,我们可以简化下方法参数,只需要:Player、EntityID、Loaction(当然你可以加上UUID参数)
由继承它的类中完成具体的实现
于是写下这样的方法
复制代码
顺便一提,方法名没有特别要求
类名、包名没有特别要求
但要与 NMS.kt 中 @TInject(asm = "cn.inrhor.nms.impl.NMSImpl") 包名和类名一致
即,创建包名 cn.inrhor.nms.impl ,创建类 NMSImpl
创建好后需要继承 NMS
即复制代码
根据 NMS.kt 中 spawnAS 方法那么要写一致的方法名、参数,然后在方法里做具体的实现
复制代码
解释:
然后一个发送数据包盔甲架方法完成了
复制代码
来自群组: Server CT
[ ! ] 阅读本文需要具备
- Kotlin 编程语言
- 熟悉Bukkit开发
- 搭起TabooLib为基础的项目
[ ! ] 相关链接
- [前置][开源][PCD]TabooLib —— 老坏黑的祖传病毒 [1.8-1.16]
- TabooLib Doc
- [SCT]玩转ProtocolLib数据包发包,将它玩出花样吧[发包|监听]
[ ! ] 本文采用
- 编程语言:Kotlin
- 内置依赖:TabooLib
- 游戏版本:1.16.4
相信有一部分的人愁于
- 复杂的NMS发包方式
- 不想硬依赖ProtocolLib
那么,一个强大的TabooLib值得你拥有
为什么呢?
- 内置依赖,无需使用者手动安装TabooLib插件(我是因为这个
感染的) - 比NMS发包方式简单
前言
我是翻阅一些基于TabooLib相关数据包项目找到规律的,自己动手后发现并不难,并且于ProtocolLib的Wiki有很大的相关性,当然,NMS也不例外
此教程初衷让开发者学
- NMS.kt
包名、类名没有特别要求
- abstract class NMS { // 抽象类,注意类名无特别要求
- companion object { // 伴生对象,静态那种懂吗
- @TInject(asm = "cn.inrhor.nms.impl.NMSImpl") // asm是版本转换(坏黑说的),不懂就接着阅读就知道了
- lateinit var INSTANCE: NMS // 声明变量,让外部访问操纵NMS
- internal val version = Version.getCurrentVersionInt() // 声明变量,为了判断版本
- /**
- * 发送数据包方法
- *
- * @param player 玩家
- * @param packet 数据包
- * @param fields vararg指可变参数,fields 为了将数据包中各个值写入包
- */
- fun sendPacket(player: Player, packet: Any, vararg fields: Pair<String, Any>) {
- TPacketHandler.sendPacket(player, setFields(packet, *fields))
- }
- /**
- * 为了将数据包中各个值写入包
- */
- fun setFields(any: Any, vararg fields: Pair<String, Any>): Any {
- fields.forEach { (key, value) ->
- Reflex.from(any.javaClass, any).set(key, value)
- }
- return any
- }
- }
- }
- NMS.kt 生成数据包盔甲架方法(抽象方法)
拿生成数据包盔甲架为例吧
我在 [SCT]玩转ProtocolLib数据包发包,将它玩出花样吧[发包|监听] 写过有关发送生成数据包盔甲架例子:
- 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) // 发送数据包
- }
从中可以看到需要最基本东西是 Player、EntitiID、UUID、X、Y、Z
不过,在抽象方法中,我们可以简化下方法参数,只需要:Player、EntityID、Loaction(当然你可以加上UUID参数)
由继承它的类中完成具体的实现
于是写下这样的方法
- /**
- * 生成盔甲架
- */
- abstract fun spawnAS(player: Player, entityId: Int, location: Location)
顺便一提,方法名没有特别要求
- NMSImpl.kt
类名、包名没有特别要求
但要与 NMS.kt 中 @TInject(asm = "cn.inrhor.nms.impl.NMSImpl") 包名和类名一致
即,创建包名 cn.inrhor.nms.impl ,创建类 NMSImpl
创建好后需要继承 NMS
即
- class NMSImpl : NMS() {
- |
- NMSImpl 生成数据包盔甲架方法(具体实现)
根据 NMS.kt 中 spawnAS 方法那么要写一致的方法名、参数,然后在方法里做具体的实现
- override fun spawnAS(player: Player, entityId: Int, location: Location) {
- sendPacket(
- player,
- PacketPlayOutSpawnEntity(),
- "a" to entityId,
- "b" to UUID.randomUUID(),
- "c" to location.x,
- "d" to location.y,
- "e" to location.z,
- "k" to EntityTypes.ARMOR_STAND
- )
- }
解释:
- 向 player 发送数据包
- 其中数据包类型为 PacketPlayOutSpawnEntity(我说过了,数据包方法与ProtocolLib Wiki有很大的相关性,如图所示,当然你可以反编译NMS去找)

- 从上图我们可以看到,a、b、c... 分别对应了 0、1、2...(也如图顺序所示)
然后一个发送数据包盔甲架方法完成了
- 发送数据包
- val player = ev.player
- val entitiID = 2333
- val loc = player.location
- NMS.INSTANCE.spawnAS(player, entitiID , loc)
未完,待更
来自群组: Server CT