Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file modified gradlew
100644 → 100755
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,8 @@ public final class AdvancedConfig {
public double supplyInteractionTimeoutSeconds = 2.0;
public double furnaceInteractionTimeoutSeconds = 2.0;
public int flightRetryCount = 2;
public boolean miningStallDetectionEnabled = true;
public double miningStallTimeoutSeconds = 8.0;
public int miningStallMovementDistance = 3;
public double miningStallCooldownSeconds = 15.0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,13 @@ public void disablePlacement() {
BaritoneAPI.getSettings().allowPlace.value = false;
}

public void disableBreakingAndPlacement() {
if (savedAllowBreak == null) savedAllowBreak = BaritoneAPI.getSettings().allowBreak.value;
if (savedAllowPlace == null) savedAllowPlace = BaritoneAPI.getSettings().allowPlace.value;
BaritoneAPI.getSettings().allowBreak.value = false;
BaritoneAPI.getSettings().allowPlace.value = false;
}

public void enableBreakingWithoutPlacement() {
if (savedAllowBreak == null) savedAllowBreak = BaritoneAPI.getSettings().allowBreak.value;
if (savedAllowPlace == null) savedAllowPlace = BaritoneAPI.getSettings().allowPlace.value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,11 @@ public final class AutomationController {
private Vec3 watchdogPosition;
private int watchdogStationaryScans;
private int watchdogRetries;
private Vec3 miningStallPosition;
private int miningStallStationaryScans;
private int miningStallLastTriggerTick;
private boolean miningStallRecovery;
private BlockPos miningStallRecoveryTarget;
private int stableInventoryScans;
private int lastInventoryItemCount;
private boolean miningCompletePending;
Expand Down Expand Up @@ -310,6 +315,7 @@ public List<String> debugSleep(PerimeterConfig config) {
public void tick() {
if (baritone == null || baritone.getPlayerContext().player() == null) return;
executeInventoryClick();
if (miningStallRecovery && tickMiningStallRecovery()) return;
if (state == AutomationState.EATING) {
tickEating();
return;
Expand Down Expand Up @@ -375,6 +381,7 @@ && shouldEat()
if (state == AutomationState.IDLE || state == AutomationState.ERROR || state == AutomationState.COMPLETE || state == AutomationState.PAUSED
) return;
if (!inventoryClicks.isEmpty()) return;
if (state == AutomationState.MINING && advanced.miningStallDetectionEnabled) tickMiningStallDetection();
ResourceCheck resources = inspectResources();
if (sleepEnabled && bedPoint != null && isBedTime()) {
beginSleepFlow(false);
Expand All @@ -399,9 +406,14 @@ && shouldEat()
if (durabilityRecoveryMode.equals("supply_point") && durabilitySupplyPoint != null) {
beginSupply(SupplyFlow.Kind.DURABILITY, false);
return;
} else if (durabilityRecoveryMode.equals("repair_portal") && hasUsableRepairConfiguration()) {
beginRepairFlow(false);
return;
} else if (durabilityRecoveryMode.equals("repair_portal")) {
if (hasUsableRepairConfiguration()) {
beginRepairFlow(false);
return;
} else if (durabilitySupplyPoint != null) {
beginSupply(SupplyFlow.Kind.DURABILITY, false);
return;
}
}
}
if (resupplyEnabled && consumableSupplyPoint != null
Expand Down Expand Up @@ -430,6 +442,7 @@ public void stop() {
returnPortalWaypoint = null;
inventoryClicks.clear();
resetNavigationWatchdog();
resetMiningStall();
unload.reset();
clearSleepContext();
clearSupplyContext();
Expand Down Expand Up @@ -558,6 +571,7 @@ else synchronize(AutomationState.PAUSED, Translations.DETAIL.message("mining_pau
}

private void startMiningCycle() {
resetMiningStall();
int emptySlots = emptyInventorySlots();
if (emptySlots == 0 && unloadEnabled) {
requestUnload();
Expand All @@ -572,6 +586,7 @@ private void startMiningCycle() {
}

private void resumeMiningCycle() {
resetMiningStall();
int emptySlots = emptyInventorySlots();
if (emptySlots == 0 && unloadEnabled) {
requestUnload();
Expand Down Expand Up @@ -1023,6 +1038,24 @@ private Optional<BlockPos> closestBedStand(BlockPos bed) {
return interactionPositionFinder.closest(Minecraft.getInstance().level, bed, baritone.getPlayerContext().playerFeet());
}

private BlockPos findSafeStandNear(BlockPos chest) {
BetterBlockPos player = baritone.getPlayerContext().playerFeet();
List<BlockPos> candidates = new ArrayList<>();
for (int dy = -1; dy <= 1; dy++) {
BlockPos base = chest.atY(chest.getY() + dy);
for (int dx = -advanced.unloadLandingSearchRadius; dx <= advanced.unloadLandingSearchRadius; dx++) {
for (int dz = -advanced.unloadLandingSearchRadius; dz <= advanced.unloadLandingSearchRadius; dz++) {
if (dx == 0 && dz == 0 && dy == 0) continue;
BlockPos position = base.offset(dx, 0, dz);
if (isSafeStandingPosition(position)) {
candidates.add(position);
}
}
}
}
return candidates.stream().min(Comparator.comparingDouble(player::distSqr)).orElse(null);
}

private boolean canReachFurnace(BlockPos furnace) {
return canReachInteractionTarget(furnace);
}
Expand Down Expand Up @@ -1116,7 +1149,7 @@ private AutomationState supplyInteractionState() {

private void startWalkingToSupply() {
supply.flying = false;
disablePlacementForNavigation();
enableBreakingForNavigation();
BlockPos chest = position(supply.point);
if (isAtInteractionStand(chest)) {
restoreAllowPlace();
Expand All @@ -1127,15 +1160,22 @@ private void startWalkingToSupply() {
if (!stands.isEmpty()) {
supply.stand = stands.stream().min(Comparator.comparingDouble(baritone.getPlayerContext().playerFeet()::distSqr)).orElseThrow();
navigation.walk(new GoalComposite(stands.stream().map(GoalBlock::new).toArray(Goal[]::new)));
} else {
supply.stand = chest.above();
transition(supplyNavigationState(), Translations.DETAIL.message("walking_supply", supply.kind.displayName, supply.stand.toShortString()));
return;
}
BlockPos widerStand = findSafeStandNear(chest);
if (widerStand != null) {
supply.stand = widerStand;
navigation.walk(new GoalBlock(supply.stand));
transition(supplyNavigationState(), Translations.DETAIL.message("walking_supply", supply.kind.displayName, supply.stand.toShortString()));
return;
}
transition(supplyNavigationState(), Translations.DETAIL.message("walking_supply", supply.kind.displayName, supply.stand.toShortString()));
restoreAllowPlace();
transition(AutomationState.ERROR, Translations.DETAIL.message("supply_no_safe_stand", supply.kind.displayName, chest.toShortString()));
}

private void tickSupplyNavigation() {
if (isAtInteractionStand(position(supply.point))) {
if (isAtInteractionStand(position(supply.point)) || baritone.getPlayerContext().playerFeet().equals(supply.stand)) {
navigation.stopFlying();
navigation.stopWalking();
restoreElytraMinimumDurability();
Expand Down Expand Up @@ -1180,6 +1220,10 @@ private void disablePlacementForNavigation() {
navigation.disablePlacement();
}

private void disableBreakingAndPlacementForNavigation() {
navigation.disableBreakingAndPlacement();
}

private void enableBreakingForNavigation() {
navigation.enableBreakingWithoutPlacement();
}
Expand Down Expand Up @@ -1903,7 +1947,8 @@ private void requestUnload() {
unload.point = unloadingPoints.stream()
.min(Comparator.comparingLong(point -> horizontalDistanceSquared(player, point.point())))
.orElseThrow();
UnloadFlow.Candidate preferred = findUnloadCandidates(unload.point.point(), player.y).stream().findFirst().orElse(null);
int preferredY = Math.max(player.y, unload.point.point().minY);
UnloadFlow.Candidate preferred = findUnloadCandidates(unload.point.point(), preferredY).stream().findFirst().orElse(null);
BlockPos flightTarget = preferred == null
? new BlockPos(unload.point.point().x, player.y, unload.point.point().z)
: preferred.position();
Expand All @@ -1927,7 +1972,8 @@ private void beginUnloadApproach() {
navigation.stopFlying();
disablePlacementForNavigation();
int currentY = baritone.getPlayerContext().playerFeet().y;
unload.candidates = findUnloadCandidates(unload.point.point(), currentY);
int preferredY = Math.max(currentY, unload.point.point().minY);
unload.candidates = findUnloadCandidates(unload.point.point(), preferredY);
unload.candidateIndex = 0;
if (unload.candidates.isEmpty()) {
restoreAllowPlace();
Expand Down Expand Up @@ -2319,6 +2365,70 @@ private void resetNavigationWatchdog() {
watchdogRetries = 0;
}

private void tickMiningStallDetection() {
Vec3 position = baritone.getPlayerContext().player().position();
if (miningStallPosition == null || position.distanceToSqr(miningStallPosition) > 0.25) {
miningStallPosition = position;
miningStallStationaryScans = 0;
return;
}
if (++miningStallStationaryScans < monitorScans(advanced.miningStallTimeoutSeconds)) return;
int cooldownTicks = ticks(advanced.miningStallCooldownSeconds);
if (tickCounter - miningStallLastTriggerTick < cooldownTicks) return;
BlockPos target = randomNearbySafeTarget(advanced.miningStallMovementDistance);
if (target == null) return;
miningStallStationaryScans = 0;
miningStallLastTriggerTick = tickCounter;
miningStallRecovery = true;
miningStallRecoveryTarget = target;
miningProcess.pause();
navigation.walk(new GoalBlock(target));
transition(AutomationState.MINING, Translations.DETAIL.message("mining_stall_recovery", target.toShortString()));
}

private boolean tickMiningStallRecovery() {
BlockPos feet = baritone.getPlayerContext().playerFeet();
if (feet.equals(miningStallRecoveryTarget) || !navigation.isWalking()) {
navigation.stopWalking();
miningStallRecovery = false;
miningStallRecoveryTarget = null;
miningStallPosition = null;
miningStallStationaryScans = 0;
resumeMiningCycle();
return true;
}
return false;
}

private BlockPos randomNearbySafeTarget(int distance) {
BlockPos feet = baritone.getPlayerContext().playerFeet();
double[] angles = new double[8];
for (int i = 0; i < 8; i++) angles[i] = Math.random() * 2.0 * Math.PI;
for (double angle : angles) {
int dx = (int) Math.round(Math.sin(angle) * distance);
int dz = (int) Math.round(Math.cos(angle) * distance);
if (dx == 0 && dz == 0) continue;
BlockPos candidate = feet.offset(dx, 0, dz);
if (isSafeStandingPosition(candidate)) return candidate;
}
for (int dx = -distance; dx <= distance; dx++) {
for (int dz = -distance; dz <= distance; dz++) {
if (dx == 0 && dz == 0) continue;
if (dx * dx + dz * dz > distance * distance) continue;
BlockPos candidate = feet.offset(dx, 0, dz);
if (isSafeStandingPosition(candidate)) return candidate;
}
}
return null;
}

private void resetMiningStall() {
miningStallPosition = null;
miningStallStationaryScans = 0;
miningStallRecovery = false;
miningStallRecoveryTarget = null;
}

private int firstDisposableSlot() {
Inventory inventory = baritone.getPlayerContext().player().getInventory();
for (int slot = 0; slot < 36; slot++) {
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/assets/perimeter-digger/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@
"perimeterdigger.detail.supply_point_missing": "No %1$s supply point is configured.",
"perimeterdigger.detail.walking_supply": "Walking to the %1$s supply chest %2$s.",
"perimeterdigger.detail.supply_unreachable": "The %1$s supply chest is unreachable: %2$s.",
"perimeterdigger.detail.supply_no_safe_stand": "No safe standing position was found near the %1$s supply chest at %2$s.",
"perimeterdigger.detail.flying_supply": "Flying to the %1$s supply point %2$s.",
"perimeterdigger.detail.preparing_supply": "Preparing the %1$s supply chest.",
"perimeterdigger.detail.supply_open_timeout": "Timed out while opening the %1$s supply chest.",
Expand Down Expand Up @@ -202,6 +203,7 @@
"perimeterdigger.detail.repair_debug_complete": "Repair debug flow complete.",
"perimeterdigger.detail.sleep_debug_complete": "Sleep debug flow complete.",
"perimeterdigger.detail.navigation_stalled": "Navigation made no positional progress after %1$s retries toward %2$s.",
"perimeterdigger.detail.mining_stall_recovery": "Mining stalled; attempting stall recovery move to %1$s.",
"perimeterdigger.detail.replacing_item": "Replacing low-durability %1$s.",
"perimeterdigger.detail.replaced_item": "Replaced low-durability %1$s.",
"perimeterdigger.detail.mining_paused": "Mining paused: %1$s. %2$s",
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/assets/perimeter-digger/lang/zh_cn.json
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@
"perimeterdigger.detail.supply_point_missing": "未配置 %1$s 补给点。",
"perimeterdigger.detail.walking_supply": "正在步行前往 %1$s 补给箱 %2$s。",
"perimeterdigger.detail.supply_unreachable": "无法到达 %1$s 补给箱:%2$s。",
"perimeterdigger.detail.supply_no_safe_stand": "在 %1$s 补给箱 %2$s 附近未找到安全站立位置。",
"perimeterdigger.detail.flying_supply": "正在飞向 %1$s 补给点 %2$s。",
"perimeterdigger.detail.preparing_supply": "正在准备操作 %1$s 补给箱。",
"perimeterdigger.detail.supply_open_timeout": "打开 %1$s 补给箱超时。",
Expand Down Expand Up @@ -202,6 +203,7 @@
"perimeterdigger.detail.repair_debug_complete": "修复调试流程已完成。",
"perimeterdigger.detail.sleep_debug_complete": "睡眠调试流程已完成。",
"perimeterdigger.detail.navigation_stalled": "向 %2$s 寻路时连续 %1$s 次重试均无位置进展。",
"perimeterdigger.detail.mining_stall_recovery": "挖掘停滞,尝试向 %1$s 脱困移动。",
"perimeterdigger.detail.replacing_item": "正在更换低耐久物品 %1$s。",
"perimeterdigger.detail.replaced_item": "已更换低耐久物品 %1$s。",
"perimeterdigger.detail.mining_paused": "挖掘已暂停:%1$s。%2$s",
Expand Down