1 次代码提交
作者 SHA1 备注 提交日期
lyizai c80bde4e3a v1.3.1: 修复溺水越沉越深 + 自动用船坐船航行
- 自动游泳改为只要在水中就持续按住空格(不再受 Baritone 接管条件影响),玩家不再越沉越深;坐船/用船流程/走两步时自动松开
- 自动用船升级:开阔水面游泳时也能直接放船登船,登船后自动坐船朝目标区块航行(替代 Baritone 水中游泳),用船期间暂停 Baritone 寻路、靠岸下船回收后自动恢复
- 登船失败加入冷却(约4秒),避免每帧重试刷屏;航行中船消失/到目标区块后自动下船
- 版本号升至 1.3.1
2026-09-12 11:57:13 +08:00
共修改 5 个文件,包含 226 行新增和 54 行删除
+4 -3
查看文件
@@ -16,7 +16,8 @@
- 自动进食(饥饿时自动吃背包食物)
- 自动攻击敌对生物:扩地途中自动面向并攻击索敌范围内的敌对生物(满蓄力出手、不追击、不打断寻路);严格豁免不会主动攻击玩家的中立生物——铁傀儡、僵尸猪灵永不攻击,末影人(仅被激怒)、蜘蛛(仅黑暗中)、猪灵(仅玩家未穿金甲)按原版敌对条件反击,狼、蜜蜂、羊驼等其它中立生物一律不打
- 耐久保护回城:每 2 秒检查主手/副手/四件盔甲耐久,任意一件剩余耐久低于阈值(默认 15%,可在 GUI 调整)时自动发送 `/u return` 回城并停止扩地,防止装备被怪物磨没
- 自动用船过水:扩地途中若路径前方出现开阔水域(默认宽度 ≥ 4 格、长度 ≥ 6 格),自动切到主手放船并登船;前方出现岸边时自动蹲伏下船并攻击船实体回收船(仅背包有任意 `*_boat`/`*_chest_boat` 时生效;不打断 Baritone 寻路)
- 自动用船过水:扩地途中遇开阔水域(默认宽度 ≥ 4 格、长度 ≥ 6 格)自动切到主手放船并登船,坐船朝目标区块航行;靠岸前自动下船并攻击船实体回收船。水面游泳时也能直接登船,用船期间暂停 Baritone 寻路、结束后自动恢复(仅背包有任意 `*_boat`/`*_chest_boat` 时生效)
- 自动游泳防溺水:玩家在水中(含 Baritone 寻路期间)持续按住跳跃键上浮,不会沉入水中越沉越深;坐上船或进入用船流程时自动松开,避免与航行/登船冲突
- 实时地图 GUI(通过 Ctrl+R 打开)
- 监听聊天/字幕消息判断开垦结果
- 刷新地图时与最新 `markers.json` 核对已占领区块,丢弃地图未确认的超期假占领,避免高地扩地残留空洞
@@ -29,7 +30,7 @@
## 安装
1. 安装 Fabric Loader 0.16.14+ 和 Fabric API
2. 将 `autostore-1.3.0.jar` 放入 `.minecraft/mods/` 目录
2. 将 `autostore-1.3.1.jar` 放入 `.minecraft/mods/` 目录
3. 启动游戏,按 `Ctrl+R` 打开 GUI
## 构建
@@ -39,7 +40,7 @@
./build_mod.sh
```
输出文件:`autostore-1.3.0.jar`
输出文件:`autostore-1.3.1.jar`
## 赞助支持
+1 -1
查看文件
@@ -7,7 +7,7 @@ yarn_mappings=1.21.4+build.8
loader_version=0.19.3
# Mod Properties
mod_version=1.3.0
mod_version=1.3.1
maven_group=autostore
archives_base_name=autostore
@@ -320,7 +320,8 @@ implements SubtitleChatMonitor.Listener, BaritoneBridge.PathListener {
client.player.sendMessage(Text.literal("[AutoStore] \u5df2\u5230\u5f00\u62d3\u65f6\u9650\u5916\uff0811:00-22:00\uff09\uff0c\u4efb\u52a1\u505c\u6b62"), false);
return;
}
if (this.tickAutoFood(client)) {
// 自动用船流程进行中:暂停自动进食,避免进食中断航行/游泳按键(吃食物占用主手动画)
if (!this.autoBoat.isActive() && this.tickAutoFood(client)) {
return;
}
// 耐久保护优先于一切寻路/战斗:装备耐久过低时先回城,防止装备被怪物磨没
@@ -328,15 +329,17 @@ implements SubtitleChatMonitor.Listener, BaritoneBridge.PathListener {
return;
}
this.tickAutoSwim(client);
// 自动用船过水:开阔水域自动放船登船、上岸前自动下船回收
// 自动用船过水:开阔水域自动放船登船、坐船朝目标航行、上岸前自动下船回收
this.tickAutoBoat(client);
// 处于"往边上走两步"阶段:每帧驱动手动横向行走,走开后自动重试原目标(该阶段不自动攻击,避免抢方向键)
if (this.sideStepping) {
this.tickSideStep();
return;
}
// 自动攻击:面向并攻击范围内的敌对生物(不追击,不打断寻路状态机)
// 自动攻击:面向并攻击范围内的敌对生物(不追击,不打断寻路状态机;用船期间不攻击,避免抢转向)
if (!this.autoBoat.isActive()) {
this.tickAutoAttack(client);
}
switch (this.state) {
case PLANNING: {
this.plan();
@@ -431,6 +434,21 @@ implements SubtitleChatMonitor.Listener, BaritoneBridge.PathListener {
if (this.skipIfTargetClaimed("\u76ee\u6807\u5df2\u88ab\u5360\u9886")) {
return;
}
// 已到达目标区块:寻路完成(无论是否在用船,都立即进入等待开垦)
if (this.playerChunk.equals(this.target)) {
this.baritoneBridge.cancel();
// 成功到达目标:寻路不再卡死,清零连续超时计数
this.consecutiveTimeoutMillis = 0L;
this.stageStartedMillis = System.currentTimeMillis();
this.setState(State.WAITING, "\u5df2\u5230\u8fbe\uff0c\u7b49\u5f85\u9886\u5730\u5f00\u62d3");
this.log("\u5df2\u5230\u8fbe\u76ee\u6807 " + this.target.x() + "," + this.target.z() + "\uff0c\u5f00\u59cb\u7b49\u5f85\u5f00\u57a6");
return;
}
// 自动用船流程进行中:移动由船导航接管(到达判定已在上方完成),
// 跳过超时/重试/路径失败处理,避免与船流程抢按键或误判
if (this.autoBoat.isActive()) {
return;
}
// Baritone 报告路径计算失败(目标不可达,如被悬崖/高山/水体完全隔断)。
// 不立即跳过:CALC_FAILED 常因瞬时能力限制或起点卡位误报,先重新寻路一次
//(相当于“往边上走两步再算一遍”),重试耗尽才跳过当前目标。
@@ -898,10 +916,11 @@ implements SubtitleChatMonitor.Listener, BaritoneBridge.PathListener {
/**
* 自动游泳逻辑(每帧调用):
* 仅在玩家处于水中(含没入 / 水面 / 浅水)、Baritone 未接管寻路、玩家不在船中时,
* 持续按住跳跃键,使玩家不断浮到水面,避免溺水。
* 任务停止、离开水、Baritone 开始寻路、坐上船等条件触发时立即释放跳跃键,
* 避免干扰 Baritone 与其它流程。
* 只要玩家处于水中(含没入 / 水面 / 浅水)、不在船中、无自动用船流程、未在手动走两步,
* 就持续按住跳跃键,使玩家不断浮到水面,避免溺水。
* 之前"只在 Baritone 未接管时按空格"会在 Baritone 寻路期间松手,导致玩家在水里越沉越深;
* 现在即使 Baritone 正在寻路也持续按空格,保证玩家始终浮在水面附近。
* 任务停止、离开水、坐上船、进入用船流程等条件触发时立即释放跳跃键,避免干扰其它流程。
*/
private void tickAutoSwim(MinecraftClient client) {
if (!this.isRunning() || client.player == null) {
@@ -909,11 +928,10 @@ implements SubtitleChatMonitor.Listener, BaritoneBridge.PathListener {
return;
}
PlayerEntity player = client.player;
// 水中 + Baritone 未接管 + 玩家不在船中(船里前进靠船自身,不需要自动跳)→ 持续按住空格
// 水中 + 不在船中(船里前进靠船自身,不需要自动跳)+ 无自动用船流程 + 未在手动走两步 → 持续按住空格
boolean inWater = player.isTouchingWater();
boolean baritoneControlling = this.baritoneBridge.isPathing();
boolean inBoat = player.getVehicle() instanceof AbstractBoatEntity;
if (inWater && !baritoneControlling && !inBoat) {
if (inWater && !inBoat && !this.autoBoat.isActive() && !this.sideStepping) {
this.pressJump(client);
} else {
this.releaseJump(client);
@@ -962,17 +980,31 @@ implements SubtitleChatMonitor.Listener, BaritoneBridge.PathListener {
/**
* 自动用船过水(每帧调用):
* 在岸上且朝向方向前方出现开阔水域时,自动放船并登船;
* 在船中且前方出现岸边时,自动下船并攻击船实体回收船。
* 仅在扩地任务运行中、配置 autoBoat 开启时生效;不打断 Baritone 寻路。
* 在开阔水域朝目标方向自动放船登船、坐船朝目标航行、上岸前自动下船回收船。
* 仅在扩地任务运行中、配置 autoBoat 开启、且处于"寻路前往目标"阶段时开启新的用船流程;
* 用船流程进行中暂停 Baritone 寻路(船由 AutoBoatController 手动导航,避免按键/方向冲突),
* 流程结束后自动恢复 Baritone 寻路。
*/
private void tickAutoBoat(MinecraftClient client) {
this.autoBoat.tick(client, this.config, this.isRunning());
boolean wasActive = this.autoBoat.isActive();
// 仅在"寻路前往目标"阶段允许开启新的用船流程;走两步阶段手动控制方向键,不抢路
boolean canStartFlow = this.state == State.PATHING && !this.sideStepping && this.target != null;
this.autoBoat.tick(client, this.config, this.isRunning(), canStartFlow, this.target);
if (this.autoBoat.isActive()) {
// 自动用船流程接管移动:取消 Baritone 寻路,避免与船的按键/方向冲突
this.baritoneBridge.cancel();
String desc = this.autoBoat.describe();
if (desc != null) {
this.status = desc;
}
} else if (wasActive) {
// 用船流程刚结束:若仍处于寻路阶段且未到达目标,恢复 Baritone 寻路
if (this.state == State.PATHING && this.target != null
&& !this.playerChunk.equals(this.target) && !this.sideStepping) {
this.stageStartedMillis = System.currentTimeMillis();
this.baritoneBridge.pathTo(this.target);
this.log("\u81ea\u52a8\u7528\u8239\u7ed3\u675f\uff0c\u6062\u590d Baritone \u5bfb\u8def");
}
}
}
@@ -19,6 +19,7 @@
package autostore.client.navigation;
import autostore.client.config.ExpansionConfig;
import autostore.client.territory.ChunkPos;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.block.Blocks;
@@ -90,42 +91,66 @@ public final class AutoBoatController {
private static final int FLOW_ENTER = 1;
/** 当前是上岸流程 */
private static final int FLOW_EXIT = 2;
/** 当前是坐船航行流程(自动朝目标区块航行) */
private static final int FLOW_SAIL = 3;
private int flow = IDLE;
/** 登船失败冷却时长(tick,80 tick ≈ 4 秒):失败后一段时间内不再尝试,避免每帧重试刷屏 */
private static final int BOARD_FAIL_COOLDOWN_TICKS = 80;
/** 已到达目标区块后仍未靠岸、强制下船的等待时长(tick,100 tick ≈ 5 秒) */
private static final int ARRIVED_FORCE_DISEMBARK_TICKS = 100;
/** 坐船航行时是否正在按住前进键 */
private boolean holdingForward;
/** 登船失败后的冷却 tick 数(>0 时不触发登船) */
private int failCooldownTicks;
/** 已到达目标区块后继续找岸边的 tick 数(超时则直接下船) */
private int arrivedTicks;
/**
* 每帧调用入口:根据当前玩家状态决定是否触发登船或上岸流程;
* 每帧调用入口:根据当前玩家状态决定是否触发登船 / 坐船航行 / 上岸流程;
* 已经处于某个流程中时推进阶段。
*
* @param client 客户端
* @param config 扩地配置(用于读取 autoBoat/最小宽度/最短长度)
* @param isRunning 当前扩地任务是否在运行(PAUSE/COMPLETE/STOPPED 时跳过)
* @param canStartFlow 是否允许开启新的用船流程(仅"寻路前往目标"阶段为 true;
* 走两步/等待开垦等阶段不抢路)
* @param target 当前寻路目标区块(坐船航行时朝它前进)
*/
public void tick(MinecraftClient client, ExpansionConfig config, boolean isRunning) {
public void tick(MinecraftClient client, ExpansionConfig config, boolean isRunning, boolean canStartFlow, ChunkPos target) {
if (client == null || client.player == null || client.world == null || client.interactionManager == null) {
return;
}
// 配置未启用或任务未运行:清理状态(如有进行中的流程,强行取消并释放蹲伏键)
// 登船失败冷却计时
if (this.failCooldownTicks > 0) {
--this.failCooldownTicks;
}
// 配置未启用或任务未运行:清理状态(如有进行中的流程,强行取消并释放按键)
if (!isRunning || !config.autoBoat) {
this.reset(client, false);
return;
}
// 自动攻击、自动进食、自动游泳、走两步期间:让位(避免按键冲突)
if (this.flow == IDLE) {
// 无进行中流程:根据玩家状态决定是否需要登船 / 上岸
// 无进行中流程:根据玩家状态决定是否需要登船 / 航行 / 上岸
Entity vehicle = client.player.getVehicle();
if (vehicle instanceof AbstractBoatEntity) {
// 已在船中:检测前方是否即将到达岸边
// 已在船中:优先靠岸下船;未靠岸且处于寻路阶段则接管航行朝目标前进,否则立即下船
if (this.shouldDisembark(client, config)) {
this.beginDisembark(client, (AbstractBoatEntity) vehicle);
} else if (canStartFlow) {
this.beginSail(client);
} else {
this.beginDisembark(client, (AbstractBoatEntity) vehicle);
}
} else if (this.shouldBoardBoat(client, config)) {
// 在岸上且前方有开阔水域:尝试登船
} else if (canStartFlow && this.shouldBoardBoat(client, config)) {
// 在岸上/水面且前方有开阔水域:尝试登船
this.beginBoard(client);
}
return;
}
// 有进行中流程:推进阶段
switch (this.flow) {
case FLOW_SAIL -> this.tickSail(client, config, target);
case FLOW_ENTER -> this.tickEnter(client);
case FLOW_EXIT -> this.tickExit(client);
}
@@ -133,14 +158,19 @@ public final class AutoBoatController {
/** 强制停止所有动作(如任务被手动停止时) */
public void reset(MinecraftClient client, boolean silent) {
if (this.flow == IDLE) {
return;
}
// 释放蹲伏键(避免卡住"按住"状态)
if (this.holdingSneak) {
this.releaseSneak(client);
this.holdingSneak = false;
}
// 释放前进键(坐船航行时按住,避免流程结束后玩家一直往前走)
if (this.holdingForward) {
this.releaseForward(client);
this.holdingForward = false;
}
if (this.flow == IDLE) {
return;
}
// 还原主手槽位(如有暂存)
this.restoreSelectedSlot(client);
this.flow = IDLE;
@@ -149,6 +179,7 @@ public final class AutoBoatController {
this.placeTarget = null;
this.boardTargetEntityId = -1;
this.boatEntityId = -1;
this.arrivedTicks = 0;
this.lastLoggedPhase = null;
}
@@ -161,6 +192,7 @@ public final class AutoBoatController {
public String describe() {
return switch (this.flow) {
case FLOW_ENTER -> "正在自动登船";
case FLOW_SAIL -> "正在坐船航行";
case FLOW_EXIT -> "正在上岸回收船";
default -> null;
};
@@ -176,11 +208,17 @@ public final class AutoBoatController {
*/
private boolean shouldBoardBoat(MinecraftClient client, ExpansionConfig config) {
PlayerEntity player = client.player;
// 玩家完全没入水中:暂不处理,等 Baritone 处理上岸(或玩家主动下船)
if (player.isSubmergedInWater()) {
// 登船失败冷却中:不重复尝试(避免每帧重试刷屏/浪费物品)
if (this.failCooldownTicks > 0) {
return false;
}
// 玩家脚下为水方块(浅水行走)或睡莲:也允许尝试放船
// 玩家没入深水(脚部上方 2 格仍是水,即已沉到水面以下 2 格以上):
// 先由自动游泳把玩家浮到水面附近再放船登船,避免把船放在头顶够不到的水里。
// 注意:水面正常游泳(潜水/漂浮)是允许登船的——这正是"开阔水面自动用船"的关键。
if (this.isWaterAt(client.world, player.getBlockPos().up(2))) {
return false;
}
// 玩家脚下为水方块(浅水/水面游泳)或睡莲:也允许尝试放船
BlockPos playerPos = player.getBlockPos();
if (!isStandable(client.world, playerPos) && !this.isWaterAt(client.world, playerPos)
&& !client.world.getBlockState(playerPos).isOf(Blocks.LILY_PAD)) {
@@ -345,10 +383,13 @@ public final class AutoBoatController {
this.lastLoggedPhase = null;
// 暂存当前主手槽位,结束后还原
this.savedSelectedSlot = client.player.getInventory().selectedSlot;
// 按住蹲伏键以阻止 Baritone 把玩家推进水里(也避免登船后立即被推动离开船)
// 在岸上时按住蹲伏键阻止 Baritone 把玩家推进水里;水面游泳登船时不按蹲伏
//(蹲伏会让角色下沉,反而不利),且 ExpansionController 已在用船期间取消 Baritone。
if (!client.player.isTouchingWater()) {
this.pressSneak(client);
this.holdingSneak = true;
}
}
private void tickEnter(MinecraftClient client) {
switch (this.phase) {
@@ -369,13 +410,13 @@ public final class AutoBoatController {
// 若玩家当前站在陆地:仍允许(船会被放在脚前的水方块上)
BlockPos waterPos = this.placeTarget != null ? this.placeTarget : player.getBlockPos();
if (!this.isWaterAt(client.world, waterPos)) {
// 没有合适的水方块 → 取消
this.reset(client, true);
// 没有合适的水方块 → 取消(进入冷却,避免每帧重试)
this.cancelEnter(client, "没有合适的水面,取消登船");
return;
}
int slot = this.findBoatSlot(player);
if (slot < 0) {
this.reset(client, true);
this.cancelEnter(client, "背包里没有船,取消登船");
return;
}
// 切换主手到船物品并放置
@@ -401,9 +442,8 @@ public final class AutoBoatController {
// 在附近寻找新放置的船
AbstractBoatEntity boat = this.findNearbyBoat(client, 6.0);
if (boat == null) {
// 没找到:可能服务器拒收 / 反作弊拦截 → 取消
this.logPhaseOnce(client, "放船后未找到船实体,取消登船");
this.reset(client, true);
// 没找到:可能服务器拒收 / 反作弊拦截 → 取消(进入冷却)
this.cancelEnter(client, "放船后未找到船实体,取消登船");
return;
}
this.boardTargetEntityId = boat.getId();
@@ -418,7 +458,7 @@ public final class AutoBoatController {
// 实体可能已被销毁:再扫一次附近
boat = this.findNearbyBoat(client, 4.0);
if (boat == null) {
this.reset(client, true);
this.cancelEnter(client, "登船目标丢失,取消登船");
return;
}
this.boardTargetEntityId = boat.getId();
@@ -437,21 +477,29 @@ public final class AutoBoatController {
return;
}
if (!(client.player.getVehicle() instanceof AbstractBoatEntity)) {
// 登船失败 → 取消
this.reset(client, true);
// 登船失败 → 取消(进入冷却)
this.cancelEnter(client, "登船失败,取消登船");
return;
}
// 释放蹲伏键,Baritone 恢复自动寻路(此时玩家在船中,按 W 即可让船前进)
// 释放蹲伏键,进入坐船航行阶段(船由本类手动朝目标导航,Baritone 已取消)
this.releaseSneak(client);
this.holdingSneak = false;
this.logPhaseOnce(client, "自动登船完成,开始过水");
this.flow = IDLE;
// 还原主手槽位(船航行不依赖主手)
this.restoreSelectedSlot(client);
this.logPhaseOnce(client, "自动登船完成,开始过水航行");
this.flow = FLOW_SAIL;
this.phase = PHASE_PLACE;
this.phaseTicks = 0;
this.placeTarget = null;
this.boardTargetEntityId = -1;
// 还原主手槽位(让 Baritone 自由切回所需工具)
this.restoreSelectedSlot(client);
this.arrivedTicks = 0;
}
/** 登船流程失败:记录日志、进入失败冷却(避免每帧重试刷屏)、清理流程状态 */
private void cancelEnter(MinecraftClient client, String message) {
this.logPhaseOnce(client, message);
this.failCooldownTicks = BOARD_FAIL_COOLDOWN_TICKS;
this.reset(client, true);
}
/** 玩家正前方 1 格内的水面方块(脚下优先);找不到返回 null */
@@ -501,6 +549,79 @@ public final class AutoBoatController {
this.savedSelectedSlot = -1;
}
// =========================== 坐船航行 ===========================
/** 开启坐船航行流程:接管船的移动,朝目标区块方向前进(Baritone 已由控制器取消) */
private void beginSail(MinecraftClient client) {
if (this.flow != IDLE) {
return;
}
this.flow = FLOW_SAIL;
this.arrivedTicks = 0;
this.lastLoggedPhase = null;
this.logPhaseOnce(client, "开始坐船航行");
}
/** 航行中每帧:靠岸或到达目标区块附近则下船回收;否则面向目标按住前进键 */
private void tickSail(MinecraftClient client, ExpansionConfig config, ChunkPos target) {
PlayerEntity player = client.player;
if (!(player.getVehicle() instanceof AbstractBoatEntity)) {
// 船已消失(被销毁 / 玩家被踢出):结束航行,交给 ExpansionController 恢复寻路
this.logPhaseOnce(client, "航行中船已消失,结束用船");
this.finishSail(client, false);
return;
}
// 前方即将靠岸:下船回收
if (this.shouldDisembark(client, config)) {
this.finishSail(client, true);
return;
}
// 已到达目标区块:再航一会儿找岸边;超时仍未靠岸则直接下船(自动游泳会接管漂浮)
if (this.reachedTarget(player, target)) {
if (++this.arrivedTicks > ARRIVED_FORCE_DISEMBARK_TICKS) {
this.logPhaseOnce(client, "已到达目标区块,直接下船");
this.finishSail(client, true);
return;
}
}
// 面向目标航行
this.steerTowardTarget(client, target);
this.pressForward(client);
}
/** 结束航行流程:释放前进键;需要下船时进入上岸流程,否则直接恢复寻路 */
private void finishSail(MinecraftClient client, boolean disembark) {
this.releaseForward(client);
if (disembark && client.player.getVehicle() instanceof AbstractBoatEntity boat) {
this.beginDisembark(client, boat);
return;
}
this.flow = IDLE;
this.arrivedTicks = 0;
this.lastLoggedPhase = null;
}
/** 玩家当前区块是否已到达目标区块 */
private boolean reachedTarget(PlayerEntity player, ChunkPos target) {
return target != null && ChunkPos.fromBlock(player.getBlockX(), player.getBlockZ()).equals(target);
}
/** 把玩家朝向对准目标区块中心(水平方向),船会沿视线方向前进 */
private void steerTowardTarget(MinecraftClient client, ChunkPos target) {
if (target == null || client.player == null) {
return;
}
PlayerEntity player = client.player;
double dx = target.centerBlockX() + 0.5 - player.getX();
double dz = target.centerBlockZ() + 0.5 - player.getZ();
if (dx * dx + dz * dz < 1.0e-6) {
return;
}
// Minecraft yaw 约定:yaw=0 面向 +Z(南),x 分量 = -sin(yaw)
float yaw = (float) Math.toDegrees(Math.atan2(-dx, dz));
player.setYaw(yaw);
}
// =========================== 上岸流程 ===========================
private void beginDisembark(MinecraftClient client, AbstractBoatEntity boat) {
@@ -612,6 +733,24 @@ public final class AutoBoatController {
sneak.setPressed(false);
}
/** 按下前进键(坐船航行时持续按住,使船沿视线方向前进) */
private void pressForward(MinecraftClient client) {
if (client.player == null) return;
if (!this.holdingForward) {
client.options.forwardKey.setPressed(true);
this.holdingForward = true;
}
}
/** 释放前进键 */
private void releaseForward(MinecraftClient client) {
if (client.player == null) return;
if (this.holdingForward) {
client.options.forwardKey.setPressed(false);
this.holdingForward = false;
}
}
/** 在指定半径内查找最接近玩家的船实体 */
private AbstractBoatEntity findNearbyBoat(MinecraftClient client, double radius) {
Vec3d center = client.player.getPos();
+1 -1
查看文件
@@ -1 +1 @@
{"schemaVersion":1,"id":"autostore","version":"1.3.0","name":"AutoStore","description":"","authors":[],"contact":{},"license":"All-Rights-Reserved","environment":"client","entrypoints":{"fabric-datagen":["autostore.client.AutoStoreModDataGenerator"],"client":["autostore.client.AutoStoreModClient"],"main":["autostore.AutoStoreMod"]},"mixins":["autostore.mixins.json",{"config":"autostore.client.mixins.json","environment":"client"}],"depends":{"fabricloader":">=0.16.14","fabric-api":"*","minecraft":"1.21.4"},"jars":[{"file":"META-INF/jars/baritone-api-fabric-1.13.1.jar"}]}
{"schemaVersion":1,"id":"autostore","version":"1.3.1","name":"AutoStore","description":"","authors":[],"contact":{},"license":"All-Rights-Reserved","environment":"client","entrypoints":{"fabric-datagen":["autostore.client.AutoStoreModDataGenerator"],"client":["autostore.client.AutoStoreModClient"],"main":["autostore.AutoStoreMod"]},"mixins":["autostore.mixins.json",{"config":"autostore.client.mixins.json","environment":"client"}],"depends":{"fabricloader":">=0.16.14","fabric-api":"*","minecraft":"1.21.4"},"jars":[{"file":"META-INF/jars/baritone-api-fabric-1.13.1.jar"}]}