本帖最后由 狡诈师 于 2022-9-28 01:24 编辑 
首先让驾驶员获得运动控制权,有以下办法
禁用默认移动AI或者添加缓慢药水效果
TabooLib提供了顶级函数clearGoalAi()
TabooLib + Kotlin
添加监听器对数据包接收进行监听
复制代码
对数据包处理前确认复制代码
反编译分析目的:获取横向速度、前进速度,跳跃
1.17+复制代码从上面分析可知我们需要的是float类型的xxa和zza,以及boolean类型isJumping,从第一个开始数标注了a,b,c,d,e...也就是说我们取出c,d,e就好了
但是,1.17以下版本有所不同,继续反编译分析
复制代码相当简洁,显而易见a,b是我们所需的(float类型容易知道),跳跃是c
总结
赋值变量复制代码
为被乘骑的实体通过数据包拦截监听玩家控制wasd赋值数据包事件中玩家的位置
复制代码
设置被乘骑的实体方向与玩家方向相同
复制了玩家的偏航yaw和俯仰pitch
复制代码
为计算运动矢量做准备,需要获取前进方向、横向方向
获取前进方向,这一点很容易,得到玩家的方向即可复制代码
那么怎么获取横向方向呢?答案是向量积,在API中Vector提供了crossProduct方法
直立的玩家代表了一个向量,这个向量总是垂直于平面,该向量的特征为[0, ±1, 0]
 
 
根据图中方法,将得到一个指向右侧的横向向量
复制代码
有了前进方向和横向方向后,可以进行矢量计算了前进方向乘积前进速度并对横向方向乘积横向速度
复制代码
然后设置被乘骑的实体的速度
复制代码
测试以上代码后会发现这些问题
速度过快
可以对前进方向和横向方向进行除法运算,适当降低速度
复制代码
如何跳跃
对变量all设置向上y坐标,首先判断被乘骑的实体是否在地面,否则给予0.0
复制代码
为了减缓在空中降落速度,适当调整一下
复制代码
ProtocolLib
ProtocolLib根据文档中,ProtocolLib相关监听类似于此
复制代码
剩下的方法相对于TabooLib基本差不多
不过读取字段不一样
第一个float:0
第二个float:1
第一个boolean:0
TabooLib/ProtocolLib 实现无需NMS的实体坐骑
首先让驾驶员获得运动控制权,有以下办法
禁用默认移动AI或者添加缓慢药水效果
TabooLib提供了顶级函数clearGoalAi()
TabooLib + Kotlin
添加监听器对数据包接收进行监听
- @SubscribeEvent
 
- fun receive(ev: PacketReceiveEvent) {
 
- }
对数据包处理前确认
- if (ev.isCancelled) { // 如果被拦截
 
-     return
 
- }
 
- if (ev.packet.name != "PacketPlayInSteerVehicle") { // 数据包
 
-     return
 
- }
反编译分析目的:获取横向速度、前进速度,跳跃
1.17+
- package net.minecraft.network.protocol.game;
 
 
- import net.minecraft.network.PacketDataSerializer;
 
- import net.minecraft.network.protocol.Packet;
 
 
- public class PacketPlayInSteerVehicle implements Packet<PacketListenerPlayIn> {
 
-     private static final int FLAG_JUMPING = 1;  // a
 
-     private static final int FLAG_SHIFT_KEY_DOWN = 2; // b
 
-     private final float xxa;  // c
 
-     private final float zza;  // d
 
-     private final boolean isJumping;  // e
 
- private final boolean isShiftKeyDown;
但是,1.17以下版本有所不同,继续反编译分析
- public class PacketPlayInSteerVehicle implements Packet<PacketListenerPlayIn> {
 
-     private float a;
 
-     private float b;
 
-     private boolean c;
 
- private boolean d;
总结
| 版本范围 | 前进速度 | 横向速度 | 跳跃 | 
| 1.17及以上 | c | d | e | 
| 1.16及以下 | a | b | c | 
赋值变量
- val swSpeed = ev.packet.read<Float>(c)?: return // 前进速度(1.17+)
 
- val adSpeed = ev.packet.read<Float>(d)?: return // 横向速度(1.17+)
 
- val jumping = ev.packet.read<Boolean>(e)?: return // 跳跃(1.17+)
为被乘骑的实体通过数据包拦截监听玩家控制wasd赋值数据包事件中玩家的位置
- val pLoc = ev.player.location
设置被乘骑的实体方向与玩家方向相同
复制了玩家的偏航yaw和俯仰pitch
- vehicle.setRotation(pLoc.yaw, pLoc.pitch)
为计算运动矢量做准备,需要获取前进方向、横向方向
获取前进方向,这一点很容易,得到玩家的方向即可
- val dir = pLoc.direction
那么怎么获取横向方向呢?答案是向量积,在API中Vector提供了crossProduct方法
直立的玩家代表了一个向量,这个向量总是垂直于平面,该向量的特征为[0, ±1, 0]
根据图中方法,将得到一个指向右侧的横向向量
- val sideways = dir.clone().crossProduct(Vector(0, -1, 0))
有了前进方向和横向方向后,可以进行矢量计算了前进方向乘积前进速度并对横向方向乘积横向速度
- val all = dir.multiply(adSpeed).add(sideways.multiply(swSpeed))
然后设置被乘骑的实体的速度
- vehicle.velocity = vehicle.velocity.add(all)
测试以上代码后会发现这些问题
- 速度过快
- 如何跳跃
 
速度过快
可以对前进方向和横向方向进行除法运算,适当降低速度
- adSpeed/10
 
- swSpeed/5
如何跳跃
对变量all设置向上y坐标,首先判断被乘骑的实体是否在地面,否则给予0.0
- all.y = (if (jumping && vehicle.isOnGround) 0.5 else 0.0)
为了减缓在空中降落速度,适当调整一下
- if (!vehicle.isOnGround) all.multiply(0.4)
ProtocolLib
ProtocolLib根据文档中,ProtocolLib相关监听类似于此
- ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(<main instance>, PacketType.Play.Client.STEER_VEHICLE){
 
 
-     @Override
 
-     public void onPacketReceiving(PacketEvent event) {
 
-        // TODO
 
-     }
 
 
- });
剩下的方法相对于TabooLib基本差不多
不过读取字段不一样
第一个float:0
第二个float:1
第一个boolean:0
| 前进速度 | 横向速度 | 跳跃 | 
| 0 | 1 | 0 | 
楼主有taboolib下载地址吗
1.12.2的vehicle没有setRotation方法,坐骑不会跟着转向,这个有办法解决吗?
GinirohikoCha 发表于 2023-3-25 14:54
1.12.2的vehicle没有setRotation方法,坐骑不会跟着转向,这个有办法解决吗?
发包旋转实体