feat: 补上出站包一直漏报的 hasHorizontalCollision(1.10.0)
针对「机器人一直在走、净位移却只有物理速度的 1/5」这个现象。 mineflayer 在 physics.js 里把 flags.hasHorizontalCollision 写成 undefined (源码注释还标着「1.21.3+」),位标志序列化后恒为 0 —— 而原版客户端在水平碰到 方块时会上报 1。机器人在崎岖地形上几乎一直在水平碰撞,却始终上报「没碰撞」, 正是反作弊 Prediction 最容易判错的形态:服务端按「该碰撞」预测、客户端说 「没碰撞」,于是被判异常并拉回。 物理引擎其实早已算出真实值(moveEntity 里给 entity.isCollidedHorizontally 赋值), 只是从没被发出去。现在在 _fixOutboundOnGround 里按真实值补上,由 grim.reportHorizontalCollision(默认开)控制。 实测依据(王城外山区,2 秒粒度采样 120 秒): - controls 几乎每 tick 都是 forward+sprint,velocity 约 0.2~3 格/秒; - 净位移只有 48.6 格 / 120 秒 = 0.405 格/秒,差额就是被服务端拉回的部分。 顺带把 _fixOutboundOnGround 拆成 _fixOnGroundFlag / _fixHorizontalCollisionFlag 两个职责单一的方法;控制台配置面板新增对应开关, packetStats.horizontalCollisionFixed 暴露补写次数。 测试 473 → 477。
这个提交包含在:
@@ -476,6 +476,58 @@ test('出站包结构异常时不抛异常', () => {
|
||||
assert.doesNotThrow(() => manager._fixOutboundOnGround({ flags: {} }));
|
||||
});
|
||||
|
||||
test('补上 hasHorizontalCollision:mineflayer 恒写 undefined(序列化后为 0)', () => {
|
||||
// 回归:原版客户端碰到方块时上报 1,而 mineflayer 在 physics.js 里把它写成
|
||||
// undefined —— 位标志序列化后恒为 0。机器人在崎岖地形上几乎一直水平碰撞,
|
||||
// 却始终上报「没碰撞」,反作弊的 Prediction 会按「该碰撞」预测后判定异常并拉回。
|
||||
const { manager } = setup();
|
||||
const bot = botStandingOnStone();
|
||||
bot.entity.isCollidedHorizontally = true;
|
||||
manager.bot = bot;
|
||||
|
||||
const params = { flags: { onGround: true, hasHorizontalCollision: undefined } };
|
||||
manager._fixOutboundOnGround(params);
|
||||
assert.strictEqual(params.flags.hasHorizontalCollision, true, '应按物理引擎的真实值补上');
|
||||
assert.strictEqual(manager.packetStats.horizontalCollisionFixed, 1);
|
||||
|
||||
// 已一致时不重复计数
|
||||
manager._fixOutboundOnGround(params);
|
||||
assert.strictEqual(manager.packetStats.horizontalCollisionFixed, 1);
|
||||
});
|
||||
|
||||
test('没有水平碰撞时如实上报 false', () => {
|
||||
const { manager } = setup();
|
||||
const bot = botStandingOnStone();
|
||||
bot.entity.isCollidedHorizontally = false;
|
||||
manager.bot = bot;
|
||||
const params = { flags: { onGround: true, hasHorizontalCollision: undefined } };
|
||||
manager._fixOutboundOnGround(params);
|
||||
assert.strictEqual(params.flags.hasHorizontalCollision, false);
|
||||
assert.strictEqual(manager.packetStats.horizontalCollisionFixed, 1);
|
||||
});
|
||||
|
||||
test('关闭 reportHorizontalCollision 后不碰这个标志', () => {
|
||||
const { manager } = setup({ config: { grim: { reportHorizontalCollision: false } } });
|
||||
const bot = botStandingOnStone();
|
||||
bot.entity.isCollidedHorizontally = true;
|
||||
manager.bot = bot;
|
||||
const params = { flags: { onGround: true, hasHorizontalCollision: undefined } };
|
||||
manager._fixOutboundOnGround(params);
|
||||
assert.strictEqual(params.flags.hasHorizontalCollision, undefined);
|
||||
assert.strictEqual(manager.packetStats.horizontalCollisionFixed, 0);
|
||||
});
|
||||
|
||||
test('物理引擎没给出碰撞状态时不瞎猜', () => {
|
||||
const { manager } = setup();
|
||||
const bot = botStandingOnStone();
|
||||
delete bot.entity.isCollidedHorizontally;
|
||||
manager.bot = bot;
|
||||
const params = { flags: { onGround: true, hasHorizontalCollision: undefined } };
|
||||
manager._fixOutboundOnGround(params);
|
||||
assert.strictEqual(params.flags.hasHorizontalCollision, undefined);
|
||||
assert.strictEqual(manager.packetStats.horizontalCollisionFixed, 0);
|
||||
});
|
||||
|
||||
test('位置包统计暴露在 snapshot 中,便于排查走不动的问题', () => {
|
||||
const { manager } = setup();
|
||||
const snap = manager.snapshot();
|
||||
|
||||
在新工单中引用
屏蔽一个用户