Merge branch 'master' into tenor
This commit is contained in:
@@ -5,12 +5,15 @@
|
||||
[](https://www.codacy.com/app/leijurv/baritone?utm_source=github.com&utm_medium=referral&utm_content=cabaletta/baritone&utm_campaign=Badge_Grade)
|
||||
[](http://hits.dwyl.com/cabaletta/baritone)
|
||||
[](https://github.com/cabaletta/baritone/issues)
|
||||
[](https://minecraft.gamepedia.com/1.12.2)
|
||||
|
||||
A Minecraft pathfinder bot. This project is an updated version of [MineBot](https://github.com/leijurv/MineBot/),
|
||||
the original version of the bot for Minecraft 1.8, rebuilt for 1.12.2. Baritone focuses on reliability and particularly performance (it's over [29x faster](https://github.com/cabaletta/baritone/pull/180#issuecomment-423822928) than MineBot at calculating paths).
|
||||
A Minecraft pathfinder bot.
|
||||
|
||||
Baritone is the pathfinding system used in [Impact](https://impactdevelopment.github.io/) since 4.4. There's a [showcase video](https://www.youtube.com/watch?v=yI8hgW_m6dQ) made by @Adovin#3153 on Baritone's integration into Impact. [Here's](https://www.youtube.com/watch?v=StquF69-_wI) a video I made showing off what it can do.
|
||||
|
||||
This project is an updated version of [MineBot](https://github.com/leijurv/MineBot/),
|
||||
the original version of the bot for Minecraft 1.8, rebuilt for 1.12.2. Baritone focuses on reliability and particularly performance (it's over [29x faster](https://github.com/cabaletta/baritone/pull/180#issuecomment-423822928) than MineBot at calculating paths).
|
||||
|
||||
Here are some links to help to get started:
|
||||
|
||||
- [Features](FEATURES.md)
|
||||
@@ -21,29 +24,29 @@ There's also some useful information down below
|
||||
|
||||
# Setup
|
||||
|
||||
## IntelliJ's Gradle UI
|
||||
- Open the project in IntelliJ as a Gradle project
|
||||
- Run the Gradle task `setupDecompWorkspace`
|
||||
- Run the Gradle task `genIntellijRuns`
|
||||
- Refresh the Gradle project (or just restart IntelliJ)
|
||||
- Select the "Minecraft Client" launch config and run
|
||||
|
||||
## Command Line
|
||||
On Mac OSX and Linux, use `./gradlew` instead of `gradlew`.
|
||||
|
||||
Running Baritone:
|
||||
|
||||
```
|
||||
$ gradlew run
|
||||
$ gradlew runClient
|
||||
```
|
||||
|
||||
Setting up for IntelliJ:
|
||||
Building Baritone:
|
||||
```
|
||||
$ gradlew setupDecompWorkspace
|
||||
$ gradlew --refresh-dependencies
|
||||
$ gradlew genIntellijRuns
|
||||
$ gradlew build
|
||||
```
|
||||
|
||||
For example, to replace out Impact 4.4's Baritone build with a customized one, switch to the `impact4.4-compat` branch, build Baritone as above then copy `dist/baritone-api-$VERSION$.jar` into `minecraft/libraries/cabaletta/baritone-api/1.0.0/baritone-api-1.0.0.jar`, replacing the jar that was previously there. You also need to edit `minecraft/versions/1.12.2-Impact_4.4/1.12.2-Impact_4.4.json`, find the line `"name": "cabaletta:baritone-api:1.0.0"`, remove the comma from the end, and entirely remove the line that's immediately after (starts with `"url"`).
|
||||
|
||||
## IntelliJ's Gradle UI
|
||||
- Open the project in IntelliJ as a Gradle project
|
||||
- Run the Gradle tasks `setupDecompWorkspace` then `genIntellijRuns`
|
||||
- Refresh the Gradle project (or, to be safe, just restart IntelliJ)
|
||||
- Select the "Minecraft Client" launch config
|
||||
- In `Edit Configurations...` you may need to select `baritone_launch` for `Use classpath of module:`.
|
||||
|
||||
# Chat control
|
||||
[Defined Here](src/main/java/baritone/utils/ExampleBaritoneControl.java)
|
||||
|
||||
|
||||
+1
-1
@@ -62,7 +62,7 @@ sourceSets {
|
||||
|
||||
minecraft {
|
||||
version = '1.12.2'
|
||||
mappings = 'snapshot_20180731'
|
||||
mappings = 'stable_39'
|
||||
tweakClass = 'baritone.launch.BaritoneTweaker'
|
||||
runDir = 'run'
|
||||
|
||||
|
||||
@@ -17,10 +17,16 @@
|
||||
|
||||
package baritone.api;
|
||||
|
||||
import baritone.api.behavior.*;
|
||||
import baritone.api.behavior.ILookBehavior;
|
||||
import baritone.api.behavior.IMemoryBehavior;
|
||||
import baritone.api.behavior.IPathingBehavior;
|
||||
import baritone.api.cache.IWorldProvider;
|
||||
import baritone.api.cache.IWorldScanner;
|
||||
import baritone.api.event.listener.IGameEventListener;
|
||||
import baritone.api.process.ICustomGoalProcess;
|
||||
import baritone.api.process.IFollowProcess;
|
||||
import baritone.api.process.IGetToBlockProcess;
|
||||
import baritone.api.process.IMineProcess;
|
||||
import baritone.api.utils.SettingsUtil;
|
||||
|
||||
import java.util.Iterator;
|
||||
@@ -36,20 +42,20 @@ import java.util.ServiceLoader;
|
||||
*/
|
||||
public final class BaritoneAPI {
|
||||
|
||||
private static final IBaritoneProvider baritone;
|
||||
private static final IBaritone baritone;
|
||||
private static final Settings settings;
|
||||
|
||||
static {
|
||||
ServiceLoader<IBaritoneProvider> baritoneLoader = ServiceLoader.load(IBaritoneProvider.class);
|
||||
Iterator<IBaritoneProvider> instances = baritoneLoader.iterator();
|
||||
baritone = instances.next();
|
||||
baritone = instances.next().getBaritoneForPlayer(null); // PWNAGE
|
||||
|
||||
settings = new Settings();
|
||||
SettingsUtil.readAndApply(settings);
|
||||
}
|
||||
|
||||
public static IFollowBehavior getFollowBehavior() {
|
||||
return baritone.getFollowBehavior();
|
||||
public static IFollowProcess getFollowProcess() {
|
||||
return baritone.getFollowProcess();
|
||||
}
|
||||
|
||||
public static ILookBehavior getLookBehavior() {
|
||||
@@ -60,8 +66,8 @@ public final class BaritoneAPI {
|
||||
return baritone.getMemoryBehavior();
|
||||
}
|
||||
|
||||
public static IMineBehavior getMineBehavior() {
|
||||
return baritone.getMineBehavior();
|
||||
public static IMineProcess getMineProcess() {
|
||||
return baritone.getMineProcess();
|
||||
}
|
||||
|
||||
public static IPathingBehavior getPathingBehavior() {
|
||||
@@ -80,6 +86,14 @@ public final class BaritoneAPI {
|
||||
return baritone.getWorldScanner();
|
||||
}
|
||||
|
||||
public static ICustomGoalProcess getCustomGoalProcess() {
|
||||
return baritone.getCustomGoalProcess();
|
||||
}
|
||||
|
||||
public static IGetToBlockProcess getGetToBlockProcess() {
|
||||
return baritone.getGetToBlockProcess();
|
||||
}
|
||||
|
||||
public static void registerEventListener(IGameEventListener listener) {
|
||||
baritone.registerEventListener(listener);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.api;
|
||||
|
||||
import baritone.api.behavior.ILookBehavior;
|
||||
import baritone.api.behavior.IMemoryBehavior;
|
||||
import baritone.api.behavior.IPathingBehavior;
|
||||
import baritone.api.cache.IWorldProvider;
|
||||
import baritone.api.cache.IWorldScanner;
|
||||
import baritone.api.event.listener.IGameEventListener;
|
||||
import baritone.api.process.ICustomGoalProcess;
|
||||
import baritone.api.process.IFollowProcess;
|
||||
import baritone.api.process.IGetToBlockProcess;
|
||||
import baritone.api.process.IMineProcess;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 9/29/2018
|
||||
*/
|
||||
public interface IBaritone {
|
||||
|
||||
/**
|
||||
* @return The {@link IFollowProcess} instance
|
||||
* @see IFollowProcess
|
||||
*/
|
||||
IFollowProcess getFollowProcess();
|
||||
|
||||
/**
|
||||
* @return The {@link ILookBehavior} instance
|
||||
* @see ILookBehavior
|
||||
*/
|
||||
ILookBehavior getLookBehavior();
|
||||
|
||||
/**
|
||||
* @return The {@link IMemoryBehavior} instance
|
||||
* @see IMemoryBehavior
|
||||
*/
|
||||
IMemoryBehavior getMemoryBehavior();
|
||||
|
||||
/**
|
||||
* @return The {@link IMineProcess} instance
|
||||
* @see IMineProcess
|
||||
*/
|
||||
IMineProcess getMineProcess();
|
||||
|
||||
/**
|
||||
* @return The {@link IPathingBehavior} instance
|
||||
* @see IPathingBehavior
|
||||
*/
|
||||
IPathingBehavior getPathingBehavior();
|
||||
|
||||
/**
|
||||
* @return The {@link IWorldProvider} instance
|
||||
* @see IWorldProvider
|
||||
*/
|
||||
IWorldProvider getWorldProvider();
|
||||
|
||||
/**
|
||||
* @return The {@link IWorldScanner} instance
|
||||
* @see IWorldScanner
|
||||
*/
|
||||
IWorldScanner getWorldScanner();
|
||||
|
||||
ICustomGoalProcess getCustomGoalProcess();
|
||||
|
||||
IGetToBlockProcess getGetToBlockProcess();
|
||||
|
||||
/**
|
||||
* Registers a {@link IGameEventListener} with Baritone's "event bus".
|
||||
*
|
||||
* @param listener The listener
|
||||
*/
|
||||
void registerEventListener(IGameEventListener listener);
|
||||
}
|
||||
@@ -17,70 +17,19 @@
|
||||
|
||||
package baritone.api;
|
||||
|
||||
import baritone.api.behavior.*;
|
||||
import baritone.api.cache.IWorldProvider;
|
||||
import baritone.api.cache.IWorldScanner;
|
||||
import baritone.api.event.listener.IGameEventListener;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 9/29/2018
|
||||
* @author Leijurv
|
||||
*/
|
||||
public interface IBaritoneProvider {
|
||||
|
||||
/**
|
||||
* @see IFollowBehavior
|
||||
* Provides the {@link IBaritone} instance for a given {@link EntityPlayerSP}. This will likely be
|
||||
* replaced with {@code #getBaritoneForUser(IBaritoneUser)} when {@code bot-system} is merged.
|
||||
*
|
||||
* @return The {@link IFollowBehavior} instance
|
||||
* @param player The player
|
||||
* @return The {@link IBaritone} instance.
|
||||
*/
|
||||
IFollowBehavior getFollowBehavior();
|
||||
|
||||
/**
|
||||
* @see ILookBehavior
|
||||
*
|
||||
* @return The {@link ILookBehavior} instance
|
||||
*/
|
||||
ILookBehavior getLookBehavior();
|
||||
|
||||
/**
|
||||
* @see IMemoryBehavior
|
||||
*
|
||||
* @return The {@link IMemoryBehavior} instance
|
||||
*/
|
||||
IMemoryBehavior getMemoryBehavior();
|
||||
|
||||
/**
|
||||
* @see IMineBehavior
|
||||
*
|
||||
* @return The {@link IMineBehavior} instance
|
||||
*/
|
||||
IMineBehavior getMineBehavior();
|
||||
|
||||
/**
|
||||
* @see IPathingBehavior
|
||||
*
|
||||
* @return The {@link IPathingBehavior} instance
|
||||
*/
|
||||
IPathingBehavior getPathingBehavior();
|
||||
|
||||
/**
|
||||
* @see IWorldProvider
|
||||
*
|
||||
* @return The {@link IWorldProvider} instance
|
||||
*/
|
||||
IWorldProvider getWorldProvider();
|
||||
|
||||
/**
|
||||
* @see IWorldScanner
|
||||
*
|
||||
* @return The {@link IWorldScanner} instance
|
||||
*/
|
||||
IWorldScanner getWorldScanner();
|
||||
|
||||
/**
|
||||
* Registers a {@link IGameEventListener} with Baritone's "event bus".
|
||||
*
|
||||
* @param listener The listener
|
||||
*/
|
||||
void registerEventListener(IGameEventListener listener);
|
||||
IBaritone getBaritoneForPlayer(EntityPlayerSP player);
|
||||
}
|
||||
|
||||
@@ -24,8 +24,8 @@ import net.minecraft.util.text.ITextComponent;
|
||||
|
||||
import java.awt.*;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
@@ -276,6 +276,13 @@ public class Settings {
|
||||
*/
|
||||
public Setting<Boolean> chunkCaching = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* On save, delete from RAM any cached regions that are more than 1024 blocks away from the player
|
||||
* <p>
|
||||
* Temporarily disabled, see issue #248
|
||||
*/
|
||||
public Setting<Boolean> pruneRegionsFromRAM = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* Print all the debug messages to chat
|
||||
*/
|
||||
@@ -305,17 +312,17 @@ public class Settings {
|
||||
/**
|
||||
* Ignore depth when rendering the goal
|
||||
*/
|
||||
public Setting<Boolean> renderGoalIgnoreDepth = new Setting<>(false);
|
||||
public Setting<Boolean> renderGoalIgnoreDepth = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Ignore depth when rendering the selection boxes (to break, to place, to walk into)
|
||||
*/
|
||||
public Setting<Boolean> renderSelectionBoxesIgnoreDepth = new Setting<>(false);
|
||||
public Setting<Boolean> renderSelectionBoxesIgnoreDepth = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Ignore depth when rendering the path
|
||||
*/
|
||||
public Setting<Boolean> renderPathIgnoreDepth = new Setting<>(false);
|
||||
public Setting<Boolean> renderPathIgnoreDepth = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Line width of the path when rendered, in pixels
|
||||
@@ -370,12 +377,27 @@ public class Settings {
|
||||
*/
|
||||
public Setting<Boolean> walkWhileBreaking = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* If we are more than 500 movements into the current path, discard the oldest segments, as they are no longer useful
|
||||
*/
|
||||
public Setting<Integer> maxPathHistoryLength = new Setting<>(300);
|
||||
|
||||
/**
|
||||
* If the current path is too long, cut off this many movements from the beginning.
|
||||
*/
|
||||
public Setting<Integer> pathHistoryCutoffAmount = new Setting<>(50);
|
||||
|
||||
/**
|
||||
* Rescan for the goal once every 5 ticks.
|
||||
* Set to 0 to disable.
|
||||
*/
|
||||
public Setting<Integer> mineGoalUpdateInterval = new Setting<>(5);
|
||||
|
||||
/**
|
||||
* While mining, should it also consider dropped items of the correct type as a pathing destination (as well as ore blocks)?
|
||||
*/
|
||||
public Setting<Boolean> mineScanDroppedItems = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Cancel the current path if the goal has changed, and the path originally ended in the goal but doesn't anymore.
|
||||
* <p>
|
||||
@@ -389,7 +411,7 @@ public class Settings {
|
||||
* <p>
|
||||
* Also on cosmic prisons this should be set to true since you don't actually mine the ore it just gets replaced with stone.
|
||||
*/
|
||||
public Setting<Boolean> cancelOnGoalInvalidation = new Setting<>(false);
|
||||
public Setting<Boolean> cancelOnGoalInvalidation = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* The "axis" command (aka GoalAxis) will go to a axis, or diagonal axis, at this Y level.
|
||||
|
||||
@@ -18,10 +18,9 @@
|
||||
package baritone.api.behavior;
|
||||
|
||||
import baritone.api.event.listener.AbstractGameEventListener;
|
||||
import baritone.api.utils.interfaces.Toggleable;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 9/23/2018
|
||||
*/
|
||||
public interface IBehavior extends AbstractGameEventListener, Toggleable {}
|
||||
public interface IBehavior extends AbstractGameEventListener {}
|
||||
|
||||
@@ -33,7 +33,7 @@ public interface ILookBehavior extends IBehavior {
|
||||
* otherwise, it should be {@code false};
|
||||
*
|
||||
* @param rotation The target rotations
|
||||
* @param force Whether or not to "force" the rotations
|
||||
* @param force Whether or not to "force" the rotations
|
||||
*/
|
||||
void updateTarget(Rotation rotation, boolean force);
|
||||
}
|
||||
|
||||
@@ -39,35 +39,25 @@ public interface IPathingBehavior extends IBehavior {
|
||||
*/
|
||||
Optional<Double> ticksRemainingInSegment();
|
||||
|
||||
/**
|
||||
* Sets the pathing goal.
|
||||
*
|
||||
* @param goal The pathing goal
|
||||
*/
|
||||
void setGoal(Goal goal);
|
||||
|
||||
/**
|
||||
* @return The current pathing goal
|
||||
*/
|
||||
Goal getGoal();
|
||||
|
||||
/**
|
||||
* Begins pathing. Calculation will start in a new thread, and once completed,
|
||||
* movement will commence. Returns whether or not the operation was successful.
|
||||
*
|
||||
* @return Whether or not the operation was successful
|
||||
*/
|
||||
boolean path();
|
||||
|
||||
/**
|
||||
* @return Whether or not a path is currently being executed.
|
||||
*/
|
||||
boolean isPathing();
|
||||
|
||||
/**
|
||||
* Cancels the pathing behavior or the current path calculation.
|
||||
* Cancels the pathing behavior or the current path calculation, and all processes that could be controlling path.
|
||||
* <p>
|
||||
* Basically, "MAKE IT STOP".
|
||||
*
|
||||
* @return Whether or not the pathing behavior was canceled. All processes are guaranteed to be canceled, but the
|
||||
* PathingBehavior might be in the middle of an uncancelable action like a parkour jump
|
||||
*/
|
||||
void cancel();
|
||||
boolean cancelEverything();
|
||||
|
||||
/**
|
||||
* Returns the current path, from the current path executor, if there is one.
|
||||
|
||||
+1
-2
@@ -29,11 +29,10 @@ public interface ICachedRegion extends IBlockTypeAccess {
|
||||
* however, the block coordinates should in on a scale from 0 to 511 (inclusive)
|
||||
* because region sizes are 512x512 blocks.
|
||||
*
|
||||
* @see ICachedWorld#isCached(int, int)
|
||||
*
|
||||
* @param blockX The block X coordinate
|
||||
* @param blockZ The block Z coordinate
|
||||
* @return Whether or not the specified XZ location is cached
|
||||
* @see ICachedWorld#isCached(int, int)
|
||||
*/
|
||||
boolean isCached(int blockX, int blockZ);
|
||||
|
||||
|
||||
+2
-2
@@ -61,8 +61,8 @@ public interface ICachedWorld {
|
||||
* information that is returned by this method may not be up to date, because
|
||||
* older cached chunks can contain data that is much more likely to have changed.
|
||||
*
|
||||
* @param block The special block to search for
|
||||
* @param maximum The maximum number of position results to receive
|
||||
* @param block The special block to search for
|
||||
* @param maximum The maximum number of position results to receive
|
||||
* @param maxRegionDistanceSq The maximum region distance, squared
|
||||
* @return The locations found that match the special block
|
||||
*/
|
||||
|
||||
@@ -50,19 +50,17 @@ public interface IWaypointCollection {
|
||||
/**
|
||||
* Gets all of the waypoints that have the specified tag
|
||||
*
|
||||
* @see IWaypointCollection#getAllWaypoints()
|
||||
*
|
||||
* @param tag The tag
|
||||
* @return All of the waypoints with the specified tag
|
||||
* @see IWaypointCollection#getAllWaypoints()
|
||||
*/
|
||||
Set<IWaypoint> getByTag(IWaypoint.Tag tag);
|
||||
|
||||
/**
|
||||
* Gets all of the waypoints in this collection, regardless of the tag.
|
||||
*
|
||||
* @see IWaypointCollection#getByTag(IWaypoint.Tag)
|
||||
*
|
||||
* @return All of the waypoints in this collection
|
||||
* @see IWaypointCollection#getByTag(IWaypoint.Tag)
|
||||
*/
|
||||
Set<IWaypoint> getAllWaypoints();
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
package baritone.api.event.events;
|
||||
|
||||
import baritone.api.event.events.type.EventState;
|
||||
import baritone.api.event.events.type.ManagedPlayerEvent;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.entity.Entity;
|
||||
@@ -35,21 +34,30 @@ public final class RotationMoveEvent extends ManagedPlayerEvent {
|
||||
private final Type type;
|
||||
|
||||
/**
|
||||
* The state of the event
|
||||
* The yaw rotation
|
||||
*/
|
||||
private final EventState state;
|
||||
private float yaw;
|
||||
|
||||
public RotationMoveEvent(EntityPlayerSP player, EventState state, Type type) {
|
||||
public RotationMoveEvent(EntityPlayerSP player, Type type, float yaw) {
|
||||
super(player);
|
||||
this.state = state;
|
||||
this.type = type;
|
||||
this.yaw = yaw;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The state of the event
|
||||
* Set the yaw movement rotation
|
||||
*
|
||||
* @param yaw Yaw rotation
|
||||
*/
|
||||
public final EventState getState() {
|
||||
return this.state;
|
||||
public final void setYaw(float yaw) {
|
||||
this.yaw = yaw;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The yaw rotation
|
||||
*/
|
||||
public final float getYaw() {
|
||||
return this.yaw;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,14 +24,12 @@ package baritone.api.event.events.type;
|
||||
public enum EventState {
|
||||
|
||||
/**
|
||||
* Indicates that whatever movement the event is being
|
||||
* dispatched as a result of is about to occur.
|
||||
* Before the dispatching of what the event is targetting
|
||||
*/
|
||||
PRE,
|
||||
|
||||
/**
|
||||
* Indicates that whatever movement the event is being
|
||||
* dispatched as a result of has already occurred.
|
||||
* After the dispatching of what the event is targetting
|
||||
*/
|
||||
POST
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@ import baritone.api.Settings;
|
||||
import baritone.api.pathing.goals.Goal;
|
||||
import baritone.api.pathing.movement.IMovement;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -51,7 +53,9 @@ public interface IPath {
|
||||
* This path is actually going to be executed in the world. Do whatever additional processing is required.
|
||||
* (as opposed to Path objects that are just constructed every frame for rendering)
|
||||
*/
|
||||
default void postProcess() {}
|
||||
default IPath postProcess() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of positions in this path. Equivalent to {@code positions().size()}.
|
||||
@@ -117,20 +121,48 @@ public interface IPath {
|
||||
*
|
||||
* @return The result of this cut-off operation
|
||||
*/
|
||||
default IPath cutoffAtLoadedChunks() {
|
||||
return this;
|
||||
default IPath cutoffAtLoadedChunks(World world) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cuts off this path using the min length and cutoff factor settings, and returns the resulting path.
|
||||
* Default implementation just returns this path, without the intended functionality.
|
||||
*
|
||||
* @return The result of this cut-off operation
|
||||
* @see Settings#pathCutoffMinimumLength
|
||||
* @see Settings#pathCutoffFactor
|
||||
*
|
||||
* @return The result of this cut-off operation
|
||||
*/
|
||||
default IPath staticCutoff(Goal destination) {
|
||||
return this;
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Performs a series of checks to ensure that the assembly of the path went as expected.
|
||||
*/
|
||||
default void sanityCheck() {
|
||||
List<BetterBlockPos> path = positions();
|
||||
List<IMovement> movements = movements();
|
||||
if (!getSrc().equals(path.get(0))) {
|
||||
throw new IllegalStateException("Start node does not equal first path element");
|
||||
}
|
||||
if (!getDest().equals(path.get(path.size() - 1))) {
|
||||
throw new IllegalStateException("End node does not equal last path element");
|
||||
}
|
||||
if (path.size() != movements.size() + 1) {
|
||||
throw new IllegalStateException("Size of path array is unexpected");
|
||||
}
|
||||
for (int i = 0; i < path.size() - 1; i++) {
|
||||
BlockPos src = path.get(i);
|
||||
BlockPos dest = path.get(i + 1);
|
||||
IMovement movement = movements.get(i);
|
||||
if (!src.equals(movement.getSrc())) {
|
||||
throw new IllegalStateException("Path source is not equal to the movement source");
|
||||
}
|
||||
if (!dest.equals(movement.getDest())) {
|
||||
throw new IllegalStateException("Path destination is not equal to the movement destination");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
package baritone.api.pathing.calc;
|
||||
|
||||
import baritone.api.pathing.goals.Goal;
|
||||
import baritone.api.utils.PathCalculationResult;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -35,7 +36,7 @@ public interface IPathFinder {
|
||||
*
|
||||
* @return The final path
|
||||
*/
|
||||
Optional<IPath> calculate(long timeout);
|
||||
PathCalculationResult calculate(long timeout);
|
||||
|
||||
/**
|
||||
* Intended to be called concurrently with calculatePath from a different thread to tell if it's finished yet
|
||||
|
||||
@@ -20,6 +20,7 @@ package baritone.api.pathing.goals;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Useful for automated combat (retreating specifically)
|
||||
@@ -32,16 +33,26 @@ public class GoalRunAway implements Goal {
|
||||
|
||||
private final double distanceSq;
|
||||
|
||||
private final Optional<Integer> maintainY;
|
||||
|
||||
public GoalRunAway(double distance, BlockPos... from) {
|
||||
this(distance, Optional.empty(), from);
|
||||
}
|
||||
|
||||
public GoalRunAway(double distance, Optional<Integer> maintainY, BlockPos... from) {
|
||||
if (from.length == 0) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
this.from = from;
|
||||
this.distanceSq = distance * distance;
|
||||
this.maintainY = maintainY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInGoal(int x, int y, int z) {
|
||||
if (maintainY.isPresent() && maintainY.get() != y) {
|
||||
return false;
|
||||
}
|
||||
for (BlockPos p : from) {
|
||||
int diffX = x - p.getX();
|
||||
int diffZ = z - p.getZ();
|
||||
@@ -62,11 +73,19 @@ public class GoalRunAway implements Goal {
|
||||
min = h;
|
||||
}
|
||||
}
|
||||
return -min;
|
||||
min = -min;
|
||||
if (maintainY.isPresent()) {
|
||||
min = min * 0.5 + GoalYLevel.calculate(maintainY.get(), y);
|
||||
}
|
||||
return min;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GoalRunAwayFrom" + Arrays.asList(from);
|
||||
if (maintainY.isPresent()) {
|
||||
return "GoalRunAwayFromMaintainY y=" + maintainY.get() + ", " + Arrays.asList(from);
|
||||
} else {
|
||||
return "GoalRunAwayFrom" + Arrays.asList(from);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.api.process;
|
||||
|
||||
import baritone.api.IBaritone;
|
||||
import baritone.api.behavior.IPathingBehavior;
|
||||
import baritone.api.event.events.PathEvent;
|
||||
|
||||
/**
|
||||
* A process that can control the PathingBehavior.
|
||||
* <p>
|
||||
* Differences between a baritone process and a behavior:
|
||||
* Only one baritone process can be active at a time
|
||||
* PathingBehavior can only be controlled by a process
|
||||
* <p>
|
||||
* That's it actually
|
||||
*
|
||||
* @author leijurv
|
||||
*/
|
||||
public interface IBaritoneProcess {
|
||||
|
||||
/**
|
||||
* Would this process like to be in control?
|
||||
*
|
||||
* @return Whether or not this process would like to be in contorl.
|
||||
*/
|
||||
boolean isActive();
|
||||
|
||||
/**
|
||||
* Called when this process is in control of pathing; Returns what Baritone should do.
|
||||
*
|
||||
* @param calcFailed {@code true} if this specific process was in control last tick,
|
||||
* and there was a {@link PathEvent#CALC_FAILED} event last tick
|
||||
* @param isSafeToCancel {@code true} if a {@link PathingCommandType#REQUEST_PAUSE} would happen this tick, and
|
||||
* {@link IPathingBehavior} wouldn't actually tick. {@code false} if the PathExecutor reported
|
||||
* pausing would be unsafe at the end of the last tick. Effectively "could request cancel or
|
||||
* pause and have it happen right away"
|
||||
* @return What the {@link IPathingBehavior} should do
|
||||
*/
|
||||
PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel);
|
||||
|
||||
/**
|
||||
* Returns whether or not this process should be treated as "temporary".
|
||||
* <p>
|
||||
* If a process is temporary, it doesn't call {@link #onLostControl} on the processes that aren't execute because of it.
|
||||
* <p>
|
||||
* For example, {@code CombatPauserProcess} and {@code PauseForAutoEatProcess} should return {@code true} always,
|
||||
* and should return {@link #isActive} {@code true} only if there's something in range this tick, or if the player would like
|
||||
* to start eating this tick. {@code PauseForAutoEatProcess} should only actually right click once onTick is called with
|
||||
* {@code isSafeToCancel} true though.
|
||||
*
|
||||
* @return Whethor or not if this control is temporary
|
||||
*/
|
||||
boolean isTemporary();
|
||||
|
||||
/**
|
||||
* Called if {@link #isActive} returned {@code true}, but another non-temporary
|
||||
* process has control. Effectively the same as cancel. You want control but you
|
||||
* don't get it.
|
||||
*/
|
||||
void onLostControl();
|
||||
|
||||
/**
|
||||
* Used to determine which Process gains control if multiple are reporting {@link #isActive()}. The one
|
||||
* that returns the highest value will be given control.
|
||||
*
|
||||
* @return A double representing the priority
|
||||
*/
|
||||
double priority();
|
||||
|
||||
/**
|
||||
* Returns which bot this process is associated with. (5000000iq forward thinking)
|
||||
*
|
||||
* @return The Bot associated with this process
|
||||
*/
|
||||
IBaritone associatedWith();
|
||||
|
||||
/**
|
||||
* Returns a user-friendly name for this process. Suitable for a HUD.
|
||||
*
|
||||
* @return A display name that's suitable for a HUD
|
||||
*/
|
||||
String displayName();
|
||||
}
|
||||
+23
-27
@@ -15,40 +15,36 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.api.utils.interfaces;
|
||||
package baritone.api.process;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/20/2018
|
||||
*/
|
||||
public interface Toggleable {
|
||||
import baritone.api.pathing.goals.Goal;
|
||||
|
||||
public interface ICustomGoalProcess extends IBaritoneProcess {
|
||||
|
||||
/**
|
||||
* Toggles the enabled state of this {@link Toggleable}.
|
||||
* Sets the pathing goal
|
||||
*
|
||||
* @return The new state.
|
||||
* @param goal The new goal
|
||||
*/
|
||||
boolean toggle();
|
||||
void setGoal(Goal goal);
|
||||
|
||||
/**
|
||||
* Sets the enabled state of this {@link Toggleable}.
|
||||
* Starts path calculation and execution.
|
||||
*/
|
||||
void path();
|
||||
|
||||
/**
|
||||
* @return The current goal
|
||||
*/
|
||||
Goal getGoal();
|
||||
|
||||
/**
|
||||
* Sets the goal and begins the path execution.
|
||||
*
|
||||
* @return The new state.
|
||||
* @param goal The new goal
|
||||
*/
|
||||
boolean setEnabled(boolean enabled);
|
||||
|
||||
/**
|
||||
* @return Whether or not this {@link Toggleable} object is enabled
|
||||
*/
|
||||
boolean isEnabled();
|
||||
|
||||
/**
|
||||
* Called when the state changes from disabled to enabled
|
||||
*/
|
||||
default void onEnable() {}
|
||||
|
||||
/**
|
||||
* Called when the state changes from enabled to disabled
|
||||
*/
|
||||
default void onDisable() {}
|
||||
default void setGoalAndPath(Goal goal) {
|
||||
this.setGoal(goal);
|
||||
this.path();
|
||||
}
|
||||
}
|
||||
+15
-8
@@ -15,30 +15,37 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.api.behavior;
|
||||
package baritone.api.process;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 9/23/2018
|
||||
*/
|
||||
public interface IFollowBehavior extends IBehavior {
|
||||
public interface IFollowProcess extends IBaritoneProcess {
|
||||
|
||||
/**
|
||||
* Set the follow target to the specified entity;
|
||||
* Set the follow target to any entities matching this predicate
|
||||
*
|
||||
* @param entity The entity to follow
|
||||
* @param filter the predicate
|
||||
*/
|
||||
void follow(Entity entity);
|
||||
void follow(Predicate<Entity> filter);
|
||||
|
||||
/**
|
||||
* @return The entity that is currently being followed
|
||||
* @return The entities that are currently being followed. null if not currently following, empty if nothing matches the predicate
|
||||
*/
|
||||
Entity following();
|
||||
List<Entity> following();
|
||||
|
||||
Predicate<Entity> currentFilter();
|
||||
|
||||
/**
|
||||
* Cancels the follow behavior, this will clear the current follow target.
|
||||
*/
|
||||
void cancel();
|
||||
default void cancel() {
|
||||
onLostControl();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.api.process;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
|
||||
/**
|
||||
* but it rescans the world every once in a while so it doesn't get fooled by its cache
|
||||
*/
|
||||
public interface IGetToBlockProcess extends IBaritoneProcess {
|
||||
|
||||
void getToBlock(Block block);
|
||||
}
|
||||
+11
-9
@@ -15,7 +15,7 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.api.behavior;
|
||||
package baritone.api.process;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
|
||||
@@ -23,7 +23,7 @@ import net.minecraft.block.Block;
|
||||
* @author Brady
|
||||
* @since 9/23/2018
|
||||
*/
|
||||
public interface IMineBehavior extends IBehavior {
|
||||
public interface IMineProcess extends IBaritoneProcess {
|
||||
|
||||
/**
|
||||
* Begin to search for and mine the specified blocks until
|
||||
@@ -31,9 +31,9 @@ public interface IMineBehavior extends IBehavior {
|
||||
* are mined. This is based on the first target block to mine.
|
||||
*
|
||||
* @param quantity The number of items to get from blocks mined
|
||||
* @param blocks The blocks to mine
|
||||
* @param blocks The blocks to mine
|
||||
*/
|
||||
void mine(int quantity, String... blocks);
|
||||
void mineByName(int quantity, String... blocks);
|
||||
|
||||
/**
|
||||
* Begin to search for and mine the specified blocks until
|
||||
@@ -41,7 +41,7 @@ public interface IMineBehavior extends IBehavior {
|
||||
* are mined. This is based on the first target block to mine.
|
||||
*
|
||||
* @param quantity The number of items to get from blocks mined
|
||||
* @param blocks The blocks to mine
|
||||
* @param blocks The blocks to mine
|
||||
*/
|
||||
void mine(int quantity, Block... blocks);
|
||||
|
||||
@@ -50,8 +50,8 @@ public interface IMineBehavior extends IBehavior {
|
||||
*
|
||||
* @param blocks The blocks to mine
|
||||
*/
|
||||
default void mine(String... blocks) {
|
||||
this.mine(0, blocks);
|
||||
default void mineByName(String... blocks) {
|
||||
mineByName(0, blocks);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,11 +60,13 @@ public interface IMineBehavior extends IBehavior {
|
||||
* @param blocks The blocks to mine
|
||||
*/
|
||||
default void mine(Block... blocks) {
|
||||
this.mine(0, blocks);
|
||||
mine(0, blocks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels the current mining task
|
||||
*/
|
||||
void cancel();
|
||||
default void cancel() {
|
||||
onLostControl();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.api.process;
|
||||
|
||||
import baritone.api.pathing.goals.Goal;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author leijurv
|
||||
*/
|
||||
public class PathingCommand {
|
||||
|
||||
/**
|
||||
* The target goal, may be {@code null}.
|
||||
*/
|
||||
public final Goal goal;
|
||||
|
||||
/**
|
||||
* The command type.
|
||||
*
|
||||
* @see PathingCommandType
|
||||
*/
|
||||
public final PathingCommandType commandType;
|
||||
|
||||
/**
|
||||
* Create a new {@link PathingCommand}.
|
||||
*
|
||||
* @param goal The target goal, may be {@code null}.
|
||||
* @param commandType The command type, cannot be {@code null}.
|
||||
* @throws NullPointerException if {@code commandType} is {@code null}.
|
||||
* @see Goal
|
||||
* @see PathingCommandType
|
||||
*/
|
||||
public PathingCommand(Goal goal, PathingCommandType commandType) {
|
||||
Objects.requireNonNull(commandType);
|
||||
|
||||
this.goal = goal;
|
||||
this.commandType = commandType;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.api.process;
|
||||
|
||||
import baritone.api.Settings;
|
||||
|
||||
public enum PathingCommandType {
|
||||
|
||||
/**
|
||||
* Set the goal and path.
|
||||
* <p>
|
||||
* If you use this alongside a {@code null} goal, it will continue along its current path and current goal.
|
||||
*/
|
||||
SET_GOAL_AND_PATH,
|
||||
|
||||
/**
|
||||
* Has no effect on the current goal or path, just requests a pause
|
||||
*/
|
||||
REQUEST_PAUSE,
|
||||
|
||||
/**
|
||||
* Set the goal (regardless of {@code null}), and request a cancel of the current path (when safe)
|
||||
*/
|
||||
CANCEL_AND_SET_GOAL,
|
||||
|
||||
/**
|
||||
* Set the goal and path.
|
||||
* <p>
|
||||
* If {@link Settings#cancelOnGoalInvalidation} is {@code true}, revalidate the
|
||||
* current goal, and cancel if it's no longer valid, or if the new goal is {@code null}.
|
||||
*/
|
||||
REVALIDATE_GOAL_AND_PATH,
|
||||
|
||||
/**
|
||||
* Set the goal and path.
|
||||
* <p>
|
||||
* Cancel the current path if the goals are not equal
|
||||
*/
|
||||
FORCE_REVALIDATE_GOAL_AND_PATH
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.api.utils;
|
||||
|
||||
import baritone.api.pathing.calc.IPath;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class PathCalculationResult {
|
||||
|
||||
public final Optional<IPath> path;
|
||||
public final Type type;
|
||||
|
||||
public PathCalculationResult(Type type, Optional<IPath> path) {
|
||||
this.path = path;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public enum Type {
|
||||
SUCCESS_TO_GOAL,
|
||||
SUCCESS_SEGMENT,
|
||||
FAILURE,
|
||||
CANCELLATION,
|
||||
EXCEPTION,
|
||||
}
|
||||
}
|
||||
@@ -30,43 +30,11 @@ import java.util.Optional;
|
||||
* @since 8/25/2018
|
||||
*/
|
||||
public final class RayTraceUtils {
|
||||
/**
|
||||
* The {@link Minecraft} instance
|
||||
*/
|
||||
|
||||
private static final Minecraft mc = Minecraft.getMinecraft();
|
||||
|
||||
private RayTraceUtils() {}
|
||||
|
||||
/**
|
||||
* Simulates a "vanilla" raytrace. A RayTraceResult returned by this method
|
||||
* will be that of the next render pass given that the local player's yaw and
|
||||
* pitch match the specified yaw and pitch values. This is particularly useful
|
||||
* when you would like to simulate a "legit" raytrace with certainty that the only
|
||||
* thing to achieve the desired outcome (whether it is hitting and entity or placing
|
||||
* a block) can be done just by modifying user input.
|
||||
*
|
||||
* @param yaw The yaw to raytrace with
|
||||
* @param pitch The pitch to raytrace with
|
||||
* @return The calculated raytrace result
|
||||
*/
|
||||
public static RayTraceResult simulateRayTrace(float yaw, float pitch) {
|
||||
RayTraceResult oldTrace = mc.objectMouseOver;
|
||||
float oldYaw = mc.player.rotationYaw;
|
||||
float oldPitch = mc.player.rotationPitch;
|
||||
|
||||
mc.player.rotationYaw = yaw;
|
||||
mc.player.rotationPitch = pitch;
|
||||
|
||||
mc.entityRenderer.getMouseOver(1.0F);
|
||||
RayTraceResult result = mc.objectMouseOver;
|
||||
mc.objectMouseOver = oldTrace;
|
||||
|
||||
mc.player.rotationYaw = oldYaw;
|
||||
mc.player.rotationPitch = oldPitch;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a block raytrace with the specified rotations. This should only be used when
|
||||
* any entity collisions can be ignored, because this method will not recognize if an
|
||||
@@ -75,9 +43,8 @@ public final class RayTraceUtils {
|
||||
* @param rotation The rotation to raytrace towards
|
||||
* @return The calculated raytrace result
|
||||
*/
|
||||
public static RayTraceResult rayTraceTowards(Rotation rotation) {
|
||||
double blockReachDistance = mc.playerController.getBlockReachDistance();
|
||||
Vec3d start = mc.player.getPositionEyes(1.0F);
|
||||
public static RayTraceResult rayTraceTowards(Entity entity, Rotation rotation, double blockReachDistance) {
|
||||
Vec3d start = entity.getPositionEyes(1.0F);
|
||||
Vec3d direction = RotationUtils.calcVec3dFromRotation(rotation);
|
||||
Vec3d end = start.add(
|
||||
direction.x * blockReachDistance,
|
||||
|
||||
@@ -86,7 +86,7 @@ public class Rotation {
|
||||
public Rotation clamp() {
|
||||
return new Rotation(
|
||||
this.yaw,
|
||||
RotationUtils.clampPitch(this.pitch)
|
||||
clampPitch(this.pitch)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ public class Rotation {
|
||||
*/
|
||||
public Rotation normalize() {
|
||||
return new Rotation(
|
||||
RotationUtils.normalizeYaw(this.yaw),
|
||||
normalizeYaw(this.yaw),
|
||||
this.pitch
|
||||
);
|
||||
}
|
||||
@@ -105,8 +105,35 @@ public class Rotation {
|
||||
*/
|
||||
public Rotation normalizeAndClamp() {
|
||||
return new Rotation(
|
||||
RotationUtils.normalizeYaw(this.yaw),
|
||||
RotationUtils.clampPitch(this.pitch)
|
||||
normalizeYaw(this.yaw),
|
||||
clampPitch(this.pitch)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clamps the specified pitch value between -90 and 90.
|
||||
*
|
||||
* @param pitch The input pitch
|
||||
* @return The clamped pitch
|
||||
*/
|
||||
public static float clampPitch(float pitch) {
|
||||
return Math.max(-90, Math.min(90, pitch));
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes the specified yaw value between -180 and 180.
|
||||
*
|
||||
* @param yaw The input yaw
|
||||
* @return The normalized yaw
|
||||
*/
|
||||
public static float normalizeYaw(float yaw) {
|
||||
float newYaw = yaw % 360F;
|
||||
if (newYaw < -180F) {
|
||||
newYaw += 360F;
|
||||
}
|
||||
if (newYaw >= 180F) {
|
||||
newYaw -= 360F;
|
||||
}
|
||||
return newYaw;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ package baritone.api.utils;
|
||||
|
||||
import net.minecraft.block.BlockFire;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.util.math.*;
|
||||
|
||||
@@ -31,11 +30,6 @@ import java.util.Optional;
|
||||
*/
|
||||
public final class RotationUtils {
|
||||
|
||||
/**
|
||||
* The {@link Minecraft} instance
|
||||
*/
|
||||
private static final Minecraft mc = Minecraft.getMinecraft();
|
||||
|
||||
/**
|
||||
* Constant that a degree value is multiplied by to get the equivalent radian value
|
||||
*/
|
||||
@@ -60,33 +54,6 @@ public final class RotationUtils {
|
||||
|
||||
private RotationUtils() {}
|
||||
|
||||
/**
|
||||
* Clamps the specified pitch value between -90 and 90.
|
||||
*
|
||||
* @param pitch The input pitch
|
||||
* @return The clamped pitch
|
||||
*/
|
||||
public static float clampPitch(float pitch) {
|
||||
return Math.max(-90, Math.min(90, pitch));
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes the specified yaw value between -180 and 180.
|
||||
*
|
||||
* @param yaw The input yaw
|
||||
* @return The normalized yaw
|
||||
*/
|
||||
public static float normalizeYaw(float yaw) {
|
||||
float newYaw = yaw % 360F;
|
||||
if (newYaw < -180F) {
|
||||
newYaw += 360F;
|
||||
}
|
||||
if (newYaw >= 180F) {
|
||||
newYaw -= 360F;
|
||||
}
|
||||
return newYaw;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the rotation from BlockPos<sub>dest</sub> to BlockPos<sub>orig</sub>
|
||||
*
|
||||
@@ -168,7 +135,7 @@ public final class RotationUtils {
|
||||
* @param pos The target block position
|
||||
* @return The optional rotation
|
||||
*/
|
||||
public static Optional<Rotation> reachable(Entity entity, BlockPos pos) {
|
||||
public static Optional<Rotation> reachable(Entity entity, BlockPos pos, double blockReachDistance) {
|
||||
if (pos.equals(RayTraceUtils.getSelectedBlock().orElse(null))) {
|
||||
/*
|
||||
* why add 0.0001?
|
||||
@@ -182,19 +149,19 @@ public final class RotationUtils {
|
||||
*/
|
||||
return Optional.of(new Rotation(entity.rotationYaw, entity.rotationPitch + 0.0001F));
|
||||
}
|
||||
Optional<Rotation> possibleRotation = reachableCenter(entity, pos);
|
||||
Optional<Rotation> possibleRotation = reachableCenter(entity, pos, blockReachDistance);
|
||||
//System.out.println("center: " + possibleRotation);
|
||||
if (possibleRotation.isPresent()) {
|
||||
return possibleRotation;
|
||||
}
|
||||
|
||||
IBlockState state = mc.world.getBlockState(pos);
|
||||
IBlockState state = entity.world.getBlockState(pos);
|
||||
AxisAlignedBB aabb = state.getBoundingBox(entity.world, pos);
|
||||
for (Vec3d sideOffset : BLOCK_SIDE_MULTIPLIERS) {
|
||||
double xDiff = aabb.minX * sideOffset.x + aabb.maxX * (1 - sideOffset.x);
|
||||
double yDiff = aabb.minY * sideOffset.y + aabb.maxY * (1 - sideOffset.y);
|
||||
double zDiff = aabb.minZ * sideOffset.z + aabb.maxZ * (1 - sideOffset.z);
|
||||
possibleRotation = reachableOffset(entity, pos, new Vec3d(pos).add(xDiff, yDiff, zDiff));
|
||||
possibleRotation = reachableOffset(entity, pos, new Vec3d(pos).add(xDiff, yDiff, zDiff), blockReachDistance);
|
||||
if (possibleRotation.isPresent()) {
|
||||
return possibleRotation;
|
||||
}
|
||||
@@ -212,9 +179,9 @@ public final class RotationUtils {
|
||||
* @param offsetPos The position of the block with the offset applied.
|
||||
* @return The optional rotation
|
||||
*/
|
||||
public static Optional<Rotation> reachableOffset(Entity entity, BlockPos pos, Vec3d offsetPos) {
|
||||
public static Optional<Rotation> reachableOffset(Entity entity, BlockPos pos, Vec3d offsetPos, double blockReachDistance) {
|
||||
Rotation rotation = calcRotationFromVec3d(entity.getPositionEyes(1.0F), offsetPos);
|
||||
RayTraceResult result = RayTraceUtils.rayTraceTowards(rotation);
|
||||
RayTraceResult result = RayTraceUtils.rayTraceTowards(entity, rotation, blockReachDistance);
|
||||
//System.out.println(result);
|
||||
if (result != null && result.typeOfHit == RayTraceResult.Type.BLOCK) {
|
||||
if (result.getBlockPos().equals(pos)) {
|
||||
@@ -235,7 +202,7 @@ public final class RotationUtils {
|
||||
* @param pos The target block position
|
||||
* @return The optional rotation
|
||||
*/
|
||||
public static Optional<Rotation> reachableCenter(Entity entity, BlockPos pos) {
|
||||
return reachableOffset(entity, pos, VecUtils.calculateBlockCenter(pos));
|
||||
public static Optional<Rotation> reachableCenter(Entity entity, BlockPos pos, double blockReachDistance) {
|
||||
return reachableOffset(entity, pos, VecUtils.calculateBlockCenter(pos), blockReachDistance);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,9 @@ import java.io.File;
|
||||
@Mixin(AnvilChunkLoader.class)
|
||||
public class MixinAnvilChunkLoader implements IAnvilChunkLoader {
|
||||
|
||||
@Shadow @Final private File chunkSaveLocation;
|
||||
@Shadow
|
||||
@Final
|
||||
private File chunkSaveLocation;
|
||||
|
||||
@Override
|
||||
public File getChunkSaveLocation() {
|
||||
|
||||
@@ -35,6 +35,12 @@ public class MixinBlockPos extends Vec3i {
|
||||
super(xIn, yIn, zIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* The purpose of this was to ensure a friendly name for when we print raw
|
||||
* block positions to chat in the context of an obfuscated environment.
|
||||
*
|
||||
* @return a string representation of the object.
|
||||
*/
|
||||
@Override
|
||||
@Nonnull
|
||||
public String toString() {
|
||||
|
||||
@@ -31,7 +31,9 @@ import org.spongepowered.asm.mixin.Shadow;
|
||||
@Mixin(ChunkProviderServer.class)
|
||||
public class MixinChunkProviderServer implements IChunkProviderServer {
|
||||
|
||||
@Shadow @Final private IChunkLoader chunkLoader;
|
||||
@Shadow
|
||||
@Final
|
||||
private IChunkLoader chunkLoader;
|
||||
|
||||
@Override
|
||||
public IChunkLoader getChunkLoader() {
|
||||
|
||||
@@ -19,14 +19,17 @@ package baritone.launch.mixins;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.event.events.RotationMoveEvent;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.entity.Entity;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import static org.spongepowered.asm.lib.Opcodes.GETFIELD;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/21/2018
|
||||
@@ -34,23 +37,38 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
@Mixin(Entity.class)
|
||||
public class MixinEntity {
|
||||
|
||||
@Shadow
|
||||
public float rotationYaw;
|
||||
|
||||
/**
|
||||
* Event called to override the movement direction when walking
|
||||
*/
|
||||
private RotationMoveEvent motionUpdateRotationEvent;
|
||||
|
||||
@Inject(
|
||||
method = "moveRelative",
|
||||
at = @At("HEAD")
|
||||
)
|
||||
private void preMoveRelative(float strafe, float up, float forward, float friction, CallbackInfo ci) {
|
||||
Entity _this = (Entity) (Object) this;
|
||||
if (EntityPlayerSP.class.isInstance(_this))
|
||||
Baritone.INSTANCE.getGameEventHandler().onPlayerRotationMove(new RotationMoveEvent((EntityPlayerSP) _this, EventState.PRE, RotationMoveEvent.Type.MOTION_UPDATE));
|
||||
// noinspection ConstantConditions
|
||||
if (EntityPlayerSP.class.isInstance(this)) {
|
||||
this.motionUpdateRotationEvent = new RotationMoveEvent((EntityPlayerSP) (Object) this, RotationMoveEvent.Type.MOTION_UPDATE, this.rotationYaw);
|
||||
Baritone.INSTANCE.getGameEventHandler().onPlayerRotationMove(this.motionUpdateRotationEvent);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(
|
||||
@Redirect(
|
||||
method = "moveRelative",
|
||||
at = @At("RETURN")
|
||||
at = @At(
|
||||
value = "FIELD",
|
||||
opcode = GETFIELD,
|
||||
target = "net/minecraft/entity/Entity.rotationYaw:F"
|
||||
)
|
||||
)
|
||||
private void postMoveRelative(float strafe, float up, float forward, float friction, CallbackInfo ci) {
|
||||
Entity _this = (Entity) (Object) this;
|
||||
if (EntityPlayerSP.class.isInstance(_this))
|
||||
Baritone.INSTANCE.getGameEventHandler().onPlayerRotationMove(new RotationMoveEvent((EntityPlayerSP) _this, EventState.POST, RotationMoveEvent.Type.MOTION_UPDATE));
|
||||
private float overrideYaw(Entity self) {
|
||||
if (self instanceof EntityPlayerSP) {
|
||||
return this.motionUpdateRotationEvent.getYaw();
|
||||
}
|
||||
return self.rotationYaw;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,41 +19,59 @@ package baritone.launch.mixins;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.event.events.RotationMoveEvent;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.world.World;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import static org.spongepowered.asm.lib.Opcodes.GETFIELD;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 9/10/2018
|
||||
*/
|
||||
@Mixin(EntityLivingBase.class)
|
||||
public class MixinEntityLivingBase {
|
||||
public abstract class MixinEntityLivingBase extends Entity {
|
||||
|
||||
/**
|
||||
* Event called to override the movement direction when jumping
|
||||
*/
|
||||
private RotationMoveEvent jumpRotationEvent;
|
||||
|
||||
public MixinEntityLivingBase(World worldIn, RotationMoveEvent jumpRotationEvent) {
|
||||
super(worldIn);
|
||||
this.jumpRotationEvent = jumpRotationEvent;
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "jump",
|
||||
at = @At("HEAD")
|
||||
)
|
||||
private void preJump(CallbackInfo ci) {
|
||||
EntityLivingBase _this = (EntityLivingBase) (Object) this;
|
||||
// This uses Class.isInstance instead of instanceof since proguard optimizes out the instanceof (since MixinEntityLivingBase could never be instanceof EntityLivingBase in normal java)
|
||||
// but proguard isn't smart enough to optimize out this Class.isInstance =)
|
||||
if (EntityPlayerSP.class.isInstance(_this))
|
||||
Baritone.INSTANCE.getGameEventHandler().onPlayerRotationMove(new RotationMoveEvent((EntityPlayerSP) _this, EventState.PRE, RotationMoveEvent.Type.JUMP));
|
||||
private void preMoveRelative(CallbackInfo ci) {
|
||||
// noinspection ConstantConditions
|
||||
if (EntityPlayerSP.class.isInstance(this)) {
|
||||
this.jumpRotationEvent = new RotationMoveEvent((EntityPlayerSP) (Object) this, RotationMoveEvent.Type.JUMP, this.rotationYaw);
|
||||
Baritone.INSTANCE.getGameEventHandler().onPlayerRotationMove(this.jumpRotationEvent);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(
|
||||
@Redirect(
|
||||
method = "jump",
|
||||
at = @At("RETURN")
|
||||
at = @At(
|
||||
value = "FIELD",
|
||||
opcode = GETFIELD,
|
||||
target = "net/minecraft/entity/EntityLivingBase.rotationYaw:F"
|
||||
)
|
||||
)
|
||||
private void postJump(CallbackInfo ci) {
|
||||
EntityLivingBase _this = (EntityLivingBase) (Object) this;
|
||||
// See above
|
||||
if (EntityPlayerSP.class.isInstance(_this))
|
||||
Baritone.INSTANCE.getGameEventHandler().onPlayerRotationMove(new RotationMoveEvent((EntityPlayerSP) _this, EventState.POST, RotationMoveEvent.Type.JUMP));
|
||||
private float overrideYaw(EntityLivingBase self) {
|
||||
if (self instanceof EntityPlayerSP) {
|
||||
return this.jumpRotationEvent.getYaw();
|
||||
}
|
||||
return self.rotationYaw;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,6 +85,6 @@ public class MixinEntityPlayerSP {
|
||||
)
|
||||
private boolean isAllowFlying(PlayerCapabilities capabilities) {
|
||||
PathingBehavior pathingBehavior = Baritone.INSTANCE.getPathingBehavior();
|
||||
return (!pathingBehavior.isEnabled() || !pathingBehavior.isPathing()) && capabilities.allowFlying;
|
||||
return !pathingBehavior.isPathing() && capabilities.allowFlying;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ public class MixinEntityRenderer {
|
||||
at = @At(
|
||||
value = "INVOKE_STRING",
|
||||
target = "Lnet/minecraft/profiler/Profiler;endStartSection(Ljava/lang/String;)V",
|
||||
args = { "ldc=hand" }
|
||||
args = {"ldc=hand"}
|
||||
)
|
||||
)
|
||||
private void renderWorldPass(int pass, float partialTicks, long finishTimeNano, CallbackInfo ci) {
|
||||
|
||||
@@ -83,10 +83,9 @@ public class MixinMinecraft {
|
||||
)
|
||||
)
|
||||
private void runTick(CallbackInfo ci) {
|
||||
Minecraft mc = (Minecraft) (Object) this;
|
||||
Baritone.INSTANCE.getGameEventHandler().onTick(new TickEvent(
|
||||
EventState.PRE,
|
||||
(mc.player != null && mc.world != null)
|
||||
(player != null && world != null)
|
||||
? TickEvent.Type.IN
|
||||
: TickEvent.Type.OUT
|
||||
));
|
||||
@@ -142,7 +141,7 @@ public class MixinMinecraft {
|
||||
)
|
||||
)
|
||||
private boolean isAllowUserInput(GuiScreen screen) {
|
||||
return (Baritone.INSTANCE.getPathingBehavior().getCurrent() != null && Baritone.INSTANCE.getPathingBehavior().isEnabled() && player != null) || screen.allowUserInput;
|
||||
return (Baritone.INSTANCE.getPathingBehavior().getCurrent() != null && player != null) || screen.allowUserInput;
|
||||
}
|
||||
|
||||
@Inject(
|
||||
|
||||
@@ -77,7 +77,8 @@ public class MixinNetworkManager {
|
||||
)
|
||||
private void preProcessPacket(ChannelHandlerContext context, Packet<?> packet, CallbackInfo ci) {
|
||||
if (this.direction == EnumPacketDirection.CLIENTBOUND) {
|
||||
Baritone.INSTANCE.getGameEventHandler().onReceivePacket(new PacketEvent((NetworkManager) (Object) this, EventState.PRE, packet));}
|
||||
Baritone.INSTANCE.getGameEventHandler().onReceivePacket(new PacketEvent((NetworkManager) (Object) this, EventState.PRE, packet));
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(
|
||||
|
||||
@@ -18,16 +18,24 @@
|
||||
package baritone;
|
||||
|
||||
import baritone.api.BaritoneAPI;
|
||||
import baritone.api.IBaritoneProvider;
|
||||
import baritone.api.IBaritone;
|
||||
import baritone.api.Settings;
|
||||
import baritone.api.event.listener.IGameEventListener;
|
||||
import baritone.behavior.*;
|
||||
import baritone.behavior.Behavior;
|
||||
import baritone.behavior.LookBehavior;
|
||||
import baritone.behavior.MemoryBehavior;
|
||||
import baritone.behavior.PathingBehavior;
|
||||
import baritone.cache.WorldProvider;
|
||||
import baritone.cache.WorldScanner;
|
||||
import baritone.event.GameEventHandler;
|
||||
import baritone.process.CustomGoalProcess;
|
||||
import baritone.process.FollowProcess;
|
||||
import baritone.process.GetToBlockProcess;
|
||||
import baritone.process.MineProcess;
|
||||
import baritone.utils.BaritoneAutoTest;
|
||||
import baritone.utils.ExampleBaritoneControl;
|
||||
import baritone.utils.InputOverrideHandler;
|
||||
import baritone.utils.PathingControlManager;
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
||||
import java.io.File;
|
||||
@@ -44,50 +52,57 @@ import java.util.concurrent.TimeUnit;
|
||||
* @author Brady
|
||||
* @since 7/31/2018 10:50 PM
|
||||
*/
|
||||
public enum Baritone implements IBaritoneProvider {
|
||||
public enum Baritone implements IBaritone {
|
||||
|
||||
/**
|
||||
* Singleton instance of this class
|
||||
*/
|
||||
INSTANCE;
|
||||
|
||||
private static ThreadPoolExecutor threadPool;
|
||||
private static File dir;
|
||||
|
||||
static {
|
||||
threadPool = new ThreadPoolExecutor(4, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<>());
|
||||
|
||||
dir = new File(Minecraft.getMinecraft().gameDir, "baritone");
|
||||
if (!Files.exists(dir.toPath())) {
|
||||
try {
|
||||
Files.createDirectories(dir.toPath());
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not {@link Baritone#init()} has been called yet
|
||||
*/
|
||||
private boolean initialized;
|
||||
|
||||
private GameEventHandler gameEventHandler;
|
||||
private InputOverrideHandler inputOverrideHandler;
|
||||
private Settings settings;
|
||||
private File dir;
|
||||
private ThreadPoolExecutor threadPool;
|
||||
|
||||
private List<Behavior> behaviors;
|
||||
private PathingBehavior pathingBehavior;
|
||||
private LookBehavior lookBehavior;
|
||||
private MemoryBehavior memoryBehavior;
|
||||
private FollowBehavior followBehavior;
|
||||
private MineBehavior mineBehavior;
|
||||
private InputOverrideHandler inputOverrideHandler;
|
||||
|
||||
/**
|
||||
* Whether or not Baritone is active
|
||||
*/
|
||||
private boolean active;
|
||||
private FollowProcess followProcess;
|
||||
private MineProcess mineProcess;
|
||||
private GetToBlockProcess getToBlockProcess;
|
||||
private CustomGoalProcess customGoalProcess;
|
||||
|
||||
private PathingControlManager pathingControlManager;
|
||||
|
||||
private WorldProvider worldProvider;
|
||||
|
||||
Baritone() {
|
||||
this.gameEventHandler = new GameEventHandler();
|
||||
this.gameEventHandler = new GameEventHandler(this);
|
||||
}
|
||||
|
||||
public synchronized void init() {
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
this.threadPool = new ThreadPoolExecutor(4, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<>());
|
||||
this.inputOverrideHandler = new InputOverrideHandler();
|
||||
|
||||
// Acquire the "singleton" instance of the settings directly from the API
|
||||
// We might want to change this...
|
||||
this.settings = BaritoneAPI.getSettings();
|
||||
|
||||
this.behaviors = new ArrayList<>();
|
||||
{
|
||||
@@ -95,26 +110,29 @@ public enum Baritone implements IBaritoneProvider {
|
||||
pathingBehavior = new PathingBehavior(this);
|
||||
lookBehavior = new LookBehavior(this);
|
||||
memoryBehavior = new MemoryBehavior(this);
|
||||
followBehavior = new FollowBehavior(this);
|
||||
mineBehavior = new MineBehavior(this);
|
||||
inputOverrideHandler = new InputOverrideHandler(this);
|
||||
new ExampleBaritoneControl(this);
|
||||
}
|
||||
|
||||
this.pathingControlManager = new PathingControlManager(this);
|
||||
{
|
||||
followProcess = new FollowProcess(this);
|
||||
mineProcess = new MineProcess(this);
|
||||
customGoalProcess = new CustomGoalProcess(this); // very high iq
|
||||
getToBlockProcess = new GetToBlockProcess(this);
|
||||
}
|
||||
|
||||
this.worldProvider = new WorldProvider();
|
||||
|
||||
if (BaritoneAutoTest.ENABLE_AUTO_TEST) {
|
||||
registerEventListener(BaritoneAutoTest.INSTANCE);
|
||||
}
|
||||
this.dir = new File(Minecraft.getMinecraft().gameDir, "baritone");
|
||||
if (!Files.exists(dir.toPath())) {
|
||||
try {
|
||||
Files.createDirectories(dir.toPath());
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
|
||||
this.active = true;
|
||||
this.initialized = true;
|
||||
}
|
||||
|
||||
public boolean isInitialized() {
|
||||
return this.initialized;
|
||||
public PathingControlManager getPathingControlManager() {
|
||||
return pathingControlManager;
|
||||
}
|
||||
|
||||
public IGameEventListener getGameEventHandler() {
|
||||
@@ -129,18 +147,24 @@ public enum Baritone implements IBaritoneProvider {
|
||||
return this.behaviors;
|
||||
}
|
||||
|
||||
public Executor getExecutor() {
|
||||
return threadPool;
|
||||
}
|
||||
|
||||
public void registerBehavior(Behavior behavior) {
|
||||
this.behaviors.add(behavior);
|
||||
this.registerEventListener(behavior);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FollowBehavior getFollowBehavior() {
|
||||
return followBehavior;
|
||||
public CustomGoalProcess getCustomGoalProcess() { // Iffy
|
||||
return customGoalProcess;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GetToBlockProcess getGetToBlockProcess() { // Iffy
|
||||
return getToBlockProcess;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FollowProcess getFollowProcess() {
|
||||
return followProcess;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -154,8 +178,8 @@ public enum Baritone implements IBaritoneProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public MineBehavior getMineBehavior() {
|
||||
return mineBehavior;
|
||||
public MineProcess getMineProcess() {
|
||||
return mineProcess;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -165,7 +189,7 @@ public enum Baritone implements IBaritoneProvider {
|
||||
|
||||
@Override
|
||||
public WorldProvider getWorldProvider() {
|
||||
return WorldProvider.INSTANCE;
|
||||
return worldProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -178,19 +202,15 @@ public enum Baritone implements IBaritoneProvider {
|
||||
this.gameEventHandler.registerEventListener(listener);
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return this.active;
|
||||
}
|
||||
|
||||
public Settings getSettings() {
|
||||
return this.settings;
|
||||
}
|
||||
|
||||
public static Settings settings() {
|
||||
return Baritone.INSTANCE.settings; // yolo
|
||||
return BaritoneAPI.getSettings();
|
||||
}
|
||||
|
||||
public File getDir() {
|
||||
return this.dir;
|
||||
public static File getDir() {
|
||||
return dir;
|
||||
}
|
||||
|
||||
public static Executor getExecutor() {
|
||||
return threadPool;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,59 +17,17 @@
|
||||
|
||||
package baritone;
|
||||
|
||||
import baritone.api.IBaritone;
|
||||
import baritone.api.IBaritoneProvider;
|
||||
import baritone.api.behavior.*;
|
||||
import baritone.api.cache.IWorldProvider;
|
||||
import baritone.api.cache.IWorldScanner;
|
||||
import baritone.api.event.listener.IGameEventListener;
|
||||
import baritone.cache.WorldProvider;
|
||||
import baritone.cache.WorldScanner;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
|
||||
/**
|
||||
* todo fix this cancer
|
||||
*
|
||||
* @author Brady
|
||||
* @since 9/29/2018
|
||||
*/
|
||||
public final class BaritoneProvider implements IBaritoneProvider {
|
||||
|
||||
@Override
|
||||
public IFollowBehavior getFollowBehavior() {
|
||||
return Baritone.INSTANCE.getFollowBehavior();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ILookBehavior getLookBehavior() {
|
||||
return Baritone.INSTANCE.getLookBehavior();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMemoryBehavior getMemoryBehavior() {
|
||||
return Baritone.INSTANCE.getMemoryBehavior();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMineBehavior getMineBehavior() {
|
||||
return Baritone.INSTANCE.getMineBehavior();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPathingBehavior getPathingBehavior() {
|
||||
return Baritone.INSTANCE.getPathingBehavior();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IWorldProvider getWorldProvider() {
|
||||
return WorldProvider.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IWorldScanner getWorldScanner() {
|
||||
return WorldScanner.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerEventListener(IGameEventListener listener) {
|
||||
Baritone.INSTANCE.registerEventListener(listener);
|
||||
public IBaritone getBaritoneForPlayer(EntityPlayerSP player) {
|
||||
return Baritone.INSTANCE; // pwnage
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import baritone.Baritone;
|
||||
import baritone.api.behavior.IBehavior;
|
||||
|
||||
/**
|
||||
* A type of game event listener that can be toggled.
|
||||
* A type of game event listener that is given {@link Baritone} instance context.
|
||||
*
|
||||
* @author Brady
|
||||
* @since 8/1/2018 6:29 PM
|
||||
@@ -30,49 +30,8 @@ public class Behavior implements IBehavior {
|
||||
|
||||
public final Baritone baritone;
|
||||
|
||||
/**
|
||||
* Whether or not this behavior is enabled
|
||||
*/
|
||||
private boolean enabled = true;
|
||||
|
||||
protected Behavior(Baritone baritone) {
|
||||
this.baritone = baritone;
|
||||
baritone.registerBehavior(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the enabled state of this {@link Behavior}.
|
||||
*
|
||||
* @return The new state.
|
||||
*/
|
||||
@Override
|
||||
public final boolean toggle() {
|
||||
return this.setEnabled(!this.isEnabled());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the enabled state of this {@link Behavior}.
|
||||
*
|
||||
* @return The new state.
|
||||
*/
|
||||
@Override
|
||||
public final boolean setEnabled(boolean enabled) {
|
||||
if (enabled == this.enabled) {
|
||||
return this.enabled;
|
||||
}
|
||||
if (this.enabled = enabled) {
|
||||
this.onEnable();
|
||||
} else {
|
||||
this.onDisable();
|
||||
}
|
||||
return this.enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whether or not this {@link Behavior} is active.
|
||||
*/
|
||||
@Override
|
||||
public final boolean isEnabled() {
|
||||
return this.enabled;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.behavior;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.behavior.IFollowBehavior;
|
||||
import baritone.api.event.events.TickEvent;
|
||||
import baritone.api.pathing.goals.GoalNear;
|
||||
import baritone.api.pathing.goals.GoalXZ;
|
||||
import baritone.utils.Helper;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
/**
|
||||
* Follow an entity
|
||||
*
|
||||
* @author leijurv
|
||||
*/
|
||||
public final class FollowBehavior extends Behavior implements IFollowBehavior, Helper {
|
||||
|
||||
private Entity following;
|
||||
|
||||
public FollowBehavior(Baritone baritone) {
|
||||
super(baritone);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTick(TickEvent event) {
|
||||
if (event.getType() == TickEvent.Type.OUT) {
|
||||
following = null;
|
||||
return;
|
||||
}
|
||||
if (following == null) {
|
||||
return;
|
||||
}
|
||||
// lol this is trashy but it works
|
||||
BlockPos pos;
|
||||
if (Baritone.settings().followOffsetDistance.get() == 0) {
|
||||
pos = following.getPosition();
|
||||
} else {
|
||||
GoalXZ g = GoalXZ.fromDirection(following.getPositionVector(), Baritone.settings().followOffsetDirection.get(), Baritone.settings().followOffsetDistance.get());
|
||||
pos = new BlockPos(g.getX(), following.posY, g.getZ());
|
||||
}
|
||||
baritone.getPathingBehavior().setGoal(new GoalNear(pos, Baritone.settings().followRadius.get()));
|
||||
((PathingBehavior) baritone.getPathingBehavior()).revalidateGoal();
|
||||
baritone.getPathingBehavior().path();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void follow(Entity entity) {
|
||||
this.following = entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entity following() {
|
||||
return this.following;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
baritone.getPathingBehavior().cancel();
|
||||
follow(null);
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@ import baritone.api.utils.Rotation;
|
||||
import baritone.utils.Helper;
|
||||
|
||||
public final class LookBehavior extends Behavior implements ILookBehavior, Helper {
|
||||
|
||||
/**
|
||||
* Target's values are as follows:
|
||||
* <p>
|
||||
@@ -63,7 +64,7 @@ public final class LookBehavior extends Behavior implements ILookBehavior, Helpe
|
||||
}
|
||||
|
||||
// Whether or not we're going to silently set our angles
|
||||
boolean silent = Baritone.settings().antiCheatCompatibility.get();
|
||||
boolean silent = Baritone.settings().antiCheatCompatibility.get() && !this.force;
|
||||
|
||||
switch (event.getState()) {
|
||||
case PRE: {
|
||||
@@ -76,14 +77,15 @@ public final class LookBehavior extends Behavior implements ILookBehavior, Helpe
|
||||
nudgeToLevel();
|
||||
}
|
||||
this.target = null;
|
||||
} else if (silent) {
|
||||
}
|
||||
if (silent) {
|
||||
this.lastYaw = player().rotationYaw;
|
||||
player().rotationYaw = this.target.getYaw();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case POST: {
|
||||
if (!this.force && silent) {
|
||||
if (silent) {
|
||||
player().rotationYaw = this.lastYaw;
|
||||
this.target = null;
|
||||
}
|
||||
@@ -97,26 +99,20 @@ public final class LookBehavior extends Behavior implements ILookBehavior, Helpe
|
||||
@Override
|
||||
public void onPlayerRotationMove(RotationMoveEvent event) {
|
||||
if (this.target != null && !this.force) {
|
||||
switch (event.getState()) {
|
||||
case PRE:
|
||||
this.lastYaw = player().rotationYaw;
|
||||
player().rotationYaw = this.target.getYaw();
|
||||
break;
|
||||
case POST:
|
||||
player().rotationYaw = this.lastYaw;
|
||||
|
||||
// If we have antiCheatCompatibility on, we're going to use the target value later in onPlayerUpdate()
|
||||
// Also the type has to be MOTION_UPDATE because that is called after JUMP
|
||||
if (!Baritone.settings().antiCheatCompatibility.get() && event.getType() == RotationMoveEvent.Type.MOTION_UPDATE) {
|
||||
this.target = null;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
event.setYaw(this.target.getYaw());
|
||||
|
||||
// If we have antiCheatCompatibility on, we're going to use the target value later in onPlayerUpdate()
|
||||
// Also the type has to be MOTION_UPDATE because that is called after JUMP
|
||||
if (!Baritone.settings().antiCheatCompatibility.get() && event.getType() == RotationMoveEvent.Type.MOTION_UPDATE) {
|
||||
this.target = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Nudges the player's pitch to a regular level. (Between {@code -20} and {@code 10}, increments are by {@code 1})
|
||||
*/
|
||||
private void nudgeToLevel() {
|
||||
if (player().rotationPitch < -20) {
|
||||
player().rotationPitch++;
|
||||
|
||||
@@ -26,7 +26,6 @@ import baritone.api.event.events.PacketEvent;
|
||||
import baritone.api.event.events.PlayerUpdateEvent;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
import baritone.cache.Waypoint;
|
||||
import baritone.cache.WorldProvider;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.Helper;
|
||||
import net.minecraft.block.BlockBed;
|
||||
@@ -122,13 +121,13 @@ public final class MemoryBehavior extends Behavior implements IMemoryBehavior, H
|
||||
@Override
|
||||
public void onBlockInteract(BlockInteractEvent event) {
|
||||
if (event.getType() == BlockInteractEvent.Type.USE && BlockStateInterface.getBlock(event.getPos()) instanceof BlockBed) {
|
||||
WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().addWaypoint(new Waypoint("bed", Waypoint.Tag.BED, event.getPos()));
|
||||
baritone.getWorldProvider().getCurrentWorld().getWaypoints().addWaypoint(new Waypoint("bed", Waypoint.Tag.BED, event.getPos()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerDeath() {
|
||||
WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().addWaypoint(new Waypoint("death", Waypoint.Tag.DEATH, playerFeet()));
|
||||
baritone.getWorldProvider().getCurrentWorld().getWaypoints().addWaypoint(new Waypoint("death", Waypoint.Tag.DEATH, playerFeet()));
|
||||
}
|
||||
|
||||
private Optional<RememberedInventory> getInventoryFromWindow(int windowId) {
|
||||
@@ -143,7 +142,7 @@ public final class MemoryBehavior extends Behavior implements IMemoryBehavior, H
|
||||
}
|
||||
|
||||
private WorldDataContainer getCurrentContainer() {
|
||||
return this.worldDataContainers.computeIfAbsent(WorldProvider.INSTANCE.getCurrentWorld(), data -> new WorldDataContainer());
|
||||
return this.worldDataContainers.computeIfAbsent(baritone.getWorldProvider().getCurrentWorld(), data -> new WorldDataContainer());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -28,12 +28,13 @@ import baritone.api.pathing.calc.IPathFinder;
|
||||
import baritone.api.pathing.goals.Goal;
|
||||
import baritone.api.pathing.goals.GoalXZ;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.api.utils.PathCalculationResult;
|
||||
import baritone.api.utils.interfaces.IGoalRenderPos;
|
||||
import baritone.pathing.calc.AStarPathFinder;
|
||||
import baritone.pathing.calc.AbstractNodeCostSearch;
|
||||
import baritone.pathing.calc.CutoffPath;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.pathing.path.CutoffPath;
|
||||
import baritone.pathing.path.PathExecutor;
|
||||
import baritone.utils.BlockBreakHelper;
|
||||
import baritone.utils.Helper;
|
||||
@@ -52,6 +53,11 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
|
||||
private Goal goal;
|
||||
|
||||
private boolean safeToCancel;
|
||||
private boolean pauseRequestedLastTick;
|
||||
private boolean cancelRequested;
|
||||
private boolean calcFailedLastTick;
|
||||
|
||||
private volatile boolean isPathCalcInProgress;
|
||||
private final Object pathCalcLock = new Object();
|
||||
|
||||
@@ -72,8 +78,9 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
private void dispatchEvents() {
|
||||
ArrayList<PathEvent> curr = new ArrayList<>();
|
||||
toDispatch.drainTo(curr);
|
||||
calcFailedLastTick = curr.contains(PathEvent.CALC_FAILED);
|
||||
for (PathEvent event : curr) {
|
||||
Baritone.INSTANCE.getGameEventHandler().onPathEvent(event);
|
||||
baritone.getGameEventHandler().onPathEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,18 +88,30 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
public void onTick(TickEvent event) {
|
||||
dispatchEvents();
|
||||
if (event.getType() == TickEvent.Type.OUT) {
|
||||
cancel();
|
||||
secretInternalSegmentCancel();
|
||||
baritone.getPathingControlManager().cancelEverything();
|
||||
return;
|
||||
}
|
||||
baritone.getPathingControlManager().preTick();
|
||||
tickPath();
|
||||
dispatchEvents();
|
||||
}
|
||||
|
||||
private void tickPath() {
|
||||
if (pauseRequestedLastTick && safeToCancel) {
|
||||
pauseRequestedLastTick = false;
|
||||
baritone.getInputOverrideHandler().clearAllKeys();
|
||||
BlockBreakHelper.stopBreakingBlock();
|
||||
return;
|
||||
}
|
||||
if (cancelRequested) {
|
||||
cancelRequested = false;
|
||||
baritone.getInputOverrideHandler().clearAllKeys();
|
||||
}
|
||||
if (current == null) {
|
||||
return;
|
||||
}
|
||||
boolean safe = current.onTick();
|
||||
safeToCancel = current.onTick();
|
||||
synchronized (pathPlanLock) {
|
||||
if (current.failed() || current.finished()) {
|
||||
current = null;
|
||||
@@ -134,7 +153,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
return;
|
||||
}
|
||||
// at this point, we know current is in progress
|
||||
if (safe && next != null && next.snipsnapifpossible()) {
|
||||
if (safeToCancel && next != null && next.snipsnapifpossible()) {
|
||||
// a movement just ended; jump directly onto the next path
|
||||
logDebug("Splicing into planned next path early...");
|
||||
queuePathEvent(PathEvent.SPLICING_ONTO_NEXT_EARLY);
|
||||
@@ -143,6 +162,10 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
current.onTick();
|
||||
return;
|
||||
}
|
||||
current = current.trySplice(next);
|
||||
if (next != null && current.getPath().getDest().equals(next.getPath().getDest())) {
|
||||
next = null;
|
||||
}
|
||||
synchronized (pathCalcLock) {
|
||||
if (isPathCalcInProgress) {
|
||||
// if we aren't calculating right now
|
||||
@@ -191,14 +214,13 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
return Optional.of(current.getPath().ticksRemainingFrom(current.getPosition()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGoal(Goal goal) {
|
||||
public void secretInternalSetGoal(Goal goal) {
|
||||
this.goal = goal;
|
||||
}
|
||||
|
||||
public boolean setGoalAndPath(Goal goal) {
|
||||
setGoal(goal);
|
||||
return path();
|
||||
public boolean secretInternalSetGoalAndPath(Goal goal) {
|
||||
secretInternalSetGoal(goal);
|
||||
return secretInternalPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -226,17 +248,60 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
return this.current != null;
|
||||
}
|
||||
|
||||
public boolean isSafeToCancel() {
|
||||
return current == null || safeToCancel;
|
||||
}
|
||||
|
||||
public void requestPause() {
|
||||
pauseRequestedLastTick = true;
|
||||
}
|
||||
|
||||
public boolean cancelSegmentIfSafe() {
|
||||
if (isSafeToCancel()) {
|
||||
secretInternalSegmentCancel();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
public boolean cancelEverything() {
|
||||
boolean doIt = isSafeToCancel();
|
||||
if (doIt) {
|
||||
secretInternalSegmentCancel();
|
||||
}
|
||||
baritone.getPathingControlManager().cancelEverything();
|
||||
return doIt;
|
||||
}
|
||||
|
||||
public boolean calcFailedLastTick() { // NOT exposed on public api
|
||||
return calcFailedLastTick;
|
||||
}
|
||||
|
||||
public void softCancelIfSafe() {
|
||||
if (!isSafeToCancel()) {
|
||||
return;
|
||||
}
|
||||
current = null;
|
||||
next = null;
|
||||
cancelRequested = true;
|
||||
AbstractNodeCostSearch.getCurrentlyRunning().ifPresent(AbstractNodeCostSearch::cancel);
|
||||
// do everything BUT clear keys
|
||||
}
|
||||
|
||||
// just cancel the current path
|
||||
public void secretInternalSegmentCancel() {
|
||||
queuePathEvent(PathEvent.CANCELED);
|
||||
current = null;
|
||||
next = null;
|
||||
Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys();
|
||||
baritone.getInputOverrideHandler().clearAllKeys();
|
||||
AbstractNodeCostSearch.getCurrentlyRunning().ifPresent(AbstractNodeCostSearch::cancel);
|
||||
BlockBreakHelper.stopBreakingBlock();
|
||||
}
|
||||
|
||||
public void forceCancel() { // NOT exposed on public api
|
||||
cancelEverything();
|
||||
secretInternalSegmentCancel();
|
||||
isPathCalcInProgress = false;
|
||||
}
|
||||
|
||||
@@ -245,8 +310,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
*
|
||||
* @return true if this call started path calculation, false if it was already calculating or executing a path
|
||||
*/
|
||||
@Override
|
||||
public boolean path() {
|
||||
public boolean secretInternalPath() {
|
||||
if (goal == null) {
|
||||
return false;
|
||||
}
|
||||
@@ -327,15 +391,16 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
isPathCalcInProgress = true;
|
||||
}
|
||||
CalculationContext context = new CalculationContext(); // not safe to create on the other thread, it looks up a lot of stuff in minecraft
|
||||
Baritone.INSTANCE.getExecutor().execute(() -> {
|
||||
Baritone.getExecutor().execute(() -> {
|
||||
if (talkAboutIt) {
|
||||
logDebug("Starting to search for path from " + start + " to " + goal);
|
||||
}
|
||||
|
||||
Optional<IPath> path = findPath(start, previous, context);
|
||||
PathCalculationResult calcResult = findPath(start, previous, context);
|
||||
Optional<IPath> path = calcResult.path;
|
||||
if (Baritone.settings().cutoffAtLoadBoundary.get()) {
|
||||
path = path.map(p -> {
|
||||
IPath result = p.cutoffAtLoadedChunks();
|
||||
IPath result = p.cutoffAtLoadedChunks(context.world());
|
||||
|
||||
if (result instanceof CutoffPath) {
|
||||
logDebug("Cutting off path at edge of loaded chunks");
|
||||
@@ -364,7 +429,10 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
queuePathEvent(PathEvent.CALC_FINISHED_NOW_EXECUTING);
|
||||
current = executor.get();
|
||||
} else {
|
||||
queuePathEvent(PathEvent.CALC_FAILED);
|
||||
if (calcResult.type != PathCalculationResult.Type.CANCELLATION && calcResult.type != PathCalculationResult.Type.EXCEPTION) {
|
||||
// don't dispatch CALC_FAILED on cancellation
|
||||
queuePathEvent(PathEvent.CALC_FAILED);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (next == null) {
|
||||
@@ -378,18 +446,16 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
throw new IllegalStateException("I have no idea what to do with this path");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (talkAboutIt && current != null && current.getPath() != null) {
|
||||
if (goal == null || goal.isInGoal(current.getPath().getDest())) {
|
||||
logDebug("Finished finding a path from " + start + " to " + goal + ". " + current.getPath().getNumNodesConsidered() + " nodes considered");
|
||||
} else {
|
||||
logDebug("Found path segment from " + start + " towards " + goal + ". " + current.getPath().getNumNodesConsidered() + " nodes considered");
|
||||
|
||||
if (talkAboutIt && current != null && current.getPath() != null) {
|
||||
if (goal == null || goal.isInGoal(current.getPath().getDest())) {
|
||||
logDebug("Finished finding a path from " + start + " to " + goal + ". " + current.getPath().getNumNodesConsidered() + " nodes considered");
|
||||
} else {
|
||||
logDebug("Found path segment from " + start + " towards " + goal + ". " + current.getPath().getNumNodesConsidered() + " nodes considered");
|
||||
}
|
||||
}
|
||||
synchronized (pathCalcLock) {
|
||||
isPathCalcInProgress = false;
|
||||
}
|
||||
}
|
||||
synchronized (pathCalcLock) {
|
||||
isPathCalcInProgress = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -400,19 +466,15 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
* @param start
|
||||
* @return
|
||||
*/
|
||||
private Optional<IPath> findPath(BlockPos start, Optional<IPath> previous, CalculationContext context) {
|
||||
private PathCalculationResult findPath(BlockPos start, Optional<IPath> previous, CalculationContext context) {
|
||||
Goal goal = this.goal;
|
||||
if (goal == null) {
|
||||
logDebug("no goal");
|
||||
return Optional.empty();
|
||||
return new PathCalculationResult(PathCalculationResult.Type.CANCELLATION, Optional.empty());
|
||||
}
|
||||
if (Baritone.settings().simplifyUnloadedYCoord.get()) {
|
||||
BlockPos pos = null;
|
||||
if (goal instanceof IGoalRenderPos) {
|
||||
pos = ((IGoalRenderPos) goal).getGoalPos();
|
||||
}
|
||||
|
||||
if (pos != null && world().getChunk(pos) instanceof EmptyChunk) {
|
||||
if (Baritone.settings().simplifyUnloadedYCoord.get() && goal instanceof IGoalRenderPos) {
|
||||
BlockPos pos = ((IGoalRenderPos) goal).getGoalPos();
|
||||
if (context.world().getChunk(pos) instanceof EmptyChunk) {
|
||||
logDebug("Simplifying " + goal.getClass() + " to GoalXZ due to distance");
|
||||
goal = new GoalXZ(pos.getX(), pos.getZ());
|
||||
}
|
||||
@@ -435,25 +497,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
} catch (Exception e) {
|
||||
logDebug("Pathing exception: " + e);
|
||||
e.printStackTrace();
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
public void revalidateGoal() {
|
||||
if (!Baritone.settings().cancelOnGoalInvalidation.get()) {
|
||||
return;
|
||||
}
|
||||
synchronized (pathPlanLock) {
|
||||
if (current == null || goal == null) {
|
||||
return;
|
||||
}
|
||||
Goal intended = current.getPath().getGoal();
|
||||
BlockPos end = current.getPath().getDest();
|
||||
if (intended.isInGoal(end) && !goal.isInGoal(end)) {
|
||||
// this path used to end in the goal
|
||||
// but the goal has changed, so there's no reason to continue...
|
||||
cancel();
|
||||
}
|
||||
return new PathCalculationResult(PathCalculationResult.Type.EXCEPTION, Optional.empty());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -461,9 +505,4 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
public void onRenderPass(RenderEvent event) {
|
||||
PathRenderer.render(event, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys();
|
||||
}
|
||||
}
|
||||
|
||||
+4
-6
@@ -17,7 +17,6 @@
|
||||
|
||||
package baritone.cache;
|
||||
|
||||
import baritone.api.cache.IBlockTypeAccess;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.pathing.PathingBlockType;
|
||||
import net.minecraft.block.Block;
|
||||
@@ -31,7 +30,7 @@ import java.util.*;
|
||||
* @author Brady
|
||||
* @since 8/3/2018 1:04 AM
|
||||
*/
|
||||
public final class CachedChunk implements IBlockTypeAccess, Helper {
|
||||
public final class CachedChunk implements Helper {
|
||||
|
||||
public static final Set<Block> BLOCKS_TO_KEEP_TRACK_OF;
|
||||
|
||||
@@ -143,8 +142,7 @@ public final class CachedChunk implements IBlockTypeAccess, Helper {
|
||||
calculateHeightMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final IBlockState getBlock(int x, int y, int z) {
|
||||
public final IBlockState getBlock(int x, int y, int z, int dimension) {
|
||||
int internalPos = z << 4 | x;
|
||||
if (heightMap[internalPos] == y) {
|
||||
// we have this exact block, it's a surface block
|
||||
@@ -155,10 +153,10 @@ public final class CachedChunk implements IBlockTypeAccess, Helper {
|
||||
return overview[internalPos];
|
||||
}
|
||||
PathingBlockType type = getType(x, y, z);
|
||||
if (type == PathingBlockType.SOLID && y == 127 && mc.player.dimension == -1) {
|
||||
if (type == PathingBlockType.SOLID && y == 127 && dimension == -1) {
|
||||
return Blocks.BEDROCK.getDefaultState();
|
||||
}
|
||||
return ChunkPacker.pathingTypeToBlock(type);
|
||||
return ChunkPacker.pathingTypeToBlock(type, dimension);
|
||||
}
|
||||
|
||||
private PathingBlockType getType(int x, int y, int z) {
|
||||
|
||||
+5
-2
@@ -59,22 +59,25 @@ public final class CachedRegion implements ICachedRegion {
|
||||
*/
|
||||
private final int z;
|
||||
|
||||
private final int dimension;
|
||||
|
||||
/**
|
||||
* Has this region been modified since its most recent load or save
|
||||
*/
|
||||
private boolean hasUnsavedChanges;
|
||||
|
||||
CachedRegion(int x, int z) {
|
||||
CachedRegion(int x, int z, int dimension) {
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
this.hasUnsavedChanges = false;
|
||||
this.dimension = dimension;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final IBlockState getBlock(int x, int y, int z) {
|
||||
CachedChunk chunk = chunks[x >> 4][z >> 4];
|
||||
if (chunk != null) {
|
||||
return chunk.getBlock(x & 15, y, z & 15);
|
||||
return chunk.getBlock(x & 15, y, z & 15, dimension);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
+11
-5
@@ -56,7 +56,9 @@ public final class CachedWorld implements ICachedWorld, Helper {
|
||||
|
||||
private final LinkedBlockingQueue<Chunk> toPack = new LinkedBlockingQueue<>();
|
||||
|
||||
CachedWorld(Path directory) {
|
||||
private final int dimension;
|
||||
|
||||
CachedWorld(Path directory, int dimension) {
|
||||
if (!Files.exists(directory)) {
|
||||
try {
|
||||
Files.createDirectories(directory);
|
||||
@@ -64,11 +66,12 @@ public final class CachedWorld implements ICachedWorld, Helper {
|
||||
}
|
||||
}
|
||||
this.directory = directory.toString();
|
||||
this.dimension = dimension;
|
||||
System.out.println("Cached world directory: " + directory);
|
||||
// Insert an invalid region element
|
||||
cachedRegions.put(0, null);
|
||||
Baritone.INSTANCE.getExecutor().execute(new PackerThread());
|
||||
Baritone.INSTANCE.getExecutor().execute(() -> {
|
||||
Baritone.getExecutor().execute(new PackerThread());
|
||||
Baritone.getExecutor().execute(() -> {
|
||||
try {
|
||||
Thread.sleep(30000);
|
||||
while (true) {
|
||||
@@ -165,6 +168,9 @@ public final class CachedWorld implements ICachedWorld, Helper {
|
||||
* Delete regions that are too far from the player
|
||||
*/
|
||||
private synchronized void prune() {
|
||||
if (!Baritone.settings().pruneRegionsFromRAM.get()) {
|
||||
return;
|
||||
}
|
||||
BlockPos pruneCenter = guessPosition();
|
||||
for (CachedRegion region : allRegions()) {
|
||||
if (region == null) {
|
||||
@@ -184,7 +190,7 @@ public final class CachedWorld implements ICachedWorld, Helper {
|
||||
* If we are still in this world and dimension, return player feet, otherwise return most recently modified chunk
|
||||
*/
|
||||
private BlockPos guessPosition() {
|
||||
WorldData data = WorldProvider.INSTANCE.getCurrentWorld();
|
||||
WorldData data = Baritone.INSTANCE.getWorldProvider().getCurrentWorld();
|
||||
if (data != null && data.getCachedWorld() == this) {
|
||||
return playerFeet();
|
||||
}
|
||||
@@ -238,7 +244,7 @@ public final class CachedWorld implements ICachedWorld, Helper {
|
||||
*/
|
||||
private synchronized CachedRegion getOrCreateRegion(int regionX, int regionZ) {
|
||||
return cachedRegions.computeIfAbsent(getRegionID(regionX, regionZ), id -> {
|
||||
CachedRegion newRegion = new CachedRegion(regionX, regionZ);
|
||||
CachedRegion newRegion = new CachedRegion(regionX, regionZ, dimension);
|
||||
newRegion.load(this.directory);
|
||||
return newRegion;
|
||||
});
|
||||
|
||||
+2
-2
@@ -144,7 +144,7 @@ public final class ChunkPacker implements Helper {
|
||||
return PathingBlockType.SOLID;
|
||||
}
|
||||
|
||||
public static IBlockState pathingTypeToBlock(PathingBlockType type) {
|
||||
public static IBlockState pathingTypeToBlock(PathingBlockType type, int dimension) {
|
||||
switch (type) {
|
||||
case AIR:
|
||||
return Blocks.AIR.getDefaultState();
|
||||
@@ -154,7 +154,7 @@ public final class ChunkPacker implements Helper {
|
||||
return Blocks.LAVA.getDefaultState();
|
||||
case SOLID:
|
||||
// Dimension solid types
|
||||
switch (mc.player.dimension) {
|
||||
switch (dimension) {
|
||||
case -1:
|
||||
return Blocks.NETHERRACK.getDefaultState();
|
||||
case 0:
|
||||
|
||||
+3
-3
@@ -42,9 +42,9 @@ public class Waypoint implements IWaypoint {
|
||||
* Constructor called when a Waypoint is read from disk, adds the creationTimestamp
|
||||
* as a parameter so that it is reserved after a waypoint is wrote to the disk.
|
||||
*
|
||||
* @param name The waypoint name
|
||||
* @param tag The waypoint tag
|
||||
* @param location The waypoint location
|
||||
* @param name The waypoint name
|
||||
* @param tag The waypoint tag
|
||||
* @param location The waypoint location
|
||||
* @param creationTimestamp When the waypoint was created
|
||||
*/
|
||||
Waypoint(String name, Tag tag, BlockPos location, long creationTimestamp) {
|
||||
|
||||
+5
-3
@@ -35,15 +35,17 @@ public class WorldData implements IWorldData {
|
||||
private final Waypoints waypoints;
|
||||
//public final MapData map;
|
||||
public final Path directory;
|
||||
public final int dimension;
|
||||
|
||||
WorldData(Path directory) {
|
||||
WorldData(Path directory, int dimension) {
|
||||
this.directory = directory;
|
||||
this.cache = new CachedWorld(directory.resolve("cache"));
|
||||
this.cache = new CachedWorld(directory.resolve("cache"), dimension);
|
||||
this.waypoints = new Waypoints(directory.resolve("waypoints"));
|
||||
this.dimension = dimension;
|
||||
}
|
||||
|
||||
public void onClose() {
|
||||
Baritone.INSTANCE.getExecutor().execute(() -> {
|
||||
Baritone.getExecutor().execute(() -> {
|
||||
System.out.println("Started saving the world in a new thread");
|
||||
cache.save();
|
||||
});
|
||||
|
||||
+22
-18
@@ -22,7 +22,6 @@ import baritone.api.cache.IWorldProvider;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.accessor.IAnvilChunkLoader;
|
||||
import baritone.utils.accessor.IChunkProviderServer;
|
||||
import net.minecraft.client.multiplayer.WorldClient;
|
||||
import net.minecraft.server.integrated.IntegratedServer;
|
||||
import net.minecraft.world.WorldServer;
|
||||
|
||||
@@ -39,11 +38,9 @@ import java.util.function.Consumer;
|
||||
* @author Brady
|
||||
* @since 8/4/2018 11:06 AM
|
||||
*/
|
||||
public enum WorldProvider implements IWorldProvider, Helper {
|
||||
public class WorldProvider implements IWorldProvider, Helper {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
private final Map<Path, WorldData> worldCache = new HashMap<>();
|
||||
private static final Map<Path, WorldData> worldCache = new HashMap<>(); // this is how the bots have the same cached world
|
||||
|
||||
private WorldData currentWorld;
|
||||
|
||||
@@ -52,13 +49,20 @@ public enum WorldProvider implements IWorldProvider, Helper {
|
||||
return this.currentWorld;
|
||||
}
|
||||
|
||||
public final void initWorld(WorldClient world) {
|
||||
int dimensionID = world.provider.getDimensionType().getId();
|
||||
File directory;
|
||||
File readme;
|
||||
/**
|
||||
* Called when a new world is initialized to discover the
|
||||
*
|
||||
* @param dimension The ID of the world's dimension
|
||||
*/
|
||||
public final void initWorld(int dimension) {
|
||||
// Fight me @leijurv
|
||||
File directory, readme;
|
||||
|
||||
IntegratedServer integratedServer = mc.getIntegratedServer();
|
||||
|
||||
// If there is an integrated server running (Aka Singleplayer) then do magic to find the world save file
|
||||
if (integratedServer != null) {
|
||||
WorldServer localServerWorld = integratedServer.getWorld(dimensionID);
|
||||
WorldServer localServerWorld = integratedServer.getWorld(dimension);
|
||||
IChunkProviderServer provider = (IChunkProviderServer) localServerWorld.getChunkProvider();
|
||||
IAnvilChunkLoader loader = (IAnvilChunkLoader) provider.getChunkLoader();
|
||||
directory = loader.getChunkSaveLocation();
|
||||
@@ -71,27 +75,27 @@ public enum WorldProvider implements IWorldProvider, Helper {
|
||||
|
||||
directory = new File(directory, "baritone");
|
||||
readme = directory;
|
||||
|
||||
} else {
|
||||
//remote
|
||||
directory = new File(Baritone.INSTANCE.getDir(), mc.getCurrentServerData().serverIP);
|
||||
readme = Baritone.INSTANCE.getDir();
|
||||
} else { // Otherwise, the server must be remote...
|
||||
directory = new File(Baritone.getDir(), mc.getCurrentServerData().serverIP);
|
||||
readme = Baritone.getDir();
|
||||
}
|
||||
|
||||
// lol wtf is this baritone folder in my minecraft save?
|
||||
try (FileOutputStream out = new FileOutputStream(new File(readme, "readme.txt"))) {
|
||||
// good thing we have a readme
|
||||
out.write("https://github.com/cabaletta/baritone\n".getBytes());
|
||||
} catch (IOException ignored) {}
|
||||
|
||||
directory = new File(directory, "DIM" + dimensionID);
|
||||
Path dir = directory.toPath();
|
||||
// We will actually store the world data in a subfolder: "DIM<id>"
|
||||
Path dir = new File(directory, "DIM" + dimension).toPath();
|
||||
if (!Files.exists(dir)) {
|
||||
try {
|
||||
Files.createDirectories(dir);
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
|
||||
System.out.println("Baritone world data dir: " + dir);
|
||||
this.currentWorld = this.worldCache.computeIfAbsent(dir, WorldData::new);
|
||||
this.currentWorld = worldCache.computeIfAbsent(dir, d -> new WorldData(d, dimension));
|
||||
}
|
||||
|
||||
public final void closeWorld() {
|
||||
|
||||
@@ -21,16 +21,12 @@ import baritone.Baritone;
|
||||
import baritone.api.event.events.*;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
import baritone.api.event.listener.IGameEventListener;
|
||||
import baritone.api.utils.interfaces.Toggleable;
|
||||
import baritone.cache.WorldProvider;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.InputOverrideHandler;
|
||||
import net.minecraft.client.settings.KeyBinding;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
@@ -38,57 +34,32 @@ import java.util.ArrayList;
|
||||
*/
|
||||
public final class GameEventHandler implements IGameEventListener, Helper {
|
||||
|
||||
private final ArrayList<IGameEventListener> listeners = new ArrayList<>();
|
||||
private final Baritone baritone;
|
||||
|
||||
private final List<IGameEventListener> listeners = new ArrayList<>();
|
||||
|
||||
public GameEventHandler(Baritone baritone) {
|
||||
this.baritone = baritone;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onTick(TickEvent event) {
|
||||
listeners.forEach(l -> {
|
||||
if (canDispatch(l)) {
|
||||
l.onTick(event);
|
||||
}
|
||||
});
|
||||
listeners.forEach(l -> l.onTick(event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onPlayerUpdate(PlayerUpdateEvent event) {
|
||||
listeners.forEach(l -> {
|
||||
if (canDispatch(l)) {
|
||||
l.onPlayerUpdate(event);
|
||||
}
|
||||
});
|
||||
listeners.forEach(l -> l.onPlayerUpdate(event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onProcessKeyBinds() {
|
||||
InputOverrideHandler inputHandler = Baritone.INSTANCE.getInputOverrideHandler();
|
||||
|
||||
// Simulate the key being held down this tick
|
||||
for (InputOverrideHandler.Input input : InputOverrideHandler.Input.values()) {
|
||||
KeyBinding keyBinding = input.getKeyBinding();
|
||||
|
||||
if (inputHandler.isInputForcedDown(keyBinding) && !keyBinding.isKeyDown()) {
|
||||
int keyCode = keyBinding.getKeyCode();
|
||||
|
||||
if (keyCode < Keyboard.KEYBOARD_SIZE) {
|
||||
KeyBinding.onTick(keyCode < 0 ? keyCode + 100 : keyCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
listeners.forEach(l -> {
|
||||
if (canDispatch(l)) {
|
||||
l.onProcessKeyBinds();
|
||||
}
|
||||
});
|
||||
listeners.forEach(IGameEventListener::onProcessKeyBinds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onSendChatMessage(ChatEvent event) {
|
||||
listeners.forEach(l -> {
|
||||
if (canDispatch(l)) {
|
||||
l.onSendChatMessage(event);
|
||||
}
|
||||
});
|
||||
listeners.forEach(l -> l.onSendChatMessage(event));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -107,108 +78,67 @@ public final class GameEventHandler implements IGameEventListener, Helper {
|
||||
&& mc.world.getChunkProvider().isChunkGeneratedAt(event.getX(), event.getZ());
|
||||
|
||||
if (isPostPopulate || isPreUnload) {
|
||||
WorldProvider.INSTANCE.ifWorldLoaded(world -> {
|
||||
baritone.getWorldProvider().ifWorldLoaded(world -> {
|
||||
Chunk chunk = mc.world.getChunk(event.getX(), event.getZ());
|
||||
world.getCachedWorld().queueForPacking(chunk);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
listeners.forEach(l -> {
|
||||
if (canDispatch(l)) {
|
||||
l.onChunkEvent(event);
|
||||
}
|
||||
});
|
||||
listeners.forEach(l -> l.onChunkEvent(event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onRenderPass(RenderEvent event) {
|
||||
listeners.forEach(l -> {
|
||||
if (canDispatch(l)) {
|
||||
l.onRenderPass(event);
|
||||
}
|
||||
});
|
||||
listeners.forEach(l -> l.onRenderPass(event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onWorldEvent(WorldEvent event) {
|
||||
WorldProvider cache = WorldProvider.INSTANCE;
|
||||
|
||||
BlockStateInterface.clearCachedChunk();
|
||||
WorldProvider cache = baritone.getWorldProvider();
|
||||
|
||||
if (event.getState() == EventState.POST) {
|
||||
cache.closeWorld();
|
||||
if (event.getWorld() != null) {
|
||||
cache.initWorld(event.getWorld());
|
||||
cache.initWorld(event.getWorld().provider.getDimensionType().getId());
|
||||
}
|
||||
}
|
||||
|
||||
listeners.forEach(l -> {
|
||||
if (canDispatch(l)) {
|
||||
l.onWorldEvent(event);
|
||||
}
|
||||
});
|
||||
listeners.forEach(l -> l.onWorldEvent(event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onSendPacket(PacketEvent event) {
|
||||
listeners.forEach(l -> {
|
||||
if (canDispatch(l)) {
|
||||
l.onSendPacket(event);
|
||||
}
|
||||
});
|
||||
listeners.forEach(l -> l.onSendPacket(event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onReceivePacket(PacketEvent event) {
|
||||
listeners.forEach(l -> {
|
||||
if (canDispatch(l)) {
|
||||
l.onReceivePacket(event);
|
||||
}
|
||||
});
|
||||
listeners.forEach(l -> l.onReceivePacket(event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerRotationMove(RotationMoveEvent event) {
|
||||
listeners.forEach(l -> {
|
||||
if (canDispatch(l)) {
|
||||
l.onPlayerRotationMove(event);
|
||||
}
|
||||
});
|
||||
listeners.forEach(l -> l.onPlayerRotationMove(event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockInteract(BlockInteractEvent event) {
|
||||
listeners.forEach(l -> {
|
||||
if (canDispatch(l)) {
|
||||
l.onBlockInteract(event);
|
||||
}
|
||||
});
|
||||
listeners.forEach(l -> l.onBlockInteract(event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerDeath() {
|
||||
listeners.forEach(l -> {
|
||||
if (canDispatch(l)) {
|
||||
l.onPlayerDeath();
|
||||
}
|
||||
});
|
||||
listeners.forEach(IGameEventListener::onPlayerDeath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPathEvent(PathEvent event) {
|
||||
listeners.forEach(l -> {
|
||||
if (canDispatch(l)) {
|
||||
l.onPathEvent(event);
|
||||
}
|
||||
});
|
||||
listeners.forEach(l -> l.onPathEvent(event));
|
||||
}
|
||||
|
||||
public final void registerEventListener(IGameEventListener listener) {
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
private boolean canDispatch(IGameEventListener listener) {
|
||||
return !(listener instanceof Toggleable) || ((Toggleable) listener).isEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.pathing.calc.openset.BinaryHeapOpenSet;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.Moves;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.pathing.BetterWorldBorder;
|
||||
import baritone.utils.pathing.MutableMoveResult;
|
||||
@@ -44,7 +43,7 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
|
||||
private final CalculationContext calcContext;
|
||||
|
||||
public AStarPathFinder(int startX, int startY, int startZ, Goal goal, Optional<HashSet<Long>> favoredPositions, CalculationContext context) {
|
||||
super(startX, startY, startZ, goal);
|
||||
super(startX, startY, startZ, goal, context);
|
||||
this.favoredPositions = favoredPositions;
|
||||
this.calcContext = context;
|
||||
}
|
||||
@@ -65,8 +64,7 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
|
||||
}
|
||||
MutableMoveResult res = new MutableMoveResult();
|
||||
HashSet<Long> favored = favoredPositions.orElse(null);
|
||||
BetterWorldBorder worldBorder = new BetterWorldBorder(world().getWorldBorder());
|
||||
BlockStateInterface.clearCachedChunk();
|
||||
BetterWorldBorder worldBorder = new BetterWorldBorder(calcContext.world().getWorldBorder());
|
||||
long startTime = System.nanoTime() / 1000000L;
|
||||
boolean slowPath = Baritone.settings().slowPath.get();
|
||||
if (slowPath) {
|
||||
@@ -95,12 +93,12 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
|
||||
numNodes++;
|
||||
if (goal.isInGoal(currentNode.x, currentNode.y, currentNode.z)) {
|
||||
logDebug("Took " + (System.nanoTime() / 1000000L - startTime) + "ms, " + numMovementsConsidered + " movements considered");
|
||||
return Optional.of(new Path(startNode, currentNode, numNodes, goal));
|
||||
return Optional.of(new Path(startNode, currentNode, numNodes, goal, calcContext));
|
||||
}
|
||||
for (Moves moves : Moves.values()) {
|
||||
int newX = currentNode.x + moves.xOffset;
|
||||
int newZ = currentNode.z + moves.zOffset;
|
||||
if ((newX >> 4 != currentNode.x >> 4 || newZ >> 4 != currentNode.z >> 4) && !BlockStateInterface.isLoaded(newX, newZ)) {
|
||||
if ((newX >> 4 != currentNode.x >> 4 || newZ >> 4 != currentNode.z >> 4) && !calcContext.isLoaded(newX, newZ)) {
|
||||
// only need to check if the destination is a loaded chunk if it's in a different chunk than the start of the movement
|
||||
if (!moves.dynamicXZ) { // only increment the counter if the movement would have gone out of bounds guaranteed
|
||||
numEmptyChunk++;
|
||||
@@ -131,7 +129,7 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
|
||||
throw new IllegalStateException(moves + " " + res.x + " " + newX + " " + res.z + " " + newZ);
|
||||
}
|
||||
if (!moves.dynamicY && res.y != currentNode.y + moves.yOffset) {
|
||||
throw new IllegalStateException(moves + " " + res.x + " " + newX + " " + res.z + " " + newZ);
|
||||
throw new IllegalStateException(moves + " " + res.y + " " + (currentNode.y + moves.yOffset));
|
||||
}
|
||||
long hashCode = BetterBlockPos.longHash(res.x, res.y, res.z);
|
||||
if (favoring && favored.contains(hashCode)) {
|
||||
@@ -198,7 +196,7 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
|
||||
System.out.println("But I'm going to do it anyway, because yolo");
|
||||
}
|
||||
System.out.println("Path goes for " + Math.sqrt(dist) + " blocks");
|
||||
return Optional.of(new Path(startNode, bestSoFar[i], numNodes, goal));
|
||||
return Optional.of(new Path(startNode, bestSoFar[i], numNodes, goal, calcContext));
|
||||
}
|
||||
}
|
||||
logDebug("Even with a cost coefficient of " + COEFFICIENTS[COEFFICIENTS.length - 1] + ", I couldn't get more than " + Math.sqrt(bestDist) + " blocks");
|
||||
|
||||
@@ -21,6 +21,8 @@ import baritone.Baritone;
|
||||
import baritone.api.pathing.calc.IPath;
|
||||
import baritone.api.pathing.calc.IPathFinder;
|
||||
import baritone.api.pathing.goals.Goal;
|
||||
import baritone.api.utils.PathCalculationResult;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||
|
||||
import java.util.Optional;
|
||||
@@ -43,6 +45,8 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
|
||||
|
||||
protected final Goal goal;
|
||||
|
||||
private final CalculationContext context;
|
||||
|
||||
/**
|
||||
* @see <a href="https://github.com/cabaletta/baritone/issues/107">Issue #107</a>
|
||||
*/
|
||||
@@ -70,11 +74,12 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
|
||||
*/
|
||||
protected final static double MIN_DIST_PATH = 5;
|
||||
|
||||
AbstractNodeCostSearch(int startX, int startY, int startZ, Goal goal) {
|
||||
AbstractNodeCostSearch(int startX, int startY, int startZ, Goal goal, CalculationContext context) {
|
||||
this.startX = startX;
|
||||
this.startY = startY;
|
||||
this.startZ = startZ;
|
||||
this.goal = goal;
|
||||
this.context = context;
|
||||
this.map = new Long2ObjectOpenHashMap<>(Baritone.settings().pathingMapDefaultSize.value, Baritone.settings().pathingMapLoadFactor.get());
|
||||
}
|
||||
|
||||
@@ -82,16 +87,26 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
|
||||
cancelRequested = true;
|
||||
}
|
||||
|
||||
public synchronized Optional<IPath> calculate(long timeout) {
|
||||
public synchronized PathCalculationResult calculate(long timeout) {
|
||||
if (isFinished) {
|
||||
throw new IllegalStateException("Path Finder is currently in use, and cannot be reused!");
|
||||
}
|
||||
this.cancelRequested = false;
|
||||
try {
|
||||
Optional<IPath> path = calculate0(timeout);
|
||||
path.ifPresent(IPath::postProcess);
|
||||
path = path.map(IPath::postProcess);
|
||||
isFinished = true;
|
||||
return path;
|
||||
if (cancelRequested) {
|
||||
return new PathCalculationResult(PathCalculationResult.Type.CANCELLATION, path);
|
||||
}
|
||||
if (!path.isPresent()) {
|
||||
return new PathCalculationResult(PathCalculationResult.Type.FAILURE, path);
|
||||
}
|
||||
if (goal.isInGoal(path.get().getDest())) {
|
||||
return new PathCalculationResult(PathCalculationResult.Type.SUCCESS_TO_GOAL, path);
|
||||
} else {
|
||||
return new PathCalculationResult(PathCalculationResult.Type.SUCCESS_SEGMENT, path);
|
||||
}
|
||||
} finally {
|
||||
// this is run regardless of what exception may or may not be raised by calculate0
|
||||
currentlyRunning = null;
|
||||
@@ -160,7 +175,7 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
|
||||
@Override
|
||||
public Optional<IPath> pathToMostRecentNodeConsidered() {
|
||||
try {
|
||||
return Optional.ofNullable(mostRecentConsidered).map(node -> new Path(startNode, node, 0, goal));
|
||||
return Optional.ofNullable(mostRecentConsidered).map(node -> new Path(startNode, node, 0, goal, context));
|
||||
} catch (IllegalStateException ex) {
|
||||
System.out.println("Unable to construct path to render");
|
||||
return Optional.empty();
|
||||
@@ -182,7 +197,7 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
|
||||
}
|
||||
if (getDistFromStartSq(bestSoFar[i]) > MIN_DIST_PATH * MIN_DIST_PATH) { // square the comparison since distFromStartSq is squared
|
||||
try {
|
||||
return Optional.of(new Path(startNode, bestSoFar[i], 0, goal));
|
||||
return Optional.of(new Path(startNode, bestSoFar[i], 0, goal, context));
|
||||
} catch (IllegalStateException ex) {
|
||||
System.out.println("Unable to construct path to render");
|
||||
return Optional.empty();
|
||||
|
||||
@@ -17,16 +17,16 @@
|
||||
|
||||
package baritone.pathing.calc;
|
||||
|
||||
import baritone.api.BaritoneAPI;
|
||||
import baritone.api.pathing.calc.IPath;
|
||||
import baritone.api.pathing.goals.Goal;
|
||||
import baritone.api.pathing.movement.IMovement;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.movement.Moves;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.chunk.EmptyChunk;
|
||||
import baritone.pathing.path.CutoffPath;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.pathing.PathBase;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -38,7 +38,7 @@ import java.util.List;
|
||||
*
|
||||
* @author leijurv
|
||||
*/
|
||||
class Path implements IPath {
|
||||
class Path extends PathBase {
|
||||
|
||||
/**
|
||||
* The start position of this path
|
||||
@@ -58,20 +58,26 @@ class Path implements IPath {
|
||||
|
||||
private final List<Movement> movements;
|
||||
|
||||
private final List<PathNode> nodes;
|
||||
|
||||
private final Goal goal;
|
||||
|
||||
private final int numNodes;
|
||||
|
||||
private final CalculationContext context;
|
||||
|
||||
private volatile boolean verified;
|
||||
|
||||
Path(PathNode start, PathNode end, int numNodes, Goal goal) {
|
||||
Path(PathNode start, PathNode end, int numNodes, Goal goal, CalculationContext context) {
|
||||
this.start = new BetterBlockPos(start.x, start.y, start.z);
|
||||
this.end = new BetterBlockPos(end.x, end.y, end.z);
|
||||
this.numNodes = numNodes;
|
||||
this.path = new ArrayList<>();
|
||||
this.movements = new ArrayList<>();
|
||||
this.nodes = new ArrayList<>();
|
||||
this.goal = goal;
|
||||
assemblePath(start, end);
|
||||
this.context = context;
|
||||
assemblePath(end);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -80,88 +86,80 @@ class Path implements IPath {
|
||||
}
|
||||
|
||||
/**
|
||||
* Assembles this path given the start and end nodes.
|
||||
* Assembles this path given the end node.
|
||||
*
|
||||
* @param start The start node
|
||||
* @param end The end node
|
||||
* @param end The end node
|
||||
*/
|
||||
private void assemblePath(PathNode start, PathNode end) {
|
||||
private void assemblePath(PathNode end) {
|
||||
if (!path.isEmpty() || !movements.isEmpty()) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
PathNode current = end;
|
||||
LinkedList<BetterBlockPos> tempPath = new LinkedList<>();
|
||||
LinkedList<PathNode> tempNodes = new LinkedList();
|
||||
// Repeatedly inserting to the beginning of an arraylist is O(n^2)
|
||||
// Instead, do it into a linked list, then convert at the end
|
||||
while (!current.equals(start)) {
|
||||
while (current != null) {
|
||||
tempNodes.addFirst(current);
|
||||
tempPath.addFirst(new BetterBlockPos(current.x, current.y, current.z));
|
||||
current = current.previous;
|
||||
}
|
||||
tempPath.addFirst(this.start);
|
||||
// Can't directly convert from the PathNode pseudo linked list to an array because we don't know how long it is
|
||||
// inserting into a LinkedList<E> keeps track of length, then when we addall (which calls .toArray) it's able
|
||||
// to performantly do that conversion since it knows the length.
|
||||
path.addAll(tempPath);
|
||||
nodes.addAll(tempNodes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a series of checks to ensure that the assembly of the path went as expected.
|
||||
*/
|
||||
private void sanityCheck() {
|
||||
if (!start.equals(path.get(0))) {
|
||||
throw new IllegalStateException("Start node does not equal first path element");
|
||||
}
|
||||
if (!end.equals(path.get(path.size() - 1))) {
|
||||
throw new IllegalStateException("End node does not equal last path element");
|
||||
}
|
||||
if (path.size() != movements.size() + 1) {
|
||||
throw new IllegalStateException("Size of path array is unexpected");
|
||||
}
|
||||
for (int i = 0; i < path.size() - 1; i++) {
|
||||
BlockPos src = path.get(i);
|
||||
BlockPos dest = path.get(i + 1);
|
||||
Movement movement = movements.get(i);
|
||||
if (!src.equals(movement.getSrc())) {
|
||||
throw new IllegalStateException("Path source is not equal to the movement source");
|
||||
}
|
||||
if (!dest.equals(movement.getDest())) {
|
||||
throw new IllegalStateException("Path destination is not equal to the movement destination");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void assembleMovements() {
|
||||
private boolean assembleMovements() {
|
||||
if (path.isEmpty() || !movements.isEmpty()) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
for (int i = 0; i < path.size() - 1; i++) {
|
||||
movements.add(runBackwards(path.get(i), path.get(i + 1)));
|
||||
double cost = nodes.get(i + 1).cost - nodes.get(i).cost;
|
||||
Movement move = runBackwards(path.get(i), path.get(i + 1), cost);
|
||||
if (move == null) {
|
||||
return true;
|
||||
} else {
|
||||
movements.add(move);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static Movement runBackwards(BetterBlockPos src, BetterBlockPos dest) { // TODO this is horrifying
|
||||
private Movement runBackwards(BetterBlockPos src, BetterBlockPos dest, double cost) {
|
||||
for (Moves moves : Moves.values()) {
|
||||
Movement move = moves.apply0(src);
|
||||
Movement move = moves.apply0(context, src);
|
||||
if (move.getDest().equals(dest)) {
|
||||
// TODO instead of recalculating here, could we take pathNode.cost - pathNode.prevNode.cost to get the cost as-calculated?
|
||||
move.recalculateCost(); // have to calculate the cost at calculation time so we can accurately judge whether a cost increase happened between cached calculation and real execution
|
||||
// have to calculate the cost at calculation time so we can accurately judge whether a cost increase happened between cached calculation and real execution
|
||||
move.override(cost);
|
||||
return move;
|
||||
}
|
||||
}
|
||||
// this is no longer called from bestPathSoFar, now it's in postprocessing
|
||||
throw new IllegalStateException("Movement became impossible during calculation " + src + " " + dest + " " + dest.subtract(src));
|
||||
Helper.HELPER.logDebug("Movement became impossible during calculation " + src + " " + dest + " " + dest.subtract(src));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcess() {
|
||||
public IPath postProcess() {
|
||||
if (verified) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
verified = true;
|
||||
assembleMovements();
|
||||
boolean failed = assembleMovements();
|
||||
movements.forEach(m -> m.checkLoadedChunk(context));
|
||||
|
||||
if (failed) { // at least one movement became impossible during calculation
|
||||
CutoffPath res = new CutoffPath(this, movements().size());
|
||||
if (res.movements().size() != movements.size()) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
// more post processing here
|
||||
movements.forEach(Movement::checkLoadedChunk);
|
||||
sanityCheck();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -191,28 +189,4 @@ class Path implements IPath {
|
||||
public BetterBlockPos getDest() {
|
||||
return end;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPath cutoffAtLoadedChunks() {
|
||||
for (int i = 0; i < positions().size(); i++) {
|
||||
BlockPos pos = positions().get(i);
|
||||
if (Minecraft.getMinecraft().world.getChunk(pos) instanceof EmptyChunk) {
|
||||
return new CutoffPath(this, i);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPath staticCutoff(Goal destination) {
|
||||
if (length() < BaritoneAPI.getSettings().pathCutoffMinimumLength.get()) {
|
||||
return this;
|
||||
}
|
||||
if (destination == null || destination.isInGoal(getDest())) {
|
||||
return this;
|
||||
}
|
||||
double factor = BaritoneAPI.getSettings().pathCutoffFactor.get();
|
||||
int newLength = (int) (length() * factor);
|
||||
return new CutoffPath(this, newLength);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,22 +19,33 @@ package baritone.pathing.movement;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.pathing.movement.ActionCosts;
|
||||
import baritone.cache.WorldData;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.ToolSet;
|
||||
import baritone.utils.pathing.BetterWorldBorder;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.enchantment.EnchantmentHelper;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/7/2018 4:30 PM
|
||||
*/
|
||||
public class CalculationContext implements Helper {
|
||||
public class CalculationContext {
|
||||
|
||||
private static final ItemStack STACK_BUCKET_WATER = new ItemStack(Items.WATER_BUCKET);
|
||||
|
||||
private final EntityPlayerSP player;
|
||||
private final World world;
|
||||
private final WorldData worldData;
|
||||
private final BlockStateInterface bsi;
|
||||
private final ToolSet toolSet;
|
||||
private final boolean hasWaterBucket;
|
||||
private final boolean hasThrowaway;
|
||||
@@ -48,19 +59,20 @@ public class CalculationContext implements Helper {
|
||||
private final BetterWorldBorder worldBorder;
|
||||
|
||||
public CalculationContext() {
|
||||
this(new ToolSet());
|
||||
}
|
||||
|
||||
public CalculationContext(ToolSet toolSet) {
|
||||
this.toolSet = toolSet;
|
||||
this.player = Helper.HELPER.player();
|
||||
this.world = Helper.HELPER.world();
|
||||
this.worldData = Baritone.INSTANCE.getWorldProvider().getCurrentWorld();
|
||||
this.bsi = new BlockStateInterface(world, worldData); // TODO TODO TODO
|
||||
// new CalculationContext() needs to happen, can't add an argument (i'll beat you), can we get the world provider from currentlyTicking?
|
||||
this.toolSet = new ToolSet(player);
|
||||
this.hasThrowaway = Baritone.settings().allowPlace.get() && MovementHelper.throwaway(false);
|
||||
this.hasWaterBucket = Baritone.settings().allowWaterBucketFall.get() && InventoryPlayer.isHotbar(player().inventory.getSlotFor(STACK_BUCKET_WATER)) && !world().provider.isNether();
|
||||
this.canSprint = Baritone.settings().allowSprint.get() && player().getFoodStats().getFoodLevel() > 6;
|
||||
this.hasWaterBucket = Baritone.settings().allowWaterBucketFall.get() && InventoryPlayer.isHotbar(player.inventory.getSlotFor(STACK_BUCKET_WATER)) && !world.provider.isNether();
|
||||
this.canSprint = Baritone.settings().allowSprint.get() && player.getFoodStats().getFoodLevel() > 6;
|
||||
this.placeBlockCost = Baritone.settings().blockPlacementPenalty.get();
|
||||
this.allowBreak = Baritone.settings().allowBreak.get();
|
||||
this.maxFallHeightNoWater = Baritone.settings().maxFallHeightNoWater.get();
|
||||
this.maxFallHeightBucket = Baritone.settings().maxFallHeightBucket.get();
|
||||
int depth = EnchantmentHelper.getDepthStriderModifier(player());
|
||||
int depth = EnchantmentHelper.getDepthStriderModifier(player);
|
||||
if (depth > 3) {
|
||||
depth = 3;
|
||||
}
|
||||
@@ -70,7 +82,23 @@ public class CalculationContext implements Helper {
|
||||
// why cache these things here, why not let the movements just get directly from settings?
|
||||
// because if some movements are calculated one way and others are calculated another way,
|
||||
// then you get a wildly inconsistent path that isn't optimal for either scenario.
|
||||
this.worldBorder = new BetterWorldBorder(world().getWorldBorder());
|
||||
this.worldBorder = new BetterWorldBorder(world.getWorldBorder());
|
||||
}
|
||||
|
||||
public IBlockState get(int x, int y, int z) {
|
||||
return bsi.get0(x, y, z); // laughs maniacally
|
||||
}
|
||||
|
||||
public boolean isLoaded(int x, int z) {
|
||||
return bsi.isLoaded(x, z);
|
||||
}
|
||||
|
||||
public IBlockState get(BlockPos pos) {
|
||||
return get(pos.getX(), pos.getY(), pos.getZ());
|
||||
}
|
||||
|
||||
public Block getBlock(int x, int y, int z) {
|
||||
return get(x, y, z).getBlock();
|
||||
}
|
||||
|
||||
public boolean canPlaceThrowawayAt(int x, int y, int z) {
|
||||
@@ -95,6 +123,22 @@ public class CalculationContext implements Helper {
|
||||
return false;
|
||||
}
|
||||
|
||||
public World world() {
|
||||
return world;
|
||||
}
|
||||
|
||||
public EntityPlayerSP player() {
|
||||
return player;
|
||||
}
|
||||
|
||||
public BlockStateInterface bsi() {
|
||||
return bsi;
|
||||
}
|
||||
|
||||
public WorldData worldData() {
|
||||
return worldData;
|
||||
}
|
||||
|
||||
public ToolSet getToolSet() {
|
||||
return toolSet;
|
||||
}
|
||||
|
||||
@@ -20,22 +20,18 @@ package baritone.pathing.movement;
|
||||
import baritone.Baritone;
|
||||
import baritone.api.pathing.movement.IMovement;
|
||||
import baritone.api.pathing.movement.MovementStatus;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.api.utils.Rotation;
|
||||
import baritone.api.utils.RotationUtils;
|
||||
import baritone.api.utils.VecUtils;
|
||||
import baritone.utils.BlockBreakHelper;
|
||||
import baritone.api.utils.*;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.InputOverrideHandler;
|
||||
import net.minecraft.block.BlockLiquid;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.world.chunk.EmptyChunk;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import static baritone.utils.InputOverrideHandler.Input;
|
||||
@@ -60,8 +56,6 @@ public abstract class Movement implements IMovement, Helper, MovementHelper {
|
||||
*/
|
||||
protected final BetterBlockPos positionToPlace;
|
||||
|
||||
private boolean didBreakLastTick;
|
||||
|
||||
private Double cost;
|
||||
|
||||
public List<BlockPos> toBreakCached = null;
|
||||
@@ -97,7 +91,7 @@ public abstract class Movement implements IMovement, Helper, MovementHelper {
|
||||
return getCost();
|
||||
}
|
||||
|
||||
protected void override(double cost) {
|
||||
public void override(double cost) {
|
||||
this.cost = cost;
|
||||
}
|
||||
|
||||
@@ -115,52 +109,31 @@ public abstract class Movement implements IMovement, Helper, MovementHelper {
|
||||
@Override
|
||||
public MovementStatus update() {
|
||||
player().capabilities.isFlying = false;
|
||||
MovementState latestState = updateState(currentState);
|
||||
if (BlockStateInterface.isLiquid(playerFeet())) {
|
||||
latestState.setInput(Input.JUMP, true);
|
||||
currentState = updateState(currentState);
|
||||
if (MovementHelper.isLiquid(playerFeet())) {
|
||||
currentState.setInput(Input.JUMP, true);
|
||||
}
|
||||
if (player().isEntityInsideOpaqueBlock()) {
|
||||
latestState.setInput(Input.CLICK_LEFT, true);
|
||||
currentState.setInput(Input.CLICK_LEFT, true);
|
||||
}
|
||||
|
||||
// If the movement target has to force the new rotations, or we aren't using silent move, then force the rotations
|
||||
latestState.getTarget().getRotation().ifPresent(rotation ->
|
||||
currentState.getTarget().getRotation().ifPresent(rotation ->
|
||||
Baritone.INSTANCE.getLookBehavior().updateTarget(
|
||||
rotation,
|
||||
latestState.getTarget().hasToForceRotations()));
|
||||
currentState.getTarget().hasToForceRotations()));
|
||||
|
||||
// TODO: calculate movement inputs from latestState.getGoal().position
|
||||
// latestState.getTarget().position.ifPresent(null); NULL CONSUMER REALLY SHOULDN'T BE THE FINAL THING YOU SHOULD REALLY REPLACE THIS WITH ALMOST ACTUALLY ANYTHING ELSE JUST PLEASE DON'T LEAVE IT AS IT IS THANK YOU KANYE
|
||||
|
||||
this.didBreakLastTick = false;
|
||||
|
||||
latestState.getInputStates().forEach((input, forced) -> {
|
||||
if (Baritone.settings().leftClickWorkaround.get()) {
|
||||
RayTraceResult trace = mc.objectMouseOver;
|
||||
boolean isBlockTrace = trace != null && trace.typeOfHit == RayTraceResult.Type.BLOCK;
|
||||
boolean isLeftClick = forced && input == Input.CLICK_LEFT;
|
||||
|
||||
// If we're forcing left click, we're in a gui screen, and we're looking
|
||||
// at a block, break the block without a direct game input manipulation.
|
||||
if (mc.currentScreen != null && isLeftClick && isBlockTrace) {
|
||||
BlockBreakHelper.tryBreakBlock(trace.getBlockPos(), trace.sideHit);
|
||||
this.didBreakLastTick = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
currentState.getInputStates().forEach((input, forced) -> {
|
||||
Baritone.INSTANCE.getInputOverrideHandler().setInputForceState(input, forced);
|
||||
});
|
||||
latestState.getInputStates().replaceAll((input, forced) -> false);
|
||||
|
||||
if (!this.didBreakLastTick) {
|
||||
BlockBreakHelper.stopBreakingBlock();
|
||||
}
|
||||
|
||||
currentState = latestState;
|
||||
currentState.getInputStates().replaceAll((input, forced) -> false);
|
||||
|
||||
// If the current status indicates a completed movement
|
||||
if (currentState.getStatus().isComplete()) {
|
||||
onFinish(latestState);
|
||||
Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys();
|
||||
}
|
||||
|
||||
return currentState.getStatus();
|
||||
@@ -174,10 +147,13 @@ public abstract class Movement implements IMovement, Helper, MovementHelper {
|
||||
for (BetterBlockPos blockPos : positionsToBreak) {
|
||||
if (!MovementHelper.canWalkThrough(blockPos) && !(BlockStateInterface.getBlock(blockPos) instanceof BlockLiquid)) { // can't break liquid, so don't try
|
||||
somethingInTheWay = true;
|
||||
Optional<Rotation> reachable = RotationUtils.reachable(player(), blockPos);
|
||||
Optional<Rotation> reachable = RotationUtils.reachable(player(), blockPos, playerController().getBlockReachDistance());
|
||||
if (reachable.isPresent()) {
|
||||
MovementHelper.switchToBestToolFor(BlockStateInterface.get(blockPos));
|
||||
state.setTarget(new MovementState.MovementTarget(reachable.get(), true)).setInput(Input.CLICK_LEFT, true);
|
||||
state.setTarget(new MovementState.MovementTarget(reachable.get(), true));
|
||||
if (Objects.equals(RayTraceUtils.getSelectedBlock().orElse(null), blockPos)) {
|
||||
state.setInput(Input.CLICK_LEFT, true);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
//get rekt minecraft
|
||||
@@ -186,7 +162,9 @@ public abstract class Movement implements IMovement, Helper, MovementHelper {
|
||||
//you dont own me!!!!
|
||||
state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(player().getPositionEyes(1.0F),
|
||||
VecUtils.getBlockPosCenter(blockPos)), true)
|
||||
).setInput(InputOverrideHandler.Input.CLICK_LEFT, true);
|
||||
);
|
||||
// don't check selectedblock on this one, this is a fallback when we can't see any face directly, it's intended to be breaking the "incorrect" block
|
||||
state.setInput(InputOverrideHandler.Input.CLICK_LEFT, true);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -218,20 +196,6 @@ public abstract class Movement implements IMovement, Helper, MovementHelper {
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run cleanup on state finish and declare success.
|
||||
*/
|
||||
public void onFinish(MovementState state) {
|
||||
state.getInputStates().replaceAll((input, forced) -> false);
|
||||
state.getInputStates().forEach((input, forced) -> Baritone.INSTANCE.getInputOverrideHandler().setInputForceState(input, forced));
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
currentState.getInputStates().replaceAll((input, forced) -> false);
|
||||
currentState.getInputStates().forEach((input, forced) -> Baritone.INSTANCE.getInputOverrideHandler().setInputForceState(input, forced));
|
||||
currentState.setStatus(MovementStatus.CANCELED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
currentState = new MovementState().setStatus(MovementStatus.PREPPING);
|
||||
@@ -262,8 +226,8 @@ public abstract class Movement implements IMovement, Helper, MovementHelper {
|
||||
return getDest().subtract(getSrc());
|
||||
}
|
||||
|
||||
public void checkLoadedChunk() {
|
||||
calculatedWhileLoaded = !(world().getChunk(getDest()) instanceof EmptyChunk);
|
||||
public void checkLoadedChunk(CalculationContext context) {
|
||||
calculatedWhileLoaded = !(context.world().getChunk(getDest()) instanceof EmptyChunk);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -28,7 +28,6 @@ import baritone.utils.ToolSet;
|
||||
import net.minecraft.block.*;
|
||||
import net.minecraft.block.properties.PropertyBool;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.item.ItemPickaxe;
|
||||
@@ -45,16 +44,16 @@ import net.minecraft.world.chunk.EmptyChunk;
|
||||
*/
|
||||
public interface MovementHelper extends ActionCosts, Helper {
|
||||
|
||||
static boolean avoidBreaking(int x, int y, int z, IBlockState state) {
|
||||
static boolean avoidBreaking(CalculationContext context, int x, int y, int z, IBlockState state) {
|
||||
Block b = state.getBlock();
|
||||
return b == Blocks.ICE // ice becomes water, and water can mess up the path
|
||||
|| b instanceof BlockSilverfish // obvious reasons
|
||||
// call BlockStateInterface.get directly with x,y,z. no need to make 5 new BlockPos for no reason
|
||||
|| BlockStateInterface.get(x, y + 1, z).getBlock() instanceof BlockLiquid//don't break anything touching liquid on any side
|
||||
|| BlockStateInterface.get(x + 1, y, z).getBlock() instanceof BlockLiquid
|
||||
|| BlockStateInterface.get(x - 1, y, z).getBlock() instanceof BlockLiquid
|
||||
|| BlockStateInterface.get(x, y, z + 1).getBlock() instanceof BlockLiquid
|
||||
|| BlockStateInterface.get(x, y, z - 1).getBlock() instanceof BlockLiquid;
|
||||
// call context.get directly with x,y,z. no need to make 5 new BlockPos for no reason
|
||||
|| context.get(x, y + 1, z).getBlock() instanceof BlockLiquid//don't break anything touching liquid on any side
|
||||
|| context.get(x + 1, y, z).getBlock() instanceof BlockLiquid
|
||||
|| context.get(x - 1, y, z).getBlock() instanceof BlockLiquid
|
||||
|| context.get(x, y, z + 1).getBlock() instanceof BlockLiquid
|
||||
|| context.get(x, y, z - 1).getBlock() instanceof BlockLiquid;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -64,14 +63,14 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
* @return
|
||||
*/
|
||||
static boolean canWalkThrough(BetterBlockPos pos) {
|
||||
return canWalkThrough(pos.x, pos.y, pos.z, BlockStateInterface.get(pos));
|
||||
return canWalkThrough(new CalculationContext(), pos.x, pos.y, pos.z, BlockStateInterface.get(pos));
|
||||
}
|
||||
|
||||
static boolean canWalkThrough(int x, int y, int z) {
|
||||
return canWalkThrough(x, y, z, BlockStateInterface.get(x, y, z));
|
||||
static boolean canWalkThrough(CalculationContext context, int x, int y, int z) {
|
||||
return canWalkThrough(context, x, y, z, context.get(x, y, z));
|
||||
}
|
||||
|
||||
static boolean canWalkThrough(int x, int y, int z, IBlockState state) {
|
||||
static boolean canWalkThrough(CalculationContext context, int x, int y, int z, IBlockState state) {
|
||||
Block block = state.getBlock();
|
||||
if (block == Blocks.AIR) { // early return for most common case
|
||||
return true;
|
||||
@@ -105,14 +104,14 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
}
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
if (BlockStateInterface.isFlowing(state)) {
|
||||
if (isFlowing(state)) {
|
||||
return false; // Don't walk through flowing liquids
|
||||
}
|
||||
if (block instanceof BlockLiquid) {
|
||||
if (Baritone.settings().assumeWalkOnWater.get()) {
|
||||
return false;
|
||||
}
|
||||
IBlockState up = BlockStateInterface.get(x, y + 1, z);
|
||||
IBlockState up = context.get(x, y + 1, z);
|
||||
if (up.getBlock() instanceof BlockLiquid || up.getBlock() instanceof BlockLilyPad) {
|
||||
return false;
|
||||
}
|
||||
@@ -130,8 +129,8 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
static boolean fullyPassable(int x, int y, int z) {
|
||||
return fullyPassable(BlockStateInterface.get(x, y, z));
|
||||
static boolean fullyPassable(CalculationContext context, int x, int y, int z) {
|
||||
return fullyPassable(context.get(x, y, z));
|
||||
}
|
||||
|
||||
static boolean fullyPassable(IBlockState state) {
|
||||
@@ -246,7 +245,7 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
static boolean canWalkOn(int x, int y, int z, IBlockState state) {
|
||||
static boolean canWalkOn(CalculationContext context, int x, int y, int z, IBlockState state) {
|
||||
Block block = state.getBlock();
|
||||
if (block == Blocks.AIR || block == Blocks.MAGMA) {
|
||||
// early return for most common case (air)
|
||||
@@ -254,9 +253,6 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
return false;
|
||||
}
|
||||
if (state.isBlockNormalCube()) {
|
||||
if (BlockStateInterface.isLava(block) || BlockStateInterface.isWater(block)) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (block == Blocks.LADDER || (block == Blocks.VINE && Baritone.settings().allowVines.get())) { // TODO reconsider this
|
||||
@@ -268,20 +264,20 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
if (block == Blocks.ENDER_CHEST || block == Blocks.CHEST) {
|
||||
return true;
|
||||
}
|
||||
if (BlockStateInterface.isWater(block)) {
|
||||
if (isWater(block)) {
|
||||
// since this is called literally millions of times per second, the benefit of not allocating millions of useless "pos.up()"
|
||||
// BlockPos s that we'd just garbage collect immediately is actually noticeable. I don't even think its a decrease in readability
|
||||
Block up = BlockStateInterface.get(x, y + 1, z).getBlock();
|
||||
Block up = context.get(x, y + 1, z).getBlock();
|
||||
if (up == Blocks.WATERLILY) {
|
||||
return true;
|
||||
}
|
||||
if (BlockStateInterface.isFlowing(state) || block == Blocks.FLOWING_WATER) {
|
||||
if (isFlowing(state) || block == Blocks.FLOWING_WATER) {
|
||||
// the only scenario in which we can walk on flowing water is if it's under still water with jesus off
|
||||
return BlockStateInterface.isWater(up) && !Baritone.settings().assumeWalkOnWater.get();
|
||||
return isWater(up) && !Baritone.settings().assumeWalkOnWater.get();
|
||||
}
|
||||
// if assumeWalkOnWater is on, we can only walk on water if there isn't water above it
|
||||
// if assumeWalkOnWater is off, we can only walk on water if there is water above it
|
||||
return BlockStateInterface.isWater(up) ^ Baritone.settings().assumeWalkOnWater.get();
|
||||
return isWater(up) ^ Baritone.settings().assumeWalkOnWater.get();
|
||||
}
|
||||
if (block instanceof BlockGlass || block instanceof BlockStainedGlass) {
|
||||
return true;
|
||||
@@ -299,19 +295,19 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
}
|
||||
|
||||
static boolean canWalkOn(BetterBlockPos pos, IBlockState state) {
|
||||
return canWalkOn(pos.x, pos.y, pos.z, state);
|
||||
return canWalkOn(new CalculationContext(), pos.x, pos.y, pos.z, state);
|
||||
}
|
||||
|
||||
static boolean canWalkOn(BetterBlockPos pos) {
|
||||
return canWalkOn(pos.x, pos.y, pos.z, BlockStateInterface.get(pos));
|
||||
return canWalkOn(new CalculationContext(), pos.x, pos.y, pos.z, BlockStateInterface.get(pos));
|
||||
}
|
||||
|
||||
static boolean canWalkOn(int x, int y, int z) {
|
||||
return canWalkOn(x, y, z, BlockStateInterface.get(x, y, z));
|
||||
static boolean canWalkOn(CalculationContext context, int x, int y, int z) {
|
||||
return canWalkOn(context, x, y, z, context.get(x, y, z));
|
||||
}
|
||||
|
||||
static boolean canPlaceAgainst(int x, int y, int z) {
|
||||
return canPlaceAgainst(BlockStateInterface.get(x, y, z));
|
||||
static boolean canPlaceAgainst(CalculationContext context, int x, int y, int z) {
|
||||
return canPlaceAgainst(context.get(x, y, z));
|
||||
}
|
||||
|
||||
static boolean canPlaceAgainst(BlockPos pos) {
|
||||
@@ -324,16 +320,16 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
}
|
||||
|
||||
static double getMiningDurationTicks(CalculationContext context, int x, int y, int z, boolean includeFalling) {
|
||||
return getMiningDurationTicks(context, x, y, z, BlockStateInterface.get(x, y, z), includeFalling);
|
||||
return getMiningDurationTicks(context, x, y, z, context.get(x, y, z), includeFalling);
|
||||
}
|
||||
|
||||
static double getMiningDurationTicks(CalculationContext context, int x, int y, int z, IBlockState state, boolean includeFalling) {
|
||||
Block block = state.getBlock();
|
||||
if (!canWalkThrough(x, y, z, state)) {
|
||||
if (!canWalkThrough(context, x, y, z, state)) {
|
||||
if (!context.canBreakAt(x, y, z)) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (avoidBreaking(x, y, z, state)) {
|
||||
if (avoidBreaking(context, x, y, z, state)) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (block instanceof BlockLiquid) {
|
||||
@@ -348,7 +344,7 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
double result = m / strVsBlock;
|
||||
result += context.breakBlockAdditionalCost();
|
||||
if (includeFalling) {
|
||||
IBlockState above = BlockStateInterface.get(x, y + 1, z);
|
||||
IBlockState above = context.get(x, y + 1, z);
|
||||
if (above.getBlock() instanceof BlockFalling) {
|
||||
result += getMiningDurationTicks(context, x, y + 1, z, above, true);
|
||||
}
|
||||
@@ -364,10 +360,6 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
&& state.getValue(BlockSlab.HALF) == BlockSlab.EnumBlockHalf.BOTTOM;
|
||||
}
|
||||
|
||||
static boolean isBottomSlab(BlockPos pos) {
|
||||
return isBottomSlab(BlockStateInterface.get(pos));
|
||||
}
|
||||
|
||||
/**
|
||||
* AutoTool
|
||||
*/
|
||||
@@ -387,7 +379,7 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
* @param b the blockstate to mine
|
||||
*/
|
||||
static void switchToBestToolFor(IBlockState b) {
|
||||
switchToBestToolFor(b, new ToolSet());
|
||||
switchToBestToolFor(b, new ToolSet(Helper.HELPER.player()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -397,11 +389,11 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
* @param ts previously calculated ToolSet
|
||||
*/
|
||||
static void switchToBestToolFor(IBlockState b, ToolSet ts) {
|
||||
mc.player.inventory.currentItem = ts.getBestSlot(b.getBlock());
|
||||
Helper.HELPER.player().inventory.currentItem = ts.getBestSlot(b.getBlock());
|
||||
}
|
||||
|
||||
static boolean throwaway(boolean select) {
|
||||
EntityPlayerSP p = Minecraft.getMinecraft().player;
|
||||
EntityPlayerSP p = Helper.HELPER.player();
|
||||
NonNullList<ItemStack> inv = p.inventory.mainInventory;
|
||||
for (byte i = 0; i < 9; i++) {
|
||||
ItemStack item = inv.get(i);
|
||||
@@ -437,11 +429,55 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
}
|
||||
|
||||
static void moveTowards(MovementState state, BlockPos pos) {
|
||||
EntityPlayerSP player = Helper.HELPER.player();
|
||||
state.setTarget(new MovementTarget(
|
||||
new Rotation(RotationUtils.calcRotationFromVec3d(mc.player.getPositionEyes(1.0F),
|
||||
new Rotation(RotationUtils.calcRotationFromVec3d(player.getPositionEyes(1.0F),
|
||||
VecUtils.getBlockPosCenter(pos),
|
||||
new Rotation(mc.player.rotationYaw, mc.player.rotationPitch)).getYaw(), mc.player.rotationPitch),
|
||||
new Rotation(player.rotationYaw, player.rotationPitch)).getYaw(), player.rotationPitch),
|
||||
false
|
||||
)).setInput(InputOverrideHandler.Input.MOVE_FORWARD, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the specified block is
|
||||
* water, regardless of whether or not it is flowing.
|
||||
*
|
||||
* @param b The block
|
||||
* @return Whether or not the block is water
|
||||
*/
|
||||
static boolean isWater(Block b) {
|
||||
return b == Blocks.FLOWING_WATER || b == Blocks.WATER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the block at the specified pos is
|
||||
* water, regardless of whether or not it is flowing.
|
||||
*
|
||||
* @param bp The block pos
|
||||
* @return Whether or not the block is water
|
||||
*/
|
||||
static boolean isWater(BlockPos bp) {
|
||||
return isWater(BlockStateInterface.getBlock(bp));
|
||||
}
|
||||
|
||||
static boolean isLava(Block b) {
|
||||
return b == Blocks.FLOWING_LAVA || b == Blocks.LAVA;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the specified pos has a liquid
|
||||
*
|
||||
* @param p The pos
|
||||
* @return Whether or not the block is a liquid
|
||||
*/
|
||||
static boolean isLiquid(BlockPos p) {
|
||||
return BlockStateInterface.getBlock(p) instanceof BlockLiquid;
|
||||
}
|
||||
|
||||
static boolean isFlowing(IBlockState state) {
|
||||
// Will be IFluidState in 1.13
|
||||
return state.getBlock() instanceof BlockLiquid
|
||||
&& state.getPropertyKeys().contains(BlockLiquid.LEVEL)
|
||||
&& state.getValue(BlockLiquid.LEVEL) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ import net.minecraft.util.EnumFacing;
|
||||
public enum Moves {
|
||||
DOWNWARD(0, -1, 0) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return new MovementDownward(src, src.down());
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ public enum Moves {
|
||||
|
||||
PILLAR(0, +1, 0) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return new MovementPillar(src, src.up());
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ public enum Moves {
|
||||
|
||||
TRAVERSE_NORTH(0, 0, -1) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return new MovementTraverse(src, src.north());
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ public enum Moves {
|
||||
|
||||
TRAVERSE_SOUTH(0, 0, +1) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return new MovementTraverse(src, src.south());
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ public enum Moves {
|
||||
|
||||
TRAVERSE_EAST(+1, 0, 0) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return new MovementTraverse(src, src.east());
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ public enum Moves {
|
||||
|
||||
TRAVERSE_WEST(-1, 0, 0) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return new MovementTraverse(src, src.west());
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ public enum Moves {
|
||||
|
||||
ASCEND_NORTH(0, +1, -1) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return new MovementAscend(src, new BetterBlockPos(src.x, src.y + 1, src.z - 1));
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ public enum Moves {
|
||||
|
||||
ASCEND_SOUTH(0, +1, +1) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return new MovementAscend(src, new BetterBlockPos(src.x, src.y + 1, src.z + 1));
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ public enum Moves {
|
||||
|
||||
ASCEND_EAST(+1, +1, 0) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return new MovementAscend(src, new BetterBlockPos(src.x + 1, src.y + 1, src.z));
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ public enum Moves {
|
||||
|
||||
ASCEND_WEST(-1, +1, 0) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return new MovementAscend(src, new BetterBlockPos(src.x - 1, src.y + 1, src.z));
|
||||
}
|
||||
|
||||
@@ -150,9 +150,9 @@ public enum Moves {
|
||||
|
||||
DESCEND_EAST(+1, -1, 0, false, true) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
MutableMoveResult res = new MutableMoveResult();
|
||||
apply(new CalculationContext(), src.x, src.y, src.z, res);
|
||||
apply(context, src.x, src.y, src.z, res);
|
||||
if (res.y == src.y - 1) {
|
||||
return new MovementDescend(src, new BetterBlockPos(res.x, res.y, res.z));
|
||||
} else {
|
||||
@@ -168,9 +168,9 @@ public enum Moves {
|
||||
|
||||
DESCEND_WEST(-1, -1, 0, false, true) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
MutableMoveResult res = new MutableMoveResult();
|
||||
apply(new CalculationContext(), src.x, src.y, src.z, res);
|
||||
apply(context, src.x, src.y, src.z, res);
|
||||
if (res.y == src.y - 1) {
|
||||
return new MovementDescend(src, new BetterBlockPos(res.x, res.y, res.z));
|
||||
} else {
|
||||
@@ -186,9 +186,9 @@ public enum Moves {
|
||||
|
||||
DESCEND_NORTH(0, -1, -1, false, true) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
MutableMoveResult res = new MutableMoveResult();
|
||||
apply(new CalculationContext(), src.x, src.y, src.z, res);
|
||||
apply(context, src.x, src.y, src.z, res);
|
||||
if (res.y == src.y - 1) {
|
||||
return new MovementDescend(src, new BetterBlockPos(res.x, res.y, res.z));
|
||||
} else {
|
||||
@@ -204,9 +204,9 @@ public enum Moves {
|
||||
|
||||
DESCEND_SOUTH(0, -1, +1, false, true) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
MutableMoveResult res = new MutableMoveResult();
|
||||
apply(new CalculationContext(), src.x, src.y, src.z, res);
|
||||
apply(context, src.x, src.y, src.z, res);
|
||||
if (res.y == src.y - 1) {
|
||||
return new MovementDescend(src, new BetterBlockPos(res.x, res.y, res.z));
|
||||
} else {
|
||||
@@ -222,7 +222,7 @@ public enum Moves {
|
||||
|
||||
DIAGONAL_NORTHEAST(+1, 0, -1) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return new MovementDiagonal(src, EnumFacing.NORTH, EnumFacing.EAST);
|
||||
}
|
||||
|
||||
@@ -234,7 +234,7 @@ public enum Moves {
|
||||
|
||||
DIAGONAL_NORTHWEST(-1, 0, -1) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return new MovementDiagonal(src, EnumFacing.NORTH, EnumFacing.WEST);
|
||||
}
|
||||
|
||||
@@ -246,7 +246,7 @@ public enum Moves {
|
||||
|
||||
DIAGONAL_SOUTHEAST(+1, 0, +1) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return new MovementDiagonal(src, EnumFacing.SOUTH, EnumFacing.EAST);
|
||||
}
|
||||
|
||||
@@ -258,7 +258,7 @@ public enum Moves {
|
||||
|
||||
DIAGONAL_SOUTHWEST(-1, 0, +1) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return new MovementDiagonal(src, EnumFacing.SOUTH, EnumFacing.WEST);
|
||||
}
|
||||
|
||||
@@ -270,8 +270,8 @@ public enum Moves {
|
||||
|
||||
PARKOUR_NORTH(0, 0, -4, true, false) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
return MovementParkour.cost(new CalculationContext(), src, EnumFacing.NORTH);
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return MovementParkour.cost(context, src, EnumFacing.NORTH);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -282,8 +282,8 @@ public enum Moves {
|
||||
|
||||
PARKOUR_SOUTH(0, 0, +4, true, false) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
return MovementParkour.cost(new CalculationContext(), src, EnumFacing.SOUTH);
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return MovementParkour.cost(context, src, EnumFacing.SOUTH);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -294,8 +294,8 @@ public enum Moves {
|
||||
|
||||
PARKOUR_EAST(+4, 0, 0, true, false) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
return MovementParkour.cost(new CalculationContext(), src, EnumFacing.EAST);
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return MovementParkour.cost(context, src, EnumFacing.EAST);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -306,8 +306,8 @@ public enum Moves {
|
||||
|
||||
PARKOUR_WEST(-4, 0, 0, true, false) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
return MovementParkour.cost(new CalculationContext(), src, EnumFacing.WEST);
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return MovementParkour.cost(context, src, EnumFacing.WEST);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -335,7 +335,7 @@ public enum Moves {
|
||||
this(x, y, z, false, false);
|
||||
}
|
||||
|
||||
public abstract Movement apply0(BetterBlockPos src);
|
||||
public abstract Movement apply0(CalculationContext context, BetterBlockPos src);
|
||||
|
||||
public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) {
|
||||
if (dynamicXZ || dynamicY) {
|
||||
|
||||
@@ -58,24 +58,24 @@ public class MovementAscend extends Movement {
|
||||
}
|
||||
|
||||
public static double cost(CalculationContext context, int x, int y, int z, int destX, int destZ) {
|
||||
IBlockState srcDown = BlockStateInterface.get(x, y - 1, z);
|
||||
IBlockState srcDown = context.get(x, y - 1, z);
|
||||
if (srcDown.getBlock() == Blocks.LADDER || srcDown.getBlock() == Blocks.VINE) {
|
||||
return COST_INF;
|
||||
}
|
||||
// we can jump from soul sand, but not from a bottom slab
|
||||
boolean jumpingFromBottomSlab = MovementHelper.isBottomSlab(srcDown);
|
||||
IBlockState toPlace = BlockStateInterface.get(destX, y, destZ);
|
||||
IBlockState toPlace = context.get(destX, y, destZ);
|
||||
boolean jumpingToBottomSlab = MovementHelper.isBottomSlab(toPlace);
|
||||
|
||||
if (jumpingFromBottomSlab && !jumpingToBottomSlab) {
|
||||
return COST_INF;// the only thing we can ascend onto from a bottom slab is another bottom slab
|
||||
}
|
||||
boolean hasToPlace = false;
|
||||
if (!MovementHelper.canWalkOn(destX, y, destZ, toPlace)) {
|
||||
if (!MovementHelper.canWalkOn(context, destX, y, destZ, toPlace)) {
|
||||
if (!context.canPlaceThrowawayAt(destX, y, destZ)) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (toPlace.getBlock() != Blocks.AIR && !BlockStateInterface.isWater(toPlace.getBlock()) && !MovementHelper.isReplacable(destX, y, destZ, toPlace)) {
|
||||
if (toPlace.getBlock() != Blocks.AIR && !MovementHelper.isWater(toPlace.getBlock()) && !MovementHelper.isReplacable(destX, y, destZ, toPlace)) {
|
||||
return COST_INF;
|
||||
}
|
||||
// TODO: add ability to place against .down() as well as the cardinal directions
|
||||
@@ -87,7 +87,7 @@ public class MovementAscend extends Movement {
|
||||
if (againstX == x && againstZ == z) {
|
||||
continue;
|
||||
}
|
||||
if (MovementHelper.canPlaceAgainst(againstX, y, againstZ)) {
|
||||
if (MovementHelper.canPlaceAgainst(context, againstX, y, againstZ)) {
|
||||
hasToPlace = true;
|
||||
break;
|
||||
}
|
||||
@@ -97,7 +97,7 @@ public class MovementAscend extends Movement {
|
||||
}
|
||||
}
|
||||
IBlockState srcUp2 = null;
|
||||
if (BlockStateInterface.get(x, y + 3, z).getBlock() instanceof BlockFalling && (MovementHelper.canWalkThrough(x, y + 1, z) || !((srcUp2 = BlockStateInterface.get(x, y + 2, z)).getBlock() instanceof BlockFalling))) {//it would fall on us and possibly suffocate us
|
||||
if (context.get(x, y + 3, z).getBlock() instanceof BlockFalling && (MovementHelper.canWalkThrough(context, x, y + 1, z) || !((srcUp2 = context.get(x, y + 2, z)).getBlock() instanceof BlockFalling))) {//it would fall on us and possibly suffocate us
|
||||
// HOWEVER, we assume that we're standing in the start position
|
||||
// that means that src and src.up(1) are both air
|
||||
// maybe they aren't now, but they will be by the time this starts
|
||||
@@ -138,7 +138,7 @@ public class MovementAscend extends Movement {
|
||||
totalCost += context.placeBlockCost();
|
||||
}
|
||||
if (srcUp2 == null) {
|
||||
srcUp2 = BlockStateInterface.get(x, y + 2, z);
|
||||
srcUp2 = context.get(x, y + 2, z);
|
||||
}
|
||||
totalCost += MovementHelper.getMiningDurationTicks(context, x, y + 2, z, srcUp2, false); // TODO MAKE ABSOLUTELY SURE we don't need includeFalling here, from the falling check above
|
||||
if (totalCost >= COST_INF) {
|
||||
@@ -204,7 +204,7 @@ public class MovementAscend extends Movement {
|
||||
return state.setStatus(MovementStatus.UNREACHABLE);
|
||||
}
|
||||
MovementHelper.moveTowards(state, dest);
|
||||
if (MovementHelper.isBottomSlab(jumpingOnto) && !MovementHelper.isBottomSlab(src.down())) {
|
||||
if (MovementHelper.isBottomSlab(jumpingOnto) && !MovementHelper.isBottomSlab(BlockStateInterface.get(src.down()))) {
|
||||
return state; // don't jump while walking from a non double slab into a bottom slab
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.pathing.movement.MovementState;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.InputOverrideHandler;
|
||||
import baritone.utils.pathing.MutableMoveResult;
|
||||
import net.minecraft.block.Block;
|
||||
@@ -58,13 +57,13 @@ public class MovementDescend extends Movement {
|
||||
}
|
||||
|
||||
public static void cost(CalculationContext context, int x, int y, int z, int destX, int destZ, MutableMoveResult res) {
|
||||
Block fromDown = BlockStateInterface.get(x, y - 1, z).getBlock();
|
||||
Block fromDown = context.get(x, y - 1, z).getBlock();
|
||||
if (fromDown == Blocks.LADDER || fromDown == Blocks.VINE) {
|
||||
return;
|
||||
}
|
||||
|
||||
double totalCost = 0;
|
||||
IBlockState destDown = BlockStateInterface.get(destX, y - 1, destZ);
|
||||
IBlockState destDown = context.get(destX, y - 1, destZ);
|
||||
totalCost += MovementHelper.getMiningDurationTicks(context, destX, y - 1, destZ, destDown, false);
|
||||
if (totalCost >= COST_INF) {
|
||||
return;
|
||||
@@ -88,8 +87,8 @@ public class MovementDescend extends Movement {
|
||||
//A is plausibly breakable by either descend or fall
|
||||
//C, D, etc determine the length of the fall
|
||||
|
||||
IBlockState below = BlockStateInterface.get(destX, y - 2, destZ);
|
||||
if (!MovementHelper.canWalkOn(destX, y - 2, destZ, below)) {
|
||||
IBlockState below = context.get(destX, y - 2, destZ);
|
||||
if (!MovementHelper.canWalkOn(context, destX, y - 2, destZ, below)) {
|
||||
dynamicFallCost(context, x, y, z, destX, destZ, totalCost, below, res);
|
||||
return;
|
||||
}
|
||||
@@ -112,13 +111,13 @@ public class MovementDescend extends Movement {
|
||||
}
|
||||
|
||||
public static void dynamicFallCost(CalculationContext context, int x, int y, int z, int destX, int destZ, double frontBreak, IBlockState below, MutableMoveResult res) {
|
||||
if (frontBreak != 0 && BlockStateInterface.get(destX, y + 2, destZ).getBlock() instanceof BlockFalling) {
|
||||
if (frontBreak != 0 && context.get(destX, y + 2, destZ).getBlock() instanceof BlockFalling) {
|
||||
// if frontBreak is 0 we can actually get through this without updating the falling block and making it actually fall
|
||||
// but if frontBreak is nonzero, we're breaking blocks in front, so don't let anything fall through this column,
|
||||
// and potentially replace the water we're going to fall into
|
||||
return;
|
||||
}
|
||||
if (!MovementHelper.canWalkThrough(destX, y - 2, destZ, below) && below.getBlock() != Blocks.WATER) {
|
||||
if (!MovementHelper.canWalkThrough(context, destX, y - 2, destZ, below) && below.getBlock() != Blocks.WATER) {
|
||||
return;
|
||||
}
|
||||
for (int fallHeight = 3; true; fallHeight++) {
|
||||
@@ -128,9 +127,9 @@ public class MovementDescend extends Movement {
|
||||
// this check prevents it from getting the block at y=-1 and crashing
|
||||
return;
|
||||
}
|
||||
IBlockState ontoBlock = BlockStateInterface.get(destX, newY, destZ);
|
||||
IBlockState ontoBlock = context.get(destX, newY, destZ);
|
||||
double tentativeCost = WALK_OFF_BLOCK_COST + FALL_N_BLOCKS_COST[fallHeight] + frontBreak;
|
||||
if (ontoBlock.getBlock() == Blocks.WATER && !BlockStateInterface.isFlowing(ontoBlock) && BlockStateInterface.getBlock(destX, newY + 1, destZ) != Blocks.WATERLILY) { // TODO flowing check required here?
|
||||
if (ontoBlock.getBlock() == Blocks.WATER && !MovementHelper.isFlowing(ontoBlock) && context.getBlock(destX, newY + 1, destZ) != Blocks.WATERLILY) { // TODO flowing check required here?
|
||||
// lilypads are canWalkThrough, but we can't end a fall that should be broken by water if it's covered by a lilypad
|
||||
// however, don't return impossible in the lilypad scenario, because we could still jump right on it (water that's below a lilypad is canWalkOn so it works)
|
||||
if (Baritone.settings().assumeWalkOnWater.get()) {
|
||||
@@ -146,10 +145,10 @@ public class MovementDescend extends Movement {
|
||||
if (ontoBlock.getBlock() == Blocks.FLOWING_WATER) {
|
||||
return;
|
||||
}
|
||||
if (MovementHelper.canWalkThrough(destX, newY, destZ, ontoBlock)) {
|
||||
if (MovementHelper.canWalkThrough(context, destX, newY, destZ, ontoBlock)) {
|
||||
continue;
|
||||
}
|
||||
if (!MovementHelper.canWalkOn(destX, newY, destZ, ontoBlock)) {
|
||||
if (!MovementHelper.canWalkOn(context, destX, newY, destZ, ontoBlock)) {
|
||||
return;
|
||||
}
|
||||
if (MovementHelper.isBottomSlab(ontoBlock)) {
|
||||
@@ -183,7 +182,7 @@ public class MovementDescend extends Movement {
|
||||
}
|
||||
|
||||
BlockPos playerFeet = playerFeet();
|
||||
if (playerFeet.equals(dest) && (BlockStateInterface.isLiquid(dest) || player().posY - playerFeet.getY() < 0.094)) { // lilypads
|
||||
if (playerFeet.equals(dest) && (MovementHelper.isLiquid(dest) || player().posY - playerFeet.getY() < 0.094)) { // lilypads
|
||||
// Wait until we're actually on the ground before saying we're done because sometimes we continue to fall if the next action starts immediately
|
||||
return state.setStatus(MovementStatus.SUCCESS);
|
||||
/* else {
|
||||
|
||||
@@ -23,7 +23,6 @@ import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.pathing.movement.MovementState;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.InputOverrideHandler;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
@@ -57,16 +56,16 @@ public class MovementDiagonal extends Movement {
|
||||
}
|
||||
|
||||
public static double cost(CalculationContext context, int x, int y, int z, int destX, int destZ) {
|
||||
Block fromDown = BlockStateInterface.get(x, y - 1, z).getBlock();
|
||||
Block fromDown = context.get(x, y - 1, z).getBlock();
|
||||
if (fromDown == Blocks.LADDER || fromDown == Blocks.VINE) {
|
||||
return COST_INF;
|
||||
}
|
||||
IBlockState destInto = BlockStateInterface.get(destX, y, destZ);
|
||||
if (!MovementHelper.canWalkThrough(destX, y, destZ, destInto) || !MovementHelper.canWalkThrough(destX, y + 1, destZ)) {
|
||||
IBlockState destInto = context.get(destX, y, destZ);
|
||||
if (!MovementHelper.canWalkThrough(context, destX, y, destZ, destInto) || !MovementHelper.canWalkThrough(context, destX, y + 1, destZ)) {
|
||||
return COST_INF;
|
||||
}
|
||||
IBlockState destWalkOn = BlockStateInterface.get(destX, y - 1, destZ);
|
||||
if (!MovementHelper.canWalkOn(destX, y - 1, destZ, destWalkOn)) {
|
||||
IBlockState destWalkOn = context.get(destX, y - 1, destZ);
|
||||
if (!MovementHelper.canWalkOn(context, destX, y - 1, destZ, destWalkOn)) {
|
||||
return COST_INF;
|
||||
}
|
||||
double multiplier = WALK_ONE_BLOCK_COST;
|
||||
@@ -77,16 +76,16 @@ public class MovementDiagonal extends Movement {
|
||||
if (fromDown == Blocks.SOUL_SAND) {
|
||||
multiplier += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2;
|
||||
}
|
||||
Block cuttingOver1 = BlockStateInterface.get(x, y - 1, destZ).getBlock();
|
||||
if (cuttingOver1 == Blocks.MAGMA || BlockStateInterface.isLava(cuttingOver1)) {
|
||||
Block cuttingOver1 = context.get(x, y - 1, destZ).getBlock();
|
||||
if (cuttingOver1 == Blocks.MAGMA || MovementHelper.isLava(cuttingOver1)) {
|
||||
return COST_INF;
|
||||
}
|
||||
Block cuttingOver2 = BlockStateInterface.get(destX, y - 1, z).getBlock();
|
||||
if (cuttingOver2 == Blocks.MAGMA || BlockStateInterface.isLava(cuttingOver2)) {
|
||||
Block cuttingOver2 = context.get(destX, y - 1, z).getBlock();
|
||||
if (cuttingOver2 == Blocks.MAGMA || MovementHelper.isLava(cuttingOver2)) {
|
||||
return COST_INF;
|
||||
}
|
||||
IBlockState pb0 = BlockStateInterface.get(x, y, destZ);
|
||||
IBlockState pb2 = BlockStateInterface.get(destX, y, z);
|
||||
IBlockState pb0 = context.get(x, y, destZ);
|
||||
IBlockState pb2 = context.get(destX, y, z);
|
||||
double optionA = MovementHelper.getMiningDurationTicks(context, x, y, destZ, pb0, false);
|
||||
double optionB = MovementHelper.getMiningDurationTicks(context, destX, y, z, pb2, false);
|
||||
if (optionA != 0 && optionB != 0) {
|
||||
@@ -94,13 +93,13 @@ public class MovementDiagonal extends Movement {
|
||||
// so no need to check pb1 as well, might as well return early here
|
||||
return COST_INF;
|
||||
}
|
||||
IBlockState pb1 = BlockStateInterface.get(x, y + 1, destZ);
|
||||
IBlockState pb1 = context.get(x, y + 1, destZ);
|
||||
optionA += MovementHelper.getMiningDurationTicks(context, x, y + 1, destZ, pb1, true);
|
||||
if (optionA != 0 && optionB != 0) {
|
||||
// same deal, if pb1 makes optionA nonzero and option B already was nonzero, pb3 can't affect the result
|
||||
return COST_INF;
|
||||
}
|
||||
IBlockState pb3 = BlockStateInterface.get(destX, y + 1, z);
|
||||
IBlockState pb3 = context.get(destX, y + 1, z);
|
||||
if (optionA == 0 && ((MovementHelper.avoidWalkingInto(pb2.getBlock()) && pb2.getBlock() != Blocks.WATER) || (MovementHelper.avoidWalkingInto(pb3.getBlock()) && pb3.getBlock() != Blocks.WATER))) {
|
||||
// at this point we're done calculating optionA, so we can check if it's actually possible to edge around in that direction
|
||||
return COST_INF;
|
||||
@@ -115,7 +114,7 @@ public class MovementDiagonal extends Movement {
|
||||
return COST_INF;
|
||||
}
|
||||
boolean water = false;
|
||||
if (BlockStateInterface.isWater(BlockStateInterface.getBlock(x, y, z)) || BlockStateInterface.isWater(destInto.getBlock())) {
|
||||
if (MovementHelper.isWater(context.getBlock(x, y, z)) || MovementHelper.isWater(destInto.getBlock())) {
|
||||
// Ignore previous multiplier
|
||||
// Whatever we were walking on (possibly soul sand) doesn't matter as we're actually floating on water
|
||||
// Not even touching the blocks below
|
||||
@@ -145,7 +144,7 @@ public class MovementDiagonal extends Movement {
|
||||
state.setStatus(MovementStatus.SUCCESS);
|
||||
return state;
|
||||
}
|
||||
if (!BlockStateInterface.isLiquid(playerFeet())) {
|
||||
if (!MovementHelper.isLiquid(playerFeet())) {
|
||||
state.setInput(InputOverrideHandler.Input.SPRINT, true);
|
||||
}
|
||||
MovementHelper.moveTowards(state, dest);
|
||||
|
||||
@@ -23,7 +23,6 @@ import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.pathing.movement.MovementState;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.init.Blocks;
|
||||
@@ -48,10 +47,10 @@ public class MovementDownward extends Movement {
|
||||
}
|
||||
|
||||
public static double cost(CalculationContext context, int x, int y, int z) {
|
||||
if (!MovementHelper.canWalkOn(x, y - 2, z)) {
|
||||
if (!MovementHelper.canWalkOn(context, x, y - 2, z)) {
|
||||
return COST_INF;
|
||||
}
|
||||
IBlockState d = BlockStateInterface.get(x, y - 1, z);
|
||||
IBlockState d = context.get(x, y - 1, z);
|
||||
Block td = d.getBlock();
|
||||
boolean ladder = td == Blocks.LADDER || td == Blocks.VINE;
|
||||
if (ladder) {
|
||||
|
||||
@@ -19,13 +19,15 @@ package baritone.pathing.movement.movements;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.pathing.movement.MovementStatus;
|
||||
import baritone.api.utils.*;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.api.utils.Rotation;
|
||||
import baritone.api.utils.RotationUtils;
|
||||
import baritone.api.utils.VecUtils;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.pathing.movement.MovementState;
|
||||
import baritone.pathing.movement.MovementState.MovementTarget;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.InputOverrideHandler;
|
||||
import baritone.utils.pathing.MutableMoveResult;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
@@ -63,18 +65,18 @@ public class MovementFall extends Movement {
|
||||
|
||||
BlockPos playerFeet = playerFeet();
|
||||
Rotation targetRotation = null;
|
||||
if (!BlockStateInterface.isWater(dest) && src.getY() - dest.getY() > Baritone.settings().maxFallHeightNoWater.get() && !playerFeet.equals(dest)) {
|
||||
if (!MovementHelper.isWater(dest) && src.getY() - dest.getY() > Baritone.settings().maxFallHeightNoWater.get() && !playerFeet.equals(dest)) {
|
||||
if (!InventoryPlayer.isHotbar(player().inventory.getSlotFor(STACK_BUCKET_WATER)) || world().provider.isNether()) {
|
||||
return state.setStatus(MovementStatus.UNREACHABLE);
|
||||
}
|
||||
|
||||
if (player().posY - dest.getY() < mc.playerController.getBlockReachDistance()) {
|
||||
if (player().posY - dest.getY() < playerController().getBlockReachDistance()) {
|
||||
player().inventory.currentItem = player().inventory.getSlotFor(STACK_BUCKET_WATER);
|
||||
|
||||
targetRotation = new Rotation(player().rotationYaw, 90.0F);
|
||||
|
||||
RayTraceResult trace = RayTraceUtils.simulateRayTrace(player().rotationYaw, 90.0F);
|
||||
if (trace != null && trace.typeOfHit == RayTraceResult.Type.BLOCK) {
|
||||
RayTraceResult trace = mc.objectMouseOver;
|
||||
if (trace != null && trace.typeOfHit == RayTraceResult.Type.BLOCK && player().rotationPitch > 89.0F) {
|
||||
state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true);
|
||||
}
|
||||
}
|
||||
@@ -84,8 +86,8 @@ public class MovementFall extends Movement {
|
||||
} else {
|
||||
state.setTarget(new MovementTarget(RotationUtils.calcRotationFromVec3d(playerHead(), VecUtils.getBlockPosCenter(dest)), false));
|
||||
}
|
||||
if (playerFeet.equals(dest) && (player().posY - playerFeet.getY() < 0.094 || BlockStateInterface.isWater(dest))) { // 0.094 because lilypads
|
||||
if (BlockStateInterface.isWater(dest)) {
|
||||
if (playerFeet.equals(dest) && (player().posY - playerFeet.getY() < 0.094 || MovementHelper.isWater(dest))) { // 0.094 because lilypads
|
||||
if (MovementHelper.isWater(dest)) {
|
||||
if (InventoryPlayer.isHotbar(player().inventory.getSlotFor(STACK_BUCKET_EMPTY))) {
|
||||
player().inventory.currentItem = player().inventory.getSlotFor(STACK_BUCKET_EMPTY);
|
||||
if (player().motionY >= 0) {
|
||||
|
||||
@@ -67,40 +67,50 @@ public class MovementParkour extends Movement {
|
||||
if (!Baritone.settings().allowParkour.get()) {
|
||||
return;
|
||||
}
|
||||
IBlockState standingOn = BlockStateInterface.get(x, y - 1, z);
|
||||
IBlockState standingOn = context.get(x, y - 1, z);
|
||||
if (standingOn.getBlock() == Blocks.VINE || standingOn.getBlock() == Blocks.LADDER || MovementHelper.isBottomSlab(standingOn)) {
|
||||
return;
|
||||
}
|
||||
int xDiff = dir.getXOffset();
|
||||
int zDiff = dir.getZOffset();
|
||||
IBlockState adj = BlockStateInterface.get(x + xDiff, y - 1, z + zDiff);
|
||||
IBlockState adj = context.get(x + xDiff, y - 1, z + zDiff);
|
||||
if (MovementHelper.avoidWalkingInto(adj.getBlock()) && adj.getBlock() != Blocks.WATER && adj.getBlock() != Blocks.FLOWING_WATER) { // magma sucks
|
||||
return;
|
||||
}
|
||||
if (MovementHelper.canWalkOn(x + xDiff, y - 1, z + zDiff, adj)) { // don't parkour if we could just traverse (for now)
|
||||
if (MovementHelper.canWalkOn(context,x + xDiff, y - 1, z + zDiff, adj)) { // don't parkour if we could just traverse (for now)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!MovementHelper.fullyPassable(x + xDiff, y, z + zDiff)) {
|
||||
if (!MovementHelper.fullyPassable(context,x + xDiff, y, z + zDiff)) {
|
||||
return;
|
||||
}
|
||||
if (!MovementHelper.fullyPassable(x + xDiff, y + 1, z + zDiff)) {
|
||||
if (!MovementHelper.fullyPassable(context,x + xDiff, y + 1, z + zDiff)) {
|
||||
return;
|
||||
}
|
||||
if (!MovementHelper.fullyPassable(x + xDiff, y + 2, z + zDiff)) {
|
||||
if (!MovementHelper.fullyPassable(context,x + xDiff, y + 2, z + zDiff)) {
|
||||
return;
|
||||
}
|
||||
if (!MovementHelper.fullyPassable(x, y + 2, z)) {
|
||||
if (!MovementHelper.fullyPassable(context,x, y + 2, z)) {
|
||||
return;
|
||||
}
|
||||
for (int i = 2; i <= (context.canSprint() ? 4 : 3); i++) {
|
||||
int maxJump;
|
||||
if (standingOn.getBlock() == Blocks.SOUL_SAND) {
|
||||
maxJump = 2; // 1 block gap
|
||||
} else {
|
||||
if (context.canSprint()) {
|
||||
maxJump = 4;
|
||||
} else {
|
||||
maxJump = 3;
|
||||
}
|
||||
}
|
||||
for (int i = 2; i <= maxJump; i++) {
|
||||
// TODO perhaps dest.up(3) doesn't need to be fullyPassable, just canWalkThrough, possibly?
|
||||
for (int y2 = 0; y2 < 4; y2++) {
|
||||
if (!MovementHelper.fullyPassable(x + xDiff * i, y + y2, z + zDiff * i)) {
|
||||
if (!MovementHelper.fullyPassable(context,x + xDiff * i, y + y2, z + zDiff * i)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (MovementHelper.canWalkOn(x + xDiff * i, y - 1, z + zDiff * i)) {
|
||||
if (MovementHelper.canWalkOn(context,x + xDiff * i, y - 1, z + zDiff * i)) {
|
||||
res.x = x + xDiff * i;
|
||||
res.y = y;
|
||||
res.z = z + zDiff * i;
|
||||
@@ -108,7 +118,7 @@ public class MovementParkour extends Movement {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!context.canSprint()) {
|
||||
if (maxJump != 4) {
|
||||
return;
|
||||
}
|
||||
if (!Baritone.settings().allowParkourPlace.get()) {
|
||||
@@ -120,11 +130,11 @@ public class MovementParkour extends Movement {
|
||||
}
|
||||
int destX = x + 4 * xDiff;
|
||||
int destZ = z + 4 * zDiff;
|
||||
IBlockState toPlace = BlockStateInterface.get(destX, y - 1, destZ);
|
||||
IBlockState toPlace = context.get(destX, y - 1, destZ);
|
||||
if (!context.canPlaceThrowawayAt(destX, y - 1, destZ)) {
|
||||
return;
|
||||
}
|
||||
if (toPlace.getBlock() != Blocks.AIR && !BlockStateInterface.isWater(toPlace.getBlock()) && !MovementHelper.isReplacable(destX, y - 1, destZ, toPlace)) {
|
||||
if (toPlace.getBlock() != Blocks.AIR && !MovementHelper.isWater(toPlace.getBlock()) && !MovementHelper.isReplacable(destX, y - 1, destZ, toPlace)) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < 5; i++) {
|
||||
@@ -133,7 +143,7 @@ public class MovementParkour extends Movement {
|
||||
if (againstX == x + xDiff * 3 && againstZ == z + zDiff * 3) { // we can't turn around that fast
|
||||
continue;
|
||||
}
|
||||
if (MovementHelper.canPlaceAgainst(againstX, y - 1, againstZ)) {
|
||||
if (MovementHelper.canPlaceAgainst(context,againstX, y - 1, againstZ)) {
|
||||
res.x = destX;
|
||||
res.y = y;
|
||||
res.z = destZ;
|
||||
@@ -217,7 +227,7 @@ public class MovementParkour extends Movement {
|
||||
double faceY = (dest.getY() + against1.getY()) * 0.5D;
|
||||
double faceZ = (dest.getZ() + against1.getZ() + 1.0D) * 0.5D;
|
||||
Rotation place = RotationUtils.calcRotationFromVec3d(playerHead(), new Vec3d(faceX, faceY, faceZ), playerRotations());
|
||||
RayTraceResult res = RayTraceUtils.rayTraceTowards(place);
|
||||
RayTraceResult res = RayTraceUtils.rayTraceTowards(player(), place, playerController().getBlockReachDistance());
|
||||
if (res != null && res.typeOfHit == RayTraceResult.Type.BLOCK && res.getBlockPos().equals(against1) && res.getBlockPos().offset(res.sideHit).equals(dest.down())) {
|
||||
state.setTarget(new MovementState.MovementTarget(place, true));
|
||||
}
|
||||
@@ -251,4 +261,4 @@ public class MovementParkour extends Movement {
|
||||
}
|
||||
return state;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.InputOverrideHandler;
|
||||
import net.minecraft.block.*;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
@@ -47,9 +46,9 @@ public class MovementPillar extends Movement {
|
||||
}
|
||||
|
||||
public static double cost(CalculationContext context, int x, int y, int z) {
|
||||
Block fromDown = BlockStateInterface.get(x, y, z).getBlock();
|
||||
Block fromDown = context.get(x, y, z).getBlock();
|
||||
boolean ladder = fromDown instanceof BlockLadder || fromDown instanceof BlockVine;
|
||||
IBlockState fromDownDown = BlockStateInterface.get(x, y - 1, z);
|
||||
IBlockState fromDownDown = context.get(x, y - 1, z);
|
||||
if (!ladder) {
|
||||
if (fromDownDown.getBlock() instanceof BlockLadder || fromDownDown.getBlock() instanceof BlockVine) {
|
||||
return COST_INF;
|
||||
@@ -58,18 +57,18 @@ public class MovementPillar extends Movement {
|
||||
return COST_INF; // can't pillar up from a bottom slab onto a non ladder
|
||||
}
|
||||
}
|
||||
if (fromDown instanceof BlockVine && !hasAgainst(x, y, z)) {
|
||||
if (fromDown instanceof BlockVine && !hasAgainst(context, x, y, z)) {
|
||||
return COST_INF;
|
||||
}
|
||||
IBlockState toBreak = BlockStateInterface.get(x, y + 2, z);
|
||||
IBlockState toBreak = context.get(x, y + 2, z);
|
||||
Block toBreakBlock = toBreak.getBlock();
|
||||
if (toBreakBlock instanceof BlockFenceGate) {
|
||||
return COST_INF;
|
||||
}
|
||||
Block srcUp = null;
|
||||
if (BlockStateInterface.isWater(toBreakBlock) && BlockStateInterface.isWater(fromDown)) {
|
||||
srcUp = BlockStateInterface.get(x, y + 1, z).getBlock();
|
||||
if (BlockStateInterface.isWater(srcUp)) {
|
||||
if (MovementHelper.isWater(toBreakBlock) && MovementHelper.isWater(fromDown)) {
|
||||
srcUp = context.get(x, y + 1, z).getBlock();
|
||||
if (MovementHelper.isWater(srcUp)) {
|
||||
return LADDER_UP_ONE_COST;
|
||||
}
|
||||
}
|
||||
@@ -84,11 +83,11 @@ public class MovementPillar extends Movement {
|
||||
if (toBreakBlock instanceof BlockLadder || toBreakBlock instanceof BlockVine) {
|
||||
hardness = 0; // we won't actually need to break the ladder / vine because we're going to use it
|
||||
} else {
|
||||
IBlockState check = BlockStateInterface.get(x, y + 3, z);
|
||||
IBlockState check = context.get(x, y + 3, z);
|
||||
if (check.getBlock() instanceof BlockFalling) {
|
||||
// see MovementAscend's identical check for breaking a falling block above our head
|
||||
if (srcUp == null) {
|
||||
srcUp = BlockStateInterface.get(x, y + 1, z).getBlock();
|
||||
srcUp = context.get(x, y + 1, z).getBlock();
|
||||
}
|
||||
if (!(toBreakBlock instanceof BlockFalling) || !(srcUp instanceof BlockFalling)) {
|
||||
return COST_INF;
|
||||
@@ -113,24 +112,24 @@ public class MovementPillar extends Movement {
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean hasAgainst(int x, int y, int z) {
|
||||
return BlockStateInterface.get(x + 1, y, z).isBlockNormalCube() ||
|
||||
BlockStateInterface.get(x - 1, y, z).isBlockNormalCube() ||
|
||||
BlockStateInterface.get(x, y, z + 1).isBlockNormalCube() ||
|
||||
BlockStateInterface.get(x, y, z - 1).isBlockNormalCube();
|
||||
public static boolean hasAgainst(CalculationContext context, int x, int y, int z) {
|
||||
return context.get(x + 1, y, z).isBlockNormalCube() ||
|
||||
context.get(x - 1, y, z).isBlockNormalCube() ||
|
||||
context.get(x, y, z + 1).isBlockNormalCube() ||
|
||||
context.get(x, y, z - 1).isBlockNormalCube();
|
||||
}
|
||||
|
||||
public static BlockPos getAgainst(BlockPos vine) {
|
||||
if (BlockStateInterface.get(vine.north()).isBlockNormalCube()) {
|
||||
public static BlockPos getAgainst(CalculationContext context, BetterBlockPos vine) {
|
||||
if (context.get(vine.north()).isBlockNormalCube()) {
|
||||
return vine.north();
|
||||
}
|
||||
if (BlockStateInterface.get(vine.south()).isBlockNormalCube()) {
|
||||
if (context.get(vine.south()).isBlockNormalCube()) {
|
||||
return vine.south();
|
||||
}
|
||||
if (BlockStateInterface.get(vine.east()).isBlockNormalCube()) {
|
||||
if (context.get(vine.east()).isBlockNormalCube()) {
|
||||
return vine.east();
|
||||
}
|
||||
if (BlockStateInterface.get(vine.west()).isBlockNormalCube()) {
|
||||
if (context.get(vine.west()).isBlockNormalCube()) {
|
||||
return vine.west();
|
||||
}
|
||||
return null;
|
||||
@@ -144,7 +143,7 @@ public class MovementPillar extends Movement {
|
||||
}
|
||||
|
||||
IBlockState fromDown = BlockStateInterface.get(src);
|
||||
if (BlockStateInterface.isWater(fromDown.getBlock()) && BlockStateInterface.isWater(dest)) {
|
||||
if (MovementHelper.isWater(fromDown.getBlock()) && MovementHelper.isWater(dest)) {
|
||||
// stay centered while swimming up a water column
|
||||
state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(playerHead(), VecUtils.getBlockPosCenter(dest)), false));
|
||||
Vec3d destCenter = VecUtils.getBlockPosCenter(dest);
|
||||
@@ -158,16 +157,16 @@ public class MovementPillar extends Movement {
|
||||
}
|
||||
boolean ladder = fromDown.getBlock() instanceof BlockLadder || fromDown.getBlock() instanceof BlockVine;
|
||||
boolean vine = fromDown.getBlock() instanceof BlockVine;
|
||||
Rotation rotation = RotationUtils.calcRotationFromVec3d(mc.player.getPositionEyes(1.0F),
|
||||
Rotation rotation = RotationUtils.calcRotationFromVec3d(player().getPositionEyes(1.0F),
|
||||
VecUtils.getBlockPosCenter(positionToPlace),
|
||||
new Rotation(mc.player.rotationYaw, mc.player.rotationPitch));
|
||||
new Rotation(player().rotationYaw, player().rotationPitch));
|
||||
if (!ladder) {
|
||||
state.setTarget(new MovementState.MovementTarget(new Rotation(mc.player.rotationYaw, rotation.getPitch()), true));
|
||||
state.setTarget(new MovementState.MovementTarget(new Rotation(player().rotationYaw, rotation.getPitch()), true));
|
||||
}
|
||||
|
||||
boolean blockIsThere = MovementHelper.canWalkOn(src) || ladder;
|
||||
if (ladder) {
|
||||
BlockPos against = vine ? getAgainst(src) : src.offset(fromDown.getValue(BlockLadder.FACING).getOpposite());
|
||||
BlockPos against = vine ? getAgainst(new CalculationContext(), src) : src.offset(fromDown.getValue(BlockLadder.FACING).getOpposite());
|
||||
if (against == null) {
|
||||
logDebug("Unable to climb vines");
|
||||
return state.setStatus(MovementStatus.UNREACHABLE);
|
||||
@@ -176,7 +175,7 @@ public class MovementPillar extends Movement {
|
||||
if (playerFeet().equals(against.up()) || playerFeet().equals(dest)) {
|
||||
return state.setStatus(MovementStatus.SUCCESS);
|
||||
}
|
||||
if (MovementHelper.isBottomSlab(src.down())) {
|
||||
if (MovementHelper.isBottomSlab(BlockStateInterface.get(src.down()))) {
|
||||
state.setInput(InputOverrideHandler.Input.JUMP, true);
|
||||
}
|
||||
/*
|
||||
@@ -215,10 +214,10 @@ public class MovementPillar extends Movement {
|
||||
|
||||
if (!blockIsThere) {
|
||||
Block fr = BlockStateInterface.get(src).getBlock();
|
||||
if (!(fr instanceof BlockAir || fr.isReplaceable(Minecraft.getMinecraft().world, src))) {
|
||||
if (!(fr instanceof BlockAir || fr.isReplaceable(world(), src))) {
|
||||
state.setInput(InputOverrideHandler.Input.CLICK_LEFT, true);
|
||||
blockIsThere = false;
|
||||
} else if (Minecraft.getMinecraft().player.isSneaking()) { // 1 tick after we're able to place
|
||||
} else if (player().isSneaking()) { // 1 tick after we're able to place
|
||||
state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true);
|
||||
}
|
||||
}
|
||||
@@ -240,9 +239,9 @@ public class MovementPillar extends Movement {
|
||||
state.setInput(InputOverrideHandler.Input.SNEAK, true);
|
||||
}
|
||||
}
|
||||
if (BlockStateInterface.isWater(dest.up())) {
|
||||
if (MovementHelper.isWater(dest.up())) {
|
||||
return true;
|
||||
}
|
||||
return super.prepared(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,14 +59,14 @@ public class MovementTraverse extends Movement {
|
||||
}
|
||||
|
||||
public static double cost(CalculationContext context, int x, int y, int z, int destX, int destZ) {
|
||||
IBlockState pb0 = BlockStateInterface.get(destX, y + 1, destZ);
|
||||
IBlockState pb1 = BlockStateInterface.get(destX, y, destZ);
|
||||
IBlockState destOn = BlockStateInterface.get(destX, y - 1, destZ);
|
||||
Block srcDown = BlockStateInterface.getBlock(x, y - 1, z);
|
||||
if (MovementHelper.canWalkOn(destX, y - 1, destZ, destOn)) {//this is a walk, not a bridge
|
||||
IBlockState pb0 = context.get(destX, y + 1, destZ);
|
||||
IBlockState pb1 = context.get(destX, y, destZ);
|
||||
IBlockState destOn = context.get(destX, y - 1, destZ);
|
||||
Block srcDown = context.getBlock(x, y - 1, z);
|
||||
if (MovementHelper.canWalkOn(context, destX, y - 1, destZ, destOn)) {//this is a walk, not a bridge
|
||||
double WC = WALK_ONE_BLOCK_COST;
|
||||
boolean water = false;
|
||||
if (BlockStateInterface.isWater(pb0.getBlock()) || BlockStateInterface.isWater(pb1.getBlock())) {
|
||||
if (MovementHelper.isWater(pb0.getBlock()) || MovementHelper.isWater(pb1.getBlock())) {
|
||||
WC = context.waterWalkSpeed();
|
||||
water = true;
|
||||
} else {
|
||||
@@ -101,8 +101,8 @@ public class MovementTraverse extends Movement {
|
||||
return COST_INF;
|
||||
}
|
||||
if (destOn.getBlock().equals(Blocks.AIR) || MovementHelper.isReplacable(destX, y - 1, destZ, destOn)) {
|
||||
boolean throughWater = BlockStateInterface.isWater(pb0.getBlock()) || BlockStateInterface.isWater(pb1.getBlock());
|
||||
if (BlockStateInterface.isWater(destOn.getBlock()) && throughWater) {
|
||||
boolean throughWater = MovementHelper.isWater(pb0.getBlock()) || MovementHelper.isWater(pb1.getBlock());
|
||||
if (MovementHelper.isWater(destOn.getBlock()) && throughWater) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (!context.canPlaceThrowawayAt(destX, y - 1, destZ)) {
|
||||
@@ -121,7 +121,7 @@ public class MovementTraverse extends Movement {
|
||||
if (againstX == x && againstZ == z) {
|
||||
continue;
|
||||
}
|
||||
if (MovementHelper.canPlaceAgainst(againstX, y - 1, againstZ)) {
|
||||
if (MovementHelper.canPlaceAgainst(context, againstX, y - 1, againstZ)) {
|
||||
return WC + context.placeBlockCost() + hardness1 + hardness2;
|
||||
}
|
||||
}
|
||||
@@ -223,7 +223,7 @@ public class MovementTraverse extends Movement {
|
||||
if (playerFeet().equals(dest)) {
|
||||
return state.setStatus(MovementStatus.SUCCESS);
|
||||
}
|
||||
if (wasTheBridgeBlockAlwaysThere && !BlockStateInterface.isLiquid(playerFeet())) {
|
||||
if (wasTheBridgeBlockAlwaysThere && !MovementHelper.isLiquid(playerFeet())) {
|
||||
state.setInput(InputOverrideHandler.Input.SPRINT, true);
|
||||
}
|
||||
Block destDown = BlockStateInterface.get(dest.down()).getBlock();
|
||||
@@ -265,7 +265,7 @@ public class MovementTraverse extends Movement {
|
||||
state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(playerHead(), new Vec3d(faceX, faceY, faceZ), playerRotations()), true));
|
||||
|
||||
EnumFacing side = Minecraft.getMinecraft().objectMouseOver.sideHit;
|
||||
if (Objects.equals(RayTraceUtils.getSelectedBlock().orElse(null), against1) && (Minecraft.getMinecraft().player.isSneaking() || Baritone.settings().assumeSafeWalk.get()) && RayTraceUtils.getSelectedBlock().get().offset(side).equals(positionToPlace)) {
|
||||
if (Objects.equals(RayTraceUtils.getSelectedBlock().orElse(null), against1) && (player().isSneaking() || Baritone.settings().assumeSafeWalk.get()) && RayTraceUtils.getSelectedBlock().get().offset(side).equals(positionToPlace)) {
|
||||
return state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true);
|
||||
}
|
||||
//System.out.println("Trying to look at " + against1 + ", actually looking at" + RayTraceUtils.getSelectedBlock());
|
||||
|
||||
+11
-5
@@ -15,17 +15,18 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.calc;
|
||||
package baritone.pathing.path;
|
||||
|
||||
import baritone.api.pathing.calc.IPath;
|
||||
import baritone.api.pathing.goals.Goal;
|
||||
import baritone.api.pathing.movement.IMovement;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.utils.pathing.PathBase;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class CutoffPath implements IPath {
|
||||
public class CutoffPath extends PathBase {
|
||||
|
||||
private final List<BetterBlockPos> path;
|
||||
|
||||
@@ -35,11 +36,16 @@ public class CutoffPath implements IPath {
|
||||
|
||||
private final Goal goal;
|
||||
|
||||
CutoffPath(IPath prev, int lastPositionToInclude) {
|
||||
path = prev.positions().subList(0, lastPositionToInclude + 1);
|
||||
movements = prev.movements().subList(0, lastPositionToInclude + 1);
|
||||
public CutoffPath(IPath prev, int firstPositionToInclude, int lastPositionToInclude) {
|
||||
path = prev.positions().subList(firstPositionToInclude, lastPositionToInclude + 1);
|
||||
movements = prev.movements().subList(firstPositionToInclude, lastPositionToInclude);
|
||||
numNodes = prev.getNumNodesConsidered();
|
||||
goal = prev.getGoal();
|
||||
sanityCheck();
|
||||
}
|
||||
|
||||
public CutoffPath(IPath prev, int lastPositionToInclude) {
|
||||
this(prev, 0, lastPositionToInclude);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -454,6 +454,43 @@ public class PathExecutor implements IPathExecutor, Helper {
|
||||
return pathPosition;
|
||||
}
|
||||
|
||||
public PathExecutor trySplice(PathExecutor next) {
|
||||
if (next == null) {
|
||||
return cutIfTooLong();
|
||||
}
|
||||
return SplicedPath.trySplice(path, next.path).map(path -> {
|
||||
if (!path.getDest().equals(next.getPath().getDest())) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
PathExecutor ret = new PathExecutor(path);
|
||||
ret.pathPosition = pathPosition;
|
||||
ret.currentMovementOriginalCostEstimate = currentMovementOriginalCostEstimate;
|
||||
ret.costEstimateIndex = costEstimateIndex;
|
||||
ret.ticksOnCurrent = ticksOnCurrent;
|
||||
return ret;
|
||||
}).orElse(cutIfTooLong());
|
||||
}
|
||||
|
||||
private PathExecutor cutIfTooLong() {
|
||||
if (pathPosition > Baritone.settings().maxPathHistoryLength.get()) {
|
||||
int cutoffAmt = Baritone.settings().pathHistoryCutoffAmount.get();
|
||||
CutoffPath newPath = new CutoffPath(path, cutoffAmt, path.length() - 1);
|
||||
if (!newPath.getDest().equals(path.getDest())) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
logDebug("Discarding earliest segment movements, length cut from " + path.length() + " to " + newPath.length());
|
||||
PathExecutor ret = new PathExecutor(newPath);
|
||||
ret.pathPosition = pathPosition - cutoffAmt;
|
||||
ret.currentMovementOriginalCostEstimate = currentMovementOriginalCostEstimate;
|
||||
if (costEstimateIndex != null) {
|
||||
ret.costEstimateIndex = costEstimateIndex - cutoffAmt;
|
||||
}
|
||||
ret.ticksOnCurrent = ticksOnCurrent;
|
||||
return ret;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPath getPath() {
|
||||
return path;
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.path;
|
||||
|
||||
import baritone.api.pathing.calc.IPath;
|
||||
import baritone.api.pathing.goals.Goal;
|
||||
import baritone.api.pathing.movement.IMovement;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.utils.pathing.PathBase;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class SplicedPath extends PathBase {
|
||||
private final List<BetterBlockPos> path;
|
||||
|
||||
private final List<IMovement> movements;
|
||||
|
||||
private final int numNodes;
|
||||
|
||||
private final Goal goal;
|
||||
|
||||
private SplicedPath(List<BetterBlockPos> path, List<IMovement> movements, int numNodesConsidered, Goal goal) {
|
||||
this.path = path;
|
||||
this.movements = movements;
|
||||
this.numNodes = numNodesConsidered;
|
||||
this.goal = goal;
|
||||
sanityCheck();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Goal getGoal() {
|
||||
return goal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IMovement> movements() {
|
||||
return Collections.unmodifiableList(movements);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BetterBlockPos> positions() {
|
||||
return Collections.unmodifiableList(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumNodesConsidered() {
|
||||
return numNodes;
|
||||
}
|
||||
|
||||
public static Optional<SplicedPath> trySplice(IPath first, IPath second) {
|
||||
if (second == null || first == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
if (!Objects.equals(first.getGoal(), second.getGoal())) {
|
||||
return Optional.empty();
|
||||
}
|
||||
if (!first.getDest().equals(second.getSrc())) {
|
||||
return Optional.empty();
|
||||
}
|
||||
HashSet<BetterBlockPos> a = new HashSet<>(first.positions());
|
||||
for (int i = 1; i < second.length(); i++) {
|
||||
if (a.contains(second.positions().get(i))) {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
List<BetterBlockPos> positions = new ArrayList<>();
|
||||
List<IMovement> movements = new ArrayList<>();
|
||||
positions.addAll(first.positions());
|
||||
positions.addAll(second.positions().subList(1, second.length()));
|
||||
movements.addAll(first.movements());
|
||||
movements.addAll(second.movements());
|
||||
return Optional.of(new SplicedPath(positions, movements, first.getNumNodesConsidered() + second.getNumNodesConsidered(), first.getGoal()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.process;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.pathing.goals.Goal;
|
||||
import baritone.api.process.ICustomGoalProcess;
|
||||
import baritone.api.process.PathingCommand;
|
||||
import baritone.api.process.PathingCommandType;
|
||||
import baritone.utils.BaritoneProcessHelper;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* As set by ExampleBaritoneControl or something idk
|
||||
*
|
||||
* @author leijurv
|
||||
*/
|
||||
public class CustomGoalProcess extends BaritoneProcessHelper implements ICustomGoalProcess {
|
||||
|
||||
/**
|
||||
* The current goal
|
||||
*/
|
||||
private Goal goal;
|
||||
|
||||
/**
|
||||
* The current process state.
|
||||
*
|
||||
* @see State
|
||||
*/
|
||||
private State state;
|
||||
|
||||
public CustomGoalProcess(Baritone baritone) {
|
||||
super(baritone, 3);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGoal(Goal goal) {
|
||||
this.goal = goal;
|
||||
this.state = State.GOAL_SET;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void path() {
|
||||
this.state = State.PATH_REQUESTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Goal getGoal() {
|
||||
return this.goal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
return this.state != State.NONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) {
|
||||
switch (this.state) {
|
||||
case GOAL_SET:
|
||||
if (!baritone.getPathingBehavior().isPathing() && Objects.equals(baritone.getPathingBehavior().getGoal(), this.goal)) {
|
||||
this.state = State.NONE;
|
||||
}
|
||||
return new PathingCommand(this.goal, PathingCommandType.CANCEL_AND_SET_GOAL);
|
||||
case PATH_REQUESTED:
|
||||
PathingCommand ret = new PathingCommand(this.goal, PathingCommandType.SET_GOAL_AND_PATH);
|
||||
this.state = State.EXECUTING;
|
||||
return ret;
|
||||
case EXECUTING:
|
||||
if (calcFailed) {
|
||||
onLostControl();
|
||||
}
|
||||
if (this.goal == null || this.goal.isInGoal(playerFeet())) {
|
||||
onLostControl(); // we're there xd
|
||||
}
|
||||
return new PathingCommand(this.goal, PathingCommandType.SET_GOAL_AND_PATH);
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLostControl() {
|
||||
this.state = State.NONE;
|
||||
this.goal = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String displayName() {
|
||||
return "Custom Goal " + this.goal;
|
||||
}
|
||||
|
||||
protected enum State {
|
||||
NONE,
|
||||
GOAL_SET,
|
||||
PATH_REQUESTED,
|
||||
EXECUTING
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.process;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.pathing.goals.Goal;
|
||||
import baritone.api.pathing.goals.GoalComposite;
|
||||
import baritone.api.pathing.goals.GoalNear;
|
||||
import baritone.api.pathing.goals.GoalXZ;
|
||||
import baritone.api.process.IFollowProcess;
|
||||
import baritone.api.process.PathingCommand;
|
||||
import baritone.api.process.PathingCommandType;
|
||||
import baritone.utils.BaritoneProcessHelper;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Follow an entity
|
||||
*
|
||||
* @author leijurv
|
||||
*/
|
||||
public final class FollowProcess extends BaritoneProcessHelper implements IFollowProcess {
|
||||
|
||||
private Predicate<Entity> filter;
|
||||
private List<Entity> cache;
|
||||
|
||||
public FollowProcess(Baritone baritone) {
|
||||
super(baritone, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) {
|
||||
scanWorld();
|
||||
Goal goal = new GoalComposite(cache.stream().map(this::towards).toArray(Goal[]::new));
|
||||
return new PathingCommand(goal, PathingCommandType.REVALIDATE_GOAL_AND_PATH);
|
||||
}
|
||||
|
||||
private Goal towards(Entity following) {
|
||||
// lol this is trashy but it works
|
||||
BlockPos pos;
|
||||
if (Baritone.settings().followOffsetDistance.get() == 0) {
|
||||
pos = new BlockPos(following);
|
||||
} else {
|
||||
GoalXZ g = GoalXZ.fromDirection(following.getPositionVector(), Baritone.settings().followOffsetDirection.get(), Baritone.settings().followOffsetDistance.get());
|
||||
pos = new BlockPos(g.getX(), following.posY, g.getZ());
|
||||
}
|
||||
return new GoalNear(pos, Baritone.settings().followRadius.get());
|
||||
}
|
||||
|
||||
|
||||
private boolean followable(Entity entity) {
|
||||
if (entity == null) {
|
||||
return false;
|
||||
}
|
||||
if (entity.isDead) {
|
||||
return false;
|
||||
}
|
||||
if (entity.equals(player())) {
|
||||
return false;
|
||||
}
|
||||
if (!world().loadedEntityList.contains(entity) && !world().playerEntities.contains(entity)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void scanWorld() {
|
||||
cache = Stream.of(world().loadedEntityList, world().playerEntities).flatMap(List::stream).filter(this::followable).filter(this.filter).distinct().collect(Collectors.toCollection(ArrayList::new));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
if (filter == null) {
|
||||
return false;
|
||||
}
|
||||
scanWorld();
|
||||
return !cache.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLostControl() {
|
||||
filter = null;
|
||||
cache = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String displayName() {
|
||||
return "Follow " + cache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void follow(Predicate<Entity> filter) {
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Entity> following() {
|
||||
return cache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Predicate<Entity> currentFilter() {
|
||||
return filter;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.process;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.pathing.goals.Goal;
|
||||
import baritone.api.pathing.goals.GoalComposite;
|
||||
import baritone.api.pathing.goals.GoalGetToBlock;
|
||||
import baritone.api.process.IGetToBlockProcess;
|
||||
import baritone.api.process.PathingCommand;
|
||||
import baritone.api.process.PathingCommandType;
|
||||
import baritone.utils.BaritoneProcessHelper;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBlockProcess {
|
||||
private Block gettingTo;
|
||||
private List<BlockPos> knownLocations;
|
||||
|
||||
private int tickCount = 0;
|
||||
|
||||
public GetToBlockProcess(Baritone baritone) {
|
||||
super(baritone, 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getToBlock(Block block) {
|
||||
gettingTo = block;
|
||||
knownLocations = null;
|
||||
rescan(new ArrayList<>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
return gettingTo != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) {
|
||||
if (knownLocations == null) {
|
||||
rescan(new ArrayList<>());
|
||||
}
|
||||
if (knownLocations.isEmpty()) {
|
||||
logDirect("No known locations of " + gettingTo + ", canceling GetToBlock");
|
||||
if (isSafeToCancel) {
|
||||
onLostControl();
|
||||
}
|
||||
return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL);
|
||||
}
|
||||
if (calcFailed) {
|
||||
logDirect("Unable to find any path to " + gettingTo + ", canceling GetToBlock");
|
||||
if (isSafeToCancel) {
|
||||
onLostControl();
|
||||
}
|
||||
return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL);
|
||||
}
|
||||
int mineGoalUpdateInterval = Baritone.settings().mineGoalUpdateInterval.get();
|
||||
if (mineGoalUpdateInterval != 0 && tickCount++ % mineGoalUpdateInterval == 0) { // big brain
|
||||
List<BlockPos> current = new ArrayList<>(knownLocations);
|
||||
Baritone.getExecutor().execute(() -> rescan(current));
|
||||
}
|
||||
Goal goal = new GoalComposite(knownLocations.stream().map(GoalGetToBlock::new).toArray(Goal[]::new));
|
||||
if (goal.isInGoal(playerFeet())) {
|
||||
onLostControl();
|
||||
}
|
||||
return new PathingCommand(goal, PathingCommandType.REVALIDATE_GOAL_AND_PATH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLostControl() {
|
||||
gettingTo = null;
|
||||
knownLocations = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String displayName() {
|
||||
return "Get To Block " + gettingTo;
|
||||
}
|
||||
|
||||
private void rescan(List<BlockPos> known) {
|
||||
knownLocations = MineProcess.searchWorld(Collections.singletonList(gettingTo), 64, baritone.getWorldProvider(), world(), known);
|
||||
}
|
||||
}
|
||||
+118
-65
@@ -15,25 +15,31 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.behavior;
|
||||
package baritone.process;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.behavior.IMineBehavior;
|
||||
import baritone.api.event.events.TickEvent;
|
||||
import baritone.api.pathing.goals.*;
|
||||
import baritone.api.process.IMineProcess;
|
||||
import baritone.api.process.PathingCommand;
|
||||
import baritone.api.process.PathingCommandType;
|
||||
import baritone.api.utils.RotationUtils;
|
||||
import baritone.cache.CachedChunk;
|
||||
import baritone.cache.ChunkPacker;
|
||||
import baritone.cache.WorldProvider;
|
||||
import baritone.cache.WorldScanner;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.utils.BaritoneProcessHelper;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.Helper;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.item.EntityItem;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.EmptyChunk;
|
||||
|
||||
import java.util.*;
|
||||
@@ -44,26 +50,28 @@ import java.util.stream.Collectors;
|
||||
*
|
||||
* @author leijurv
|
||||
*/
|
||||
public final class MineBehavior extends Behavior implements IMineBehavior, Helper {
|
||||
public final class MineProcess extends BaritoneProcessHelper implements IMineProcess {
|
||||
|
||||
private static final int ORE_LOCATIONS_COUNT = 64;
|
||||
|
||||
private List<Block> mining;
|
||||
private List<BlockPos> knownOreLocations;
|
||||
private BlockPos branchPoint;
|
||||
private GoalRunAway branchPointRunaway;
|
||||
private int desiredQuantity;
|
||||
private int tickCount;
|
||||
|
||||
public MineBehavior(Baritone baritone) {
|
||||
super(baritone);
|
||||
public MineProcess(Baritone baritone) {
|
||||
super(baritone, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTick(TickEvent event) {
|
||||
if (event.getType() == TickEvent.Type.OUT) {
|
||||
cancel();
|
||||
return;
|
||||
}
|
||||
if (mining == null) {
|
||||
return;
|
||||
}
|
||||
public boolean isActive() {
|
||||
return mining != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) {
|
||||
if (desiredQuantity > 0) {
|
||||
Item item = mining.get(0).getItemDropped(mining.get(0).getDefaultState(), new Random(), 0);
|
||||
int curr = player().inventory.mainInventory.stream().filter(stack -> item.equals(stack.getItem())).mapToInt(ItemStack::getCount).sum();
|
||||
@@ -71,66 +79,92 @@ public final class MineBehavior extends Behavior implements IMineBehavior, Helpe
|
||||
if (curr >= desiredQuantity) {
|
||||
logDirect("Have " + curr + " " + item.getItemStackDisplayName(new ItemStack(item, 1)));
|
||||
cancel();
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (calcFailed) {
|
||||
logDirect("Unable to find any path to " + mining + ", canceling Mine");
|
||||
cancel();
|
||||
return null;
|
||||
}
|
||||
int mineGoalUpdateInterval = Baritone.settings().mineGoalUpdateInterval.get();
|
||||
if (mineGoalUpdateInterval != 0 && event.getCount() % mineGoalUpdateInterval == 0) {
|
||||
Baritone.INSTANCE.getExecutor().execute(this::rescan);
|
||||
if (mineGoalUpdateInterval != 0 && tickCount++ % mineGoalUpdateInterval == 0) { // big brain
|
||||
List<BlockPos> curr = new ArrayList<>(knownOreLocations);
|
||||
baritone.getExecutor().execute(() -> rescan(curr));
|
||||
}
|
||||
if (Baritone.settings().legitMine.get()) {
|
||||
addNearby();
|
||||
}
|
||||
updateGoal();
|
||||
baritone.getPathingBehavior().revalidateGoal();
|
||||
Goal goal = updateGoal();
|
||||
if (goal == null) {
|
||||
// none in range
|
||||
// maybe say something in chat? (ahem impact)
|
||||
cancel();
|
||||
return null;
|
||||
}
|
||||
return new PathingCommand(goal, PathingCommandType.FORCE_REVALIDATE_GOAL_AND_PATH);
|
||||
}
|
||||
|
||||
private void updateGoal() {
|
||||
if (mining == null) {
|
||||
return;
|
||||
}
|
||||
@Override
|
||||
public void onLostControl() {
|
||||
mine(0, (Block[]) null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String displayName() {
|
||||
return "Mine " + mining;
|
||||
}
|
||||
|
||||
private Goal updateGoal() {
|
||||
List<BlockPos> locs = knownOreLocations;
|
||||
if (!locs.isEmpty()) {
|
||||
List<BlockPos> locs2 = prune(new ArrayList<>(locs), mining, 64);
|
||||
List<BlockPos> locs2 = prune(new ArrayList<>(locs), mining, ORE_LOCATIONS_COUNT, world());
|
||||
// can't reassign locs, gotta make a new var locs2, because we use it in a lambda right here, and variables you use in a lambda must be effectively final
|
||||
baritone.getPathingBehavior().setGoalAndPath(new GoalComposite(locs2.stream().map(loc -> coalesce(loc, locs2)).toArray(Goal[]::new)));
|
||||
knownOreLocations = locs;
|
||||
return;
|
||||
Goal goal = new GoalComposite(locs2.stream().map(loc -> coalesce(loc, locs2)).toArray(Goal[]::new));
|
||||
knownOreLocations = locs2;
|
||||
return goal;
|
||||
}
|
||||
// we don't know any ore locations at the moment
|
||||
if (!Baritone.settings().legitMine.get()) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
// only in non-Xray mode (aka legit mode) do we do this
|
||||
int y = Baritone.settings().legitMineYLevel.get();
|
||||
if (branchPoint == null) {
|
||||
int y = Baritone.settings().legitMineYLevel.get();
|
||||
if (!baritone.getPathingBehavior().isPathing() && playerFeet().y == y) {
|
||||
/*if (!baritone.getPathingBehavior().isPathing() && playerFeet().y == y) {
|
||||
// cool, path is over and we are at desired y
|
||||
branchPoint = playerFeet();
|
||||
branchPointRunaway = null;
|
||||
} else {
|
||||
baritone.getPathingBehavior().setGoalAndPath(new GoalYLevel(y));
|
||||
return;
|
||||
}
|
||||
return new GoalYLevel(y);
|
||||
}*/
|
||||
branchPoint = playerFeet();
|
||||
}
|
||||
|
||||
if (playerFeet().equals(branchPoint)) {
|
||||
// TODO mine 1x1 shafts to either side
|
||||
branchPoint = branchPoint.north(10);
|
||||
// TODO shaft mode, mine 1x1 shafts to either side
|
||||
// TODO also, see if the GoalRunAway with maintain Y at 11 works even from the surface
|
||||
if (branchPointRunaway == null) {
|
||||
branchPointRunaway = new GoalRunAway(1, Optional.of(y), branchPoint) {
|
||||
@Override
|
||||
public boolean isInGoal(int x, int y, int z) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
baritone.getPathingBehavior().setGoalAndPath(new GoalBlock(branchPoint));
|
||||
return branchPointRunaway;
|
||||
}
|
||||
|
||||
private void rescan() {
|
||||
private void rescan(List<BlockPos> already) {
|
||||
if (mining == null) {
|
||||
return;
|
||||
}
|
||||
if (Baritone.settings().legitMine.get()) {
|
||||
return;
|
||||
}
|
||||
List<BlockPos> locs = searchWorld(mining, 64);
|
||||
List<BlockPos> locs = searchWorld(mining, ORE_LOCATIONS_COUNT, baritone.getWorldProvider(), world(), already);
|
||||
locs.addAll(droppedItemsScan(mining, world()));
|
||||
if (locs.isEmpty()) {
|
||||
logDebug("No locations for " + mining + " known, cancelling");
|
||||
mine(0, (String[]) null);
|
||||
cancel();
|
||||
return;
|
||||
}
|
||||
knownOreLocations = locs;
|
||||
@@ -158,13 +192,39 @@ public final class MineBehavior extends Behavior implements IMineBehavior, Helpe
|
||||
}
|
||||
}
|
||||
|
||||
public List<BlockPos> searchWorld(List<Block> mining, int max) {
|
||||
public static List<BlockPos> droppedItemsScan(List<Block> mining, World world) {
|
||||
if (!Baritone.settings().mineScanDroppedItems.get()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
Set<Item> searchingFor = new HashSet<>();
|
||||
for (Block block : mining) {
|
||||
Item drop = block.getItemDropped(block.getDefaultState(), new Random(), 0);
|
||||
Item ore = Item.getItemFromBlock(block);
|
||||
searchingFor.add(drop);
|
||||
searchingFor.add(ore);
|
||||
}
|
||||
List<BlockPos> ret = new ArrayList<>();
|
||||
for (Entity entity : world.loadedEntityList) {
|
||||
if (entity instanceof EntityItem) {
|
||||
EntityItem ei = (EntityItem) entity;
|
||||
if (searchingFor.contains(ei.getItem().getItem())) {
|
||||
ret.add(new BlockPos(entity));
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*public static List<BlockPos> searchWorld(List<Block> mining, int max, World world) {
|
||||
|
||||
}*/
|
||||
public static List<BlockPos> searchWorld(List<Block> mining, int max, WorldProvider provider, World world, List<BlockPos> alreadyKnown) {
|
||||
List<BlockPos> locs = new ArrayList<>();
|
||||
List<Block> uninteresting = new ArrayList<>();
|
||||
//long b = System.currentTimeMillis();
|
||||
for (Block m : mining) {
|
||||
if (CachedChunk.BLOCKS_TO_KEEP_TRACK_OF.contains(m)) {
|
||||
locs.addAll(WorldProvider.INSTANCE.getCurrentWorld().getCachedWorld().getLocationsOf(ChunkPacker.blockToString(m), 1, 1));
|
||||
locs.addAll(provider.getCurrentWorld().getCachedWorld().getLocationsOf(ChunkPacker.blockToString(m), 1, 1));
|
||||
} else {
|
||||
uninteresting.add(m);
|
||||
}
|
||||
@@ -178,34 +238,38 @@ public final class MineBehavior extends Behavior implements IMineBehavior, Helpe
|
||||
locs.addAll(WorldScanner.INSTANCE.scanChunkRadius(uninteresting, max, 10, 26));
|
||||
//System.out.println("Scan of loaded chunks took " + (System.currentTimeMillis() - before) + "ms");
|
||||
}
|
||||
return prune(locs, mining, max);
|
||||
locs.addAll(alreadyKnown);
|
||||
return prune(locs, mining, max, world);
|
||||
}
|
||||
|
||||
public void addNearby() {
|
||||
knownOreLocations.addAll(droppedItemsScan(mining, world()));
|
||||
BlockPos playerFeet = playerFeet();
|
||||
int searchDist = 4;//why four? idk
|
||||
for (int x = playerFeet.getX() - searchDist; x <= playerFeet.getX() + searchDist; x++) {
|
||||
for (int y = playerFeet.getY() - searchDist; y <= playerFeet.getY() + searchDist; y++) {
|
||||
for (int z = playerFeet.getZ() - searchDist; z <= playerFeet.getZ() + searchDist; z++) {
|
||||
BlockPos pos = new BlockPos(x, y, z);
|
||||
if (mining.contains(BlockStateInterface.getBlock(pos)) && RotationUtils.reachable(player(), pos).isPresent()) {//crucial to only add blocks we can see because otherwise this is an x-ray and it'll get caught
|
||||
if (mining.contains(BlockStateInterface.getBlock(pos)) && RotationUtils.reachable(player(), pos, playerController().getBlockReachDistance()).isPresent()) {//crucial to only add blocks we can see because otherwise this is an x-ray and it'll get caught
|
||||
knownOreLocations.add(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
knownOreLocations = prune(knownOreLocations, mining, 64);
|
||||
knownOreLocations = prune(knownOreLocations, mining, ORE_LOCATIONS_COUNT, world());
|
||||
}
|
||||
|
||||
public List<BlockPos> prune(List<BlockPos> locs2, List<Block> mining, int max) {
|
||||
public static List<BlockPos> prune(List<BlockPos> locs2, List<Block> mining, int max, World world) {
|
||||
List<BlockPos> dropped = droppedItemsScan(mining, world);
|
||||
List<BlockPos> locs = locs2
|
||||
.stream()
|
||||
.distinct()
|
||||
|
||||
// remove any that are within loaded chunks that aren't actually what we want
|
||||
.filter(pos -> world().getChunk(pos) instanceof EmptyChunk || mining.contains(BlockStateInterface.get(pos).getBlock()))
|
||||
.filter(pos -> world.getChunk(pos) instanceof EmptyChunk || mining.contains(BlockStateInterface.get(pos).getBlock()) || dropped.contains(pos))
|
||||
|
||||
// remove any that are implausible to mine (encased in bedrock, or touching lava)
|
||||
.filter(MineBehavior::plausibleToBreak)
|
||||
.filter(MineProcess::plausibleToBreak)
|
||||
|
||||
.sorted(Comparator.comparingDouble(Helper.HELPER.playerFeet()::distanceSq))
|
||||
.collect(Collectors.toList());
|
||||
@@ -217,7 +281,7 @@ public final class MineBehavior extends Behavior implements IMineBehavior, Helpe
|
||||
}
|
||||
|
||||
public static boolean plausibleToBreak(BlockPos pos) {
|
||||
if (MovementHelper.avoidBreaking(pos.getX(), pos.getY(), pos.getZ(), BlockStateInterface.get(pos))) {
|
||||
if (MovementHelper.avoidBreaking(new CalculationContext(), pos.getX(), pos.getY(), pos.getZ(), BlockStateInterface.get(pos))) {
|
||||
return false;
|
||||
}
|
||||
// bedrock above and below makes it implausible, otherwise we're good
|
||||
@@ -225,13 +289,8 @@ public final class MineBehavior extends Behavior implements IMineBehavior, Helpe
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mine(int quantity, String... blocks) {
|
||||
this.mining = blocks == null || blocks.length == 0 ? null : Arrays.stream(blocks).map(ChunkPacker::stringToBlock).collect(Collectors.toList());
|
||||
this.desiredQuantity = quantity;
|
||||
this.knownOreLocations = new ArrayList<>();
|
||||
this.branchPoint = null;
|
||||
rescan();
|
||||
updateGoal();
|
||||
public void mineByName(int quantity, String... blocks) {
|
||||
mine(quantity, blocks == null || blocks.length == 0 ? null : Arrays.stream(blocks).map(ChunkPacker::stringToBlock).toArray(Block[]::new));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -240,13 +299,7 @@ public final class MineBehavior extends Behavior implements IMineBehavior, Helpe
|
||||
this.desiredQuantity = quantity;
|
||||
this.knownOreLocations = new ArrayList<>();
|
||||
this.branchPoint = null;
|
||||
rescan();
|
||||
updateGoal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
mine(0, (String[]) null);
|
||||
baritone.getPathingBehavior().cancel();
|
||||
this.branchPointRunaway = null;
|
||||
rescan(new ArrayList<>());
|
||||
}
|
||||
}
|
||||
@@ -105,8 +105,7 @@ public class BaritoneAutoTest implements AbstractGameEventListener, Helper {
|
||||
}
|
||||
|
||||
// Setup Baritone's pathing goal and (if needed) begin pathing
|
||||
Baritone.INSTANCE.getPathingBehavior().setGoal(GOAL);
|
||||
Baritone.INSTANCE.getPathingBehavior().path();
|
||||
Baritone.INSTANCE.getCustomGoalProcess().setGoalAndPath(GOAL);
|
||||
|
||||
// If we have reached our goal, print a message and safely close the game
|
||||
if (GOAL.isInGoal(playerFeet())) {
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.utils;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.process.IBaritoneProcess;
|
||||
|
||||
public abstract class BaritoneProcessHelper implements IBaritoneProcess, Helper {
|
||||
public static final double DEFAULT_PRIORITY = 0;
|
||||
|
||||
protected final Baritone baritone;
|
||||
private final double priority;
|
||||
|
||||
public BaritoneProcessHelper(Baritone baritone) {
|
||||
this(baritone, DEFAULT_PRIORITY);
|
||||
}
|
||||
|
||||
public BaritoneProcessHelper(Baritone baritone, double priority) {
|
||||
this.baritone = baritone;
|
||||
this.priority = priority;
|
||||
baritone.getPathingControlManager().registerProcess(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Baritone associatedWith() {
|
||||
return baritone;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTemporary() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double priority() {
|
||||
return priority;
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@ package baritone.utils;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
@@ -32,6 +33,7 @@ public final class BlockBreakHelper implements Helper {
|
||||
* between attempts, then we re-initialize the breaking process.
|
||||
*/
|
||||
private static BlockPos lastBlock;
|
||||
private static boolean didBreakLastTick;
|
||||
|
||||
private BlockBreakHelper() {}
|
||||
|
||||
@@ -48,7 +50,23 @@ public final class BlockBreakHelper implements Helper {
|
||||
public static void stopBreakingBlock() {
|
||||
if (mc.playerController != null) {
|
||||
mc.playerController.resetBlockRemoving();
|
||||
}
|
||||
}
|
||||
lastBlock = null;
|
||||
}
|
||||
|
||||
public static boolean tick(boolean isLeftClick) {
|
||||
RayTraceResult trace = mc.objectMouseOver;
|
||||
boolean isBlockTrace = trace != null && trace.typeOfHit == RayTraceResult.Type.BLOCK;
|
||||
|
||||
// If we're forcing left click, we're in a gui screen, and we're looking
|
||||
// at a block, break the block without a direct game input manipulation.
|
||||
if (mc.currentScreen != null && isLeftClick && isBlockTrace) {
|
||||
tryBreakBlock(trace.getBlockPos(), trace.sideHit);
|
||||
didBreakLastTick = true;
|
||||
} else if (didBreakLastTick) {
|
||||
stopBreakingBlock();
|
||||
didBreakLastTick = false;
|
||||
}
|
||||
return !didBreakLastTick && isLeftClick;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,12 +20,12 @@ package baritone.utils;
|
||||
import baritone.Baritone;
|
||||
import baritone.cache.CachedRegion;
|
||||
import baritone.cache.WorldData;
|
||||
import baritone.cache.WorldProvider;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockLiquid;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
|
||||
/**
|
||||
@@ -35,16 +35,31 @@ import net.minecraft.world.chunk.Chunk;
|
||||
*/
|
||||
public class BlockStateInterface implements Helper {
|
||||
|
||||
private static Chunk prev = null;
|
||||
private static CachedRegion prevCached = null;
|
||||
private final World world;
|
||||
private final WorldData worldData;
|
||||
|
||||
|
||||
private Chunk prev = null;
|
||||
private CachedRegion prevCached = null;
|
||||
|
||||
private static final IBlockState AIR = Blocks.AIR.getDefaultState();
|
||||
|
||||
public static IBlockState get(BlockPos pos) {
|
||||
return get(pos.getX(), pos.getY(), pos.getZ());
|
||||
public BlockStateInterface(World world, WorldData worldData) {
|
||||
this.worldData = worldData;
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
public static IBlockState get(int x, int y, int z) {
|
||||
public static Block getBlock(BlockPos pos) { // won't be called from the pathing thread because the pathing thread doesn't make a single blockpos pog
|
||||
return get(pos).getBlock();
|
||||
}
|
||||
|
||||
public static IBlockState get(BlockPos pos) {
|
||||
return new CalculationContext().get(pos); // immense iq
|
||||
// can't just do world().get because that doesn't work for out of bounds
|
||||
// and toBreak and stuff fails when the movement is instantiated out of load range but it's not able to BlockStateInterface.get what it's going to walk on
|
||||
}
|
||||
|
||||
public IBlockState get0(int x, int y, int z) {
|
||||
|
||||
// Invalid vertical position
|
||||
if (y < 0 || y >= 256) {
|
||||
@@ -62,7 +77,7 @@ public class BlockStateInterface implements Helper {
|
||||
if (cached != null && cached.x == x >> 4 && cached.z == z >> 4) {
|
||||
return cached.getBlockState(x, y, z);
|
||||
}
|
||||
Chunk chunk = mc.world.getChunk(x >> 4, z >> 4);
|
||||
Chunk chunk = world.getChunk(x >> 4, z >> 4);
|
||||
if (chunk.isLoaded()) {
|
||||
prev = chunk;
|
||||
return chunk.getBlockState(x, y, z);
|
||||
@@ -72,11 +87,10 @@ public class BlockStateInterface implements Helper {
|
||||
// except here, it's 512x512 tiles instead of 16x16, so even better repetition
|
||||
CachedRegion cached = prevCached;
|
||||
if (cached == null || cached.getX() != x >> 9 || cached.getZ() != z >> 9) {
|
||||
WorldData world = WorldProvider.INSTANCE.getCurrentWorld();
|
||||
if (world == null) {
|
||||
if (worldData == null) {
|
||||
return AIR;
|
||||
}
|
||||
CachedRegion region = world.cache.getRegion(x >> 9, z >> 9);
|
||||
CachedRegion region = worldData.cache.getRegion(x >> 9, z >> 9);
|
||||
if (region == null) {
|
||||
return AIR;
|
||||
}
|
||||
@@ -90,12 +104,12 @@ public class BlockStateInterface implements Helper {
|
||||
return type;
|
||||
}
|
||||
|
||||
public static boolean isLoaded(int x, int z) {
|
||||
public boolean isLoaded(int x, int z) {
|
||||
Chunk prevChunk = prev;
|
||||
if (prevChunk != null && prevChunk.x == x >> 4 && prevChunk.z == z >> 4) {
|
||||
return true;
|
||||
}
|
||||
prevChunk = mc.world.getChunk(x >> 4, z >> 4);
|
||||
prevChunk = world.getChunk(x >> 4, z >> 4);
|
||||
if (prevChunk.isLoaded()) {
|
||||
prev = prevChunk;
|
||||
return true;
|
||||
@@ -104,71 +118,14 @@ public class BlockStateInterface implements Helper {
|
||||
if (prevRegion != null && prevRegion.getX() == x >> 9 && prevRegion.getZ() == z >> 9) {
|
||||
return prevRegion.isCached(x & 511, z & 511);
|
||||
}
|
||||
WorldData world = WorldProvider.INSTANCE.getCurrentWorld();
|
||||
if (world == null) {
|
||||
if (worldData == null) {
|
||||
return false;
|
||||
}
|
||||
prevRegion = world.cache.getRegion(x >> 9, z >> 9);
|
||||
prevRegion = worldData.cache.getRegion(x >> 9, z >> 9);
|
||||
if (prevRegion == null) {
|
||||
return false;
|
||||
}
|
||||
prevCached = prevRegion;
|
||||
return prevRegion.isCached(x & 511, z & 511);
|
||||
}
|
||||
|
||||
public static void clearCachedChunk() {
|
||||
prev = null;
|
||||
prevCached = null;
|
||||
}
|
||||
|
||||
public static Block getBlock(BlockPos pos) {
|
||||
return get(pos).getBlock();
|
||||
}
|
||||
|
||||
public static Block getBlock(int x, int y, int z) {
|
||||
return get(x, y, z).getBlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the specified block is
|
||||
* water, regardless of whether or not it is flowing.
|
||||
*
|
||||
* @param b The block
|
||||
* @return Whether or not the block is water
|
||||
*/
|
||||
public static boolean isWater(Block b) {
|
||||
return b == Blocks.FLOWING_WATER || b == Blocks.WATER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the block at the specified pos is
|
||||
* water, regardless of whether or not it is flowing.
|
||||
*
|
||||
* @param bp The block pos
|
||||
* @return Whether or not the block is water
|
||||
*/
|
||||
public static boolean isWater(BlockPos bp) {
|
||||
return isWater(BlockStateInterface.getBlock(bp));
|
||||
}
|
||||
|
||||
public static boolean isLava(Block b) {
|
||||
return b == Blocks.FLOWING_LAVA || b == Blocks.LAVA;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the specified pos has a liquid
|
||||
*
|
||||
* @param p The pos
|
||||
* @return Whether or not the block is a liquid
|
||||
*/
|
||||
public static boolean isLiquid(BlockPos p) {
|
||||
return BlockStateInterface.getBlock(p) instanceof BlockLiquid;
|
||||
}
|
||||
|
||||
public static boolean isFlowing(IBlockState state) {
|
||||
// Will be IFluidState in 1.13
|
||||
return state.getBlock() instanceof BlockLiquid
|
||||
&& state.getPropertyKeys().contains(BlockLiquid.LEVEL)
|
||||
&& state.getValue(BlockLiquid.LEVEL) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,10 +29,11 @@ import baritone.behavior.Behavior;
|
||||
import baritone.behavior.PathingBehavior;
|
||||
import baritone.cache.ChunkPacker;
|
||||
import baritone.cache.Waypoint;
|
||||
import baritone.cache.WorldProvider;
|
||||
import baritone.pathing.calc.AbstractNodeCostSearch;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.movement.Moves;
|
||||
import baritone.process.CustomGoalProcess;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.multiplayer.ChunkProviderClient;
|
||||
import net.minecraft.entity.Entity;
|
||||
@@ -46,6 +47,35 @@ import java.util.stream.Stream;
|
||||
|
||||
public class ExampleBaritoneControl extends Behavior implements Helper {
|
||||
|
||||
private static final String HELP_MSG =
|
||||
"baritone - Output settings into chat\n" +
|
||||
"settings - Same as baritone\n" +
|
||||
"goal - Create a goal (one number is '<Y>', two is '<X> <Z>', three is '<X> <Y> <Z>, 'clear' to clear)\n" +
|
||||
"path - Go towards goal\n" +
|
||||
"repack - (debug) Repacks chunk cache\n" +
|
||||
"rescan - (debug) Same as repack\n" +
|
||||
"axis - Paths towards the closest axis or diagonal axis, at y=120\n" +
|
||||
"cancel - Cancels current path\n" +
|
||||
"forcecancel - sudo cancel (only use if very glitched, try toggling 'pause' first)\n" +
|
||||
"gc - Calls System.gc();\n" +
|
||||
"invert - Runs away from the goal instead of towards it\n" +
|
||||
"follow - Follows a player 'follow username'\n" +
|
||||
"reloadall - (debug) Reloads chunk cache\n" +
|
||||
"saveall - (debug) Saves chunk cache\n" +
|
||||
"find - (debug) outputs how many blocks of a certain type are within the cache\n" +
|
||||
"mine - Paths to and mines specified blocks 'mine x_ore y_ore ...'\n" +
|
||||
"thisway - Creates a goal X blocks where you're facing\n" +
|
||||
"list - Lists waypoints under a category\n" +
|
||||
"get - Same as list\n" +
|
||||
"show - Same as list\n" +
|
||||
"save - Saves a waypoint (works but don't try to make sense of it)\n" +
|
||||
"goto - Paths towards specified block or waypoint\n" +
|
||||
"spawn - Paths towards world spawn or your most recent bed right-click\n" +
|
||||
"sethome - Sets \"home\"\n" +
|
||||
"home - Paths towards \"home\" \n" +
|
||||
"costs - (debug) all movement costs from current location\n" +
|
||||
"damn - Daniel ";
|
||||
|
||||
public ExampleBaritoneControl(Baritone baritone) {
|
||||
super(baritone);
|
||||
}
|
||||
@@ -70,6 +100,7 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
|
||||
public boolean runCommand(String msg0) {
|
||||
String msg = msg0.toLowerCase(Locale.US).trim(); // don't reassign the argument LOL
|
||||
PathingBehavior pathingBehavior = baritone.getPathingBehavior();
|
||||
CustomGoalProcess customGoalProcess = baritone.getCustomGoalProcess();
|
||||
List<Settings.Setting<Boolean>> toggleable = Baritone.settings().getAllValuesByType(Boolean.class);
|
||||
for (Settings.Setting<Boolean> setting : toggleable) {
|
||||
if (msg.equalsIgnoreCase(setting.getName())) {
|
||||
@@ -85,6 +116,12 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (msg.equals("") || msg.equals("help") || msg.equals("?")) {
|
||||
for (String line : HELP_MSG.split("\n")) {
|
||||
logDirect(line);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (msg.contains(" ")) {
|
||||
String[] data = msg.split(" ");
|
||||
if (data.length == 2) {
|
||||
@@ -151,21 +188,19 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
|
||||
logDirect("unable to parse integer " + ex);
|
||||
return true;
|
||||
}
|
||||
pathingBehavior.setGoal(goal);
|
||||
customGoalProcess.setGoal(goal);
|
||||
logDirect("Goal: " + goal);
|
||||
return true;
|
||||
}
|
||||
if (msg.equals("path")) {
|
||||
if (!pathingBehavior.path()) {
|
||||
if (pathingBehavior.getGoal() == null) {
|
||||
logDirect("No goal.");
|
||||
} else {
|
||||
if (pathingBehavior.getGoal().isInGoal(playerFeet())) {
|
||||
logDirect("Already in goal");
|
||||
} else {
|
||||
logDirect("Currently executing a path. Please cancel it first.");
|
||||
}
|
||||
}
|
||||
if (pathingBehavior.getGoal() == null) {
|
||||
logDirect("No goal.");
|
||||
} else if (pathingBehavior.getGoal().isInGoal(playerFeet())) {
|
||||
logDirect("Already in goal");
|
||||
} else if (pathingBehavior.isPathing()) {
|
||||
logDirect("Currently executing a path. Please cancel it first.");
|
||||
} else {
|
||||
customGoalProcess.setGoalAndPath(pathingBehavior.getGoal());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -179,7 +214,7 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
|
||||
Chunk chunk = cli.getLoadedChunk(x, z);
|
||||
if (chunk != null) {
|
||||
count++;
|
||||
WorldProvider.INSTANCE.getCurrentWorld().getCachedWorld().queueForPacking(chunk);
|
||||
baritone.getWorldProvider().getCurrentWorld().getCachedWorld().queueForPacking(chunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -187,21 +222,16 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
|
||||
return true;
|
||||
}
|
||||
if (msg.equals("axis")) {
|
||||
pathingBehavior.setGoal(new GoalAxis());
|
||||
pathingBehavior.path();
|
||||
customGoalProcess.setGoalAndPath(new GoalAxis());
|
||||
return true;
|
||||
}
|
||||
if (msg.equals("cancel") || msg.equals("stop")) {
|
||||
baritone.getMineBehavior().cancel();
|
||||
baritone.getFollowBehavior().cancel();
|
||||
pathingBehavior.cancel();
|
||||
pathingBehavior.cancelEverything();
|
||||
logDirect("ok canceled");
|
||||
return true;
|
||||
}
|
||||
if (msg.equals("forcecancel")) {
|
||||
baritone.getMineBehavior().cancel();
|
||||
baritone.getFollowBehavior().cancel();
|
||||
pathingBehavior.cancel();
|
||||
pathingBehavior.cancelEverything();
|
||||
AbstractNodeCostSearch.forceCancel();
|
||||
pathingBehavior.forceCancel();
|
||||
logDirect("ok force canceled");
|
||||
@@ -224,15 +254,17 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
|
||||
logDirect("Inverting goal of player feet");
|
||||
runAwayFrom = playerFeet();
|
||||
}
|
||||
pathingBehavior.setGoal(new GoalRunAway(1, runAwayFrom) {
|
||||
customGoalProcess.setGoalAndPath(new GoalRunAway(1, runAwayFrom) {
|
||||
@Override
|
||||
public boolean isInGoal(BlockPos pos) {
|
||||
public boolean isInGoal(int x, int y, int z) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
if (!pathingBehavior.path()) {
|
||||
logDirect("Currently executing a path. Please cancel it first.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (msg.startsWith("followplayers")) {
|
||||
baritone.getFollowProcess().follow(EntityPlayer.class::isInstance); // O P P A
|
||||
logDirect("Following any players");
|
||||
return true;
|
||||
}
|
||||
if (msg.startsWith("follow")) {
|
||||
@@ -252,23 +284,24 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
|
||||
logDirect("Not found");
|
||||
return true;
|
||||
}
|
||||
baritone.getFollowBehavior().follow(toFollow.get());
|
||||
Entity effectivelyFinal = toFollow.get();
|
||||
baritone.getFollowProcess().follow(x -> effectivelyFinal.equals(x));
|
||||
logDirect("Following " + toFollow.get());
|
||||
return true;
|
||||
}
|
||||
if (msg.equals("reloadall")) {
|
||||
WorldProvider.INSTANCE.getCurrentWorld().getCachedWorld().reloadAllFromDisk();
|
||||
baritone.getWorldProvider().getCurrentWorld().getCachedWorld().reloadAllFromDisk();
|
||||
logDirect("ok");
|
||||
return true;
|
||||
}
|
||||
if (msg.equals("saveall")) {
|
||||
WorldProvider.INSTANCE.getCurrentWorld().getCachedWorld().save();
|
||||
baritone.getWorldProvider().getCurrentWorld().getCachedWorld().save();
|
||||
logDirect("ok");
|
||||
return true;
|
||||
}
|
||||
if (msg.startsWith("find")) {
|
||||
String blockType = msg.substring(4).trim();
|
||||
LinkedList<BlockPos> locs = WorldProvider.INSTANCE.getCurrentWorld().getCachedWorld().getLocationsOf(blockType, 1, 4);
|
||||
LinkedList<BlockPos> locs = baritone.getWorldProvider().getCurrentWorld().getCachedWorld().getLocationsOf(blockType, 1, 4);
|
||||
logDirect("Have " + locs.size() + " locations");
|
||||
for (BlockPos pos : locs) {
|
||||
Block actually = BlockStateInterface.get(pos).getBlock();
|
||||
@@ -284,7 +317,7 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
|
||||
int quantity = Integer.parseInt(blockTypes[1]);
|
||||
Block block = ChunkPacker.stringToBlock(blockTypes[0]);
|
||||
Objects.requireNonNull(block);
|
||||
baritone.getMineBehavior().mine(quantity, block);
|
||||
baritone.getMineProcess().mine(quantity, block);
|
||||
logDirect("Will mine " + quantity + " " + blockTypes[0]);
|
||||
return true;
|
||||
} catch (NumberFormatException | ArrayIndexOutOfBoundsException | NullPointerException ex) {}
|
||||
@@ -295,14 +328,14 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
|
||||
}
|
||||
|
||||
}
|
||||
baritone.getMineBehavior().mine(0, blockTypes);
|
||||
baritone.getMineProcess().mineByName(0, blockTypes);
|
||||
logDirect("Started mining blocks of type " + Arrays.toString(blockTypes));
|
||||
return true;
|
||||
}
|
||||
if (msg.startsWith("thisway")) {
|
||||
try {
|
||||
Goal goal = GoalXZ.fromDirection(playerFeetAsVec(), player().rotationYaw, Double.parseDouble(msg.substring(7).trim()));
|
||||
pathingBehavior.setGoal(goal);
|
||||
customGoalProcess.setGoal(goal);
|
||||
logDirect("Goal: " + goal);
|
||||
} catch (NumberFormatException ex) {
|
||||
logDirect("Error unable to parse '" + msg.substring(7).trim() + "' to a double.");
|
||||
@@ -320,7 +353,7 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
|
||||
logDirect("Not a valid tag. Tags are: " + Arrays.asList(Waypoint.Tag.values()).toString().toLowerCase());
|
||||
return true;
|
||||
}
|
||||
Set<IWaypoint> waypoints = WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().getByTag(tag);
|
||||
Set<IWaypoint> waypoints = baritone.getWorldProvider().getCurrentWorld().getWaypoints().getByTag(tag);
|
||||
// might as well show them from oldest to newest
|
||||
List<IWaypoint> sorted = new ArrayList<>(waypoints);
|
||||
sorted.sort(Comparator.comparingLong(IWaypoint::getCreationTimestamp));
|
||||
@@ -348,7 +381,7 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
|
||||
}
|
||||
name = parts[0];
|
||||
}
|
||||
WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().addWaypoint(new Waypoint(name, Waypoint.Tag.USER, pos));
|
||||
baritone.getWorldProvider().getCurrentWorld().getWaypoints().addWaypoint(new Waypoint(name, Waypoint.Tag.USER, pos));
|
||||
logDirect("Saved user defined position " + pos + " under name '" + name + "'. Say 'goto " + name + "' to set goal, say 'list user' to list custom waypoints.");
|
||||
return true;
|
||||
}
|
||||
@@ -365,69 +398,59 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
|
||||
Block block = ChunkPacker.stringToBlock(mining);
|
||||
//logDirect("Not a valid tag. Tags are: " + Arrays.asList(Waypoint.Tag.values()).toString().toLowerCase());
|
||||
if (block == null) {
|
||||
waypoint = WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().getAllWaypoints().stream().filter(w -> w.getName().equalsIgnoreCase(mining)).max(Comparator.comparingLong(IWaypoint::getCreationTimestamp)).orElse(null);
|
||||
waypoint = baritone.getWorldProvider().getCurrentWorld().getWaypoints().getAllWaypoints().stream().filter(w -> w.getName().equalsIgnoreCase(mining)).max(Comparator.comparingLong(IWaypoint::getCreationTimestamp)).orElse(null);
|
||||
if (waypoint == null) {
|
||||
logDirect("No locations for " + mining + " known, cancelling");
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
List<BlockPos> locs = baritone.getMineBehavior().searchWorld(Collections.singletonList(block), 64);
|
||||
if (locs.isEmpty()) {
|
||||
logDirect("No locations for " + mining + " known, cancelling");
|
||||
return true;
|
||||
}
|
||||
pathingBehavior.setGoal(new GoalComposite(locs.stream().map(GoalGetToBlock::new).toArray(Goal[]::new)));
|
||||
pathingBehavior.path();
|
||||
baritone.getGetToBlockProcess().getToBlock(block);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
waypoint = WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().getMostRecentByTag(tag);
|
||||
waypoint = baritone.getWorldProvider().getCurrentWorld().getWaypoints().getMostRecentByTag(tag);
|
||||
if (waypoint == null) {
|
||||
logDirect("None saved for tag " + tag);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Goal goal = new GoalBlock(waypoint.getLocation());
|
||||
pathingBehavior.setGoal(goal);
|
||||
if (!pathingBehavior.path() && !goal.isInGoal(playerFeet())) {
|
||||
logDirect("Currently executing a path. Please cancel it first.");
|
||||
}
|
||||
customGoalProcess.setGoalAndPath(goal);
|
||||
return true;
|
||||
}
|
||||
if (msg.equals("spawn") || msg.equals("bed")) {
|
||||
IWaypoint waypoint = WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().getMostRecentByTag(Waypoint.Tag.BED);
|
||||
IWaypoint waypoint = baritone.getWorldProvider().getCurrentWorld().getWaypoints().getMostRecentByTag(Waypoint.Tag.BED);
|
||||
if (waypoint == null) {
|
||||
BlockPos spawnPoint = player().getBedLocation();
|
||||
// for some reason the default spawnpoint is underground sometimes
|
||||
Goal goal = new GoalXZ(spawnPoint.getX(), spawnPoint.getZ());
|
||||
logDirect("spawn not saved, defaulting to world spawn. set goal to " + goal);
|
||||
pathingBehavior.setGoal(goal);
|
||||
customGoalProcess.setGoalAndPath(goal);
|
||||
} else {
|
||||
Goal goal = new GoalBlock(waypoint.getLocation());
|
||||
pathingBehavior.setGoal(goal);
|
||||
Goal goal = new GoalGetToBlock(waypoint.getLocation());
|
||||
customGoalProcess.setGoalAndPath(goal);
|
||||
logDirect("Set goal to most recent bed " + goal);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (msg.equals("sethome")) {
|
||||
WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().addWaypoint(new Waypoint("", Waypoint.Tag.HOME, playerFeet()));
|
||||
baritone.getWorldProvider().getCurrentWorld().getWaypoints().addWaypoint(new Waypoint("", Waypoint.Tag.HOME, playerFeet()));
|
||||
logDirect("Saved. Say home to set goal.");
|
||||
return true;
|
||||
}
|
||||
if (msg.equals("home")) {
|
||||
IWaypoint waypoint = WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().getMostRecentByTag(Waypoint.Tag.HOME);
|
||||
IWaypoint waypoint = baritone.getWorldProvider().getCurrentWorld().getWaypoints().getMostRecentByTag(Waypoint.Tag.HOME);
|
||||
if (waypoint == null) {
|
||||
logDirect("home not saved");
|
||||
} else {
|
||||
Goal goal = new GoalBlock(waypoint.getLocation());
|
||||
pathingBehavior.setGoal(goal);
|
||||
pathingBehavior.path();
|
||||
customGoalProcess.setGoalAndPath(goal);
|
||||
logDirect("Going to saved home " + goal);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (msg.equals("costs")) {
|
||||
List<Movement> moves = Stream.of(Moves.values()).map(x -> x.apply0(playerFeet())).collect(Collectors.toCollection(ArrayList::new));
|
||||
List<Movement> moves = Stream.of(Moves.values()).map(x -> x.apply0(new CalculationContext(), playerFeet())).collect(Collectors.toCollection(ArrayList::new));
|
||||
while (moves.contains(null)) {
|
||||
moves.remove(null);
|
||||
}
|
||||
@@ -443,11 +466,6 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (msg.equals("pause")) {
|
||||
boolean enabled = pathingBehavior.toggle();
|
||||
logDirect("Pathing Behavior has " + (enabled ? "resumed" : "paused") + ".");
|
||||
return true;
|
||||
}
|
||||
if (msg.equals("damn")) {
|
||||
logDirect("daniel");
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import baritone.api.utils.Rotation;
|
||||
import net.minecraft.block.BlockSlab;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.client.multiplayer.PlayerControllerMP;
|
||||
import net.minecraft.client.multiplayer.WorldClient;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
@@ -51,10 +52,23 @@ public interface Helper {
|
||||
Minecraft mc = Minecraft.getMinecraft();
|
||||
|
||||
default EntityPlayerSP player() {
|
||||
if (!mc.isCallingFromMinecraftThread()) {
|
||||
throw new IllegalStateException("h00000000");
|
||||
}
|
||||
return mc.player;
|
||||
}
|
||||
|
||||
default PlayerControllerMP playerController() { // idk
|
||||
if (!mc.isCallingFromMinecraftThread()) {
|
||||
throw new IllegalStateException("h00000000");
|
||||
}
|
||||
return mc.playerController;
|
||||
}
|
||||
|
||||
default WorldClient world() {
|
||||
if (!mc.isCallingFromMinecraftThread()) {
|
||||
throw new IllegalStateException("h00000000");
|
||||
}
|
||||
return mc.world;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,8 +17,13 @@
|
||||
|
||||
package baritone.utils;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.event.events.TickEvent;
|
||||
import baritone.behavior.Behavior;
|
||||
import net.minecraft.client.settings.KeyBinding;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -30,16 +35,16 @@ import java.util.Map;
|
||||
* @author Brady
|
||||
* @since 7/31/2018 11:20 PM
|
||||
*/
|
||||
public final class InputOverrideHandler implements Helper {
|
||||
public final class InputOverrideHandler extends Behavior implements Helper {
|
||||
|
||||
public InputOverrideHandler(Baritone baritone) {
|
||||
super(baritone);
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps keybinds to whether or not we are forcing their state down.
|
||||
* Maps inputs to whether or not we are forcing their state down.
|
||||
*/
|
||||
private final Map<KeyBinding, Boolean> inputForceStateMap = new HashMap<>();
|
||||
|
||||
public final void clearAllKeys() {
|
||||
inputForceStateMap.clear();
|
||||
}
|
||||
private final Map<Input, Boolean> inputForceStateMap = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Returns whether or not we are forcing down the specified {@link KeyBinding}.
|
||||
@@ -48,7 +53,17 @@ public final class InputOverrideHandler implements Helper {
|
||||
* @return Whether or not it is being forced down
|
||||
*/
|
||||
public final boolean isInputForcedDown(KeyBinding key) {
|
||||
return inputForceStateMap.getOrDefault(key, false);
|
||||
return isInputForcedDown(Input.getInputForBind(key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not we are forcing down the specified {@link Input}.
|
||||
*
|
||||
* @param input The input
|
||||
* @return Whether or not it is being forced down
|
||||
*/
|
||||
public final boolean isInputForcedDown(Input input) {
|
||||
return input == null ? false : this.inputForceStateMap.getOrDefault(input, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,11 +73,47 @@ public final class InputOverrideHandler implements Helper {
|
||||
* @param forced Whether or not the state is being forced
|
||||
*/
|
||||
public final void setInputForceState(Input input, boolean forced) {
|
||||
inputForceStateMap.put(input.getKeyBinding(), forced);
|
||||
this.inputForceStateMap.put(input, forced);
|
||||
}
|
||||
|
||||
/**
|
||||
* An {@link Enum} representing the possible inputs that we may want to force.
|
||||
* Clears the override state for all keys
|
||||
*/
|
||||
public final void clearAllKeys() {
|
||||
this.inputForceStateMap.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onProcessKeyBinds() {
|
||||
// Simulate the key being held down this tick
|
||||
for (InputOverrideHandler.Input input : Input.values()) {
|
||||
KeyBinding keyBinding = input.getKeyBinding();
|
||||
|
||||
if (isInputForcedDown(keyBinding) && !keyBinding.isKeyDown()) {
|
||||
int keyCode = keyBinding.getKeyCode();
|
||||
|
||||
if (keyCode < Keyboard.KEYBOARD_SIZE) {
|
||||
KeyBinding.onTick(keyCode < 0 ? keyCode + 100 : keyCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onTick(TickEvent event) {
|
||||
if (event.getType() == TickEvent.Type.OUT) {
|
||||
return;
|
||||
}
|
||||
if (Baritone.settings().leftClickWorkaround.get()) {
|
||||
boolean stillClick = BlockBreakHelper.tick(isInputForcedDown(Input.CLICK_LEFT.keyBinding));
|
||||
setInputForceState(Input.CLICK_LEFT, stillClick);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An {@link Enum} representing the inputs that control the player's
|
||||
* behavior. This includes moving, interacting with blocks, jumping,
|
||||
* sneaking, and sprinting.
|
||||
*/
|
||||
public enum Input {
|
||||
|
||||
@@ -111,6 +162,11 @@ public final class InputOverrideHandler implements Helper {
|
||||
*/
|
||||
SPRINT(mc.gameSettings.keyBindSprint);
|
||||
|
||||
/**
|
||||
* Map of {@link KeyBinding} to {@link Input}. Values should be queried through {@link #getInputForBind(KeyBinding)}
|
||||
*/
|
||||
private static final Map<KeyBinding, Input> bindToInputMap = new HashMap<>();
|
||||
|
||||
/**
|
||||
* The actual game {@link KeyBinding} being forced.
|
||||
*/
|
||||
@@ -126,5 +182,15 @@ public final class InputOverrideHandler implements Helper {
|
||||
public final KeyBinding getKeyBinding() {
|
||||
return this.keyBinding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the {@link Input} constant that is associated with the specified {@link KeyBinding}.
|
||||
*
|
||||
* @param binding The {@link KeyBinding} to find the associated {@link Input} for
|
||||
* @return The {@link Input} associated with the specified {@link KeyBinding}
|
||||
*/
|
||||
public static Input getInputForBind(KeyBinding binding) {
|
||||
return bindToInputMap.computeIfAbsent(binding, b -> Arrays.stream(values()).filter(input -> input.keyBinding == b).findFirst().orElse(null));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.utils;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.event.events.TickEvent;
|
||||
import baritone.api.event.listener.AbstractGameEventListener;
|
||||
import baritone.api.pathing.goals.Goal;
|
||||
import baritone.api.process.IBaritoneProcess;
|
||||
import baritone.api.process.PathingCommand;
|
||||
import baritone.behavior.PathingBehavior;
|
||||
import baritone.pathing.calc.AbstractNodeCostSearch;
|
||||
import baritone.pathing.path.PathExecutor;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class PathingControlManager {
|
||||
private final Baritone baritone;
|
||||
private final HashSet<IBaritoneProcess> processes; // unGh
|
||||
private IBaritoneProcess inControlLastTick;
|
||||
private IBaritoneProcess inControlThisTick;
|
||||
private PathingCommand command;
|
||||
|
||||
public PathingControlManager(Baritone baritone) {
|
||||
this.baritone = baritone;
|
||||
this.processes = new HashSet<>();
|
||||
baritone.registerEventListener(new AbstractGameEventListener() { // needs to be after all behavior ticks
|
||||
@Override
|
||||
public void onTick(TickEvent event) {
|
||||
if (event.getType() == TickEvent.Type.OUT) {
|
||||
return;
|
||||
}
|
||||
postTick();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void registerProcess(IBaritoneProcess process) {
|
||||
process.onLostControl(); // make sure it's reset
|
||||
processes.add(process);
|
||||
}
|
||||
|
||||
public void cancelEverything() {
|
||||
for (IBaritoneProcess proc : processes) {
|
||||
proc.onLostControl();
|
||||
if (proc.isActive() && !proc.isTemporary()) { // it's okay for a temporary thing (like combat pause) to maintain control even if you say to cancel
|
||||
// but not for a non temporary thing
|
||||
throw new IllegalStateException(proc.displayName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IBaritoneProcess inControlThisTick() {
|
||||
return inControlThisTick;
|
||||
}
|
||||
|
||||
public void preTick() {
|
||||
inControlLastTick = inControlThisTick;
|
||||
command = doTheStuff();
|
||||
if (command == null) {
|
||||
return;
|
||||
}
|
||||
PathingBehavior p = baritone.getPathingBehavior();
|
||||
switch (command.commandType) {
|
||||
case REQUEST_PAUSE:
|
||||
p.requestPause();
|
||||
break;
|
||||
case CANCEL_AND_SET_GOAL:
|
||||
p.secretInternalSetGoal(command.goal);
|
||||
p.cancelSegmentIfSafe();
|
||||
break;
|
||||
case FORCE_REVALIDATE_GOAL_AND_PATH:
|
||||
if (!p.isPathing() && !AbstractNodeCostSearch.getCurrentlyRunning().isPresent()) {
|
||||
p.secretInternalSetGoalAndPath(command.goal);
|
||||
}
|
||||
break;
|
||||
case REVALIDATE_GOAL_AND_PATH:
|
||||
if (!p.isPathing() && !AbstractNodeCostSearch.getCurrentlyRunning().isPresent()) {
|
||||
p.secretInternalSetGoalAndPath(command.goal);
|
||||
}
|
||||
break;
|
||||
case SET_GOAL_AND_PATH:
|
||||
// now this i can do
|
||||
if (command.goal != null) {
|
||||
baritone.getPathingBehavior().secretInternalSetGoalAndPath(command.goal);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
public void postTick() {
|
||||
// if we did this in pretick, it would suck
|
||||
// we use the time between ticks as calculation time
|
||||
// therefore, we only cancel and recalculate after the tick for the current path has executed
|
||||
// "it would suck" means it would actually execute a path every other tick
|
||||
if (command == null) {
|
||||
return;
|
||||
}
|
||||
PathingBehavior p = baritone.getPathingBehavior();
|
||||
switch (command.commandType) {
|
||||
case FORCE_REVALIDATE_GOAL_AND_PATH:
|
||||
if (command.goal == null || forceRevalidate(command.goal) || revalidateGoal(command.goal)) {
|
||||
// pwnage
|
||||
p.softCancelIfSafe();
|
||||
}
|
||||
p.secretInternalSetGoalAndPath(command.goal);
|
||||
break;
|
||||
case REVALIDATE_GOAL_AND_PATH:
|
||||
if (Baritone.settings().cancelOnGoalInvalidation.get() && (command.goal == null || revalidateGoal(command.goal))) {
|
||||
p.softCancelIfSafe();
|
||||
}
|
||||
p.secretInternalSetGoalAndPath(command.goal);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
public boolean forceRevalidate(Goal newGoal) {
|
||||
PathExecutor current = baritone.getPathingBehavior().getCurrent();
|
||||
if (current != null) {
|
||||
if (newGoal.isInGoal(current.getPath().getDest())) {
|
||||
return false;
|
||||
}
|
||||
return !newGoal.toString().equals(current.getPath().getGoal().toString());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean revalidateGoal(Goal newGoal) {
|
||||
PathExecutor current = baritone.getPathingBehavior().getCurrent();
|
||||
if (current != null) {
|
||||
Goal intended = current.getPath().getGoal();
|
||||
BlockPos end = current.getPath().getDest();
|
||||
if (intended.isInGoal(end) && !newGoal.isInGoal(end)) {
|
||||
// this path used to end in the goal
|
||||
// but the goal has changed, so there's no reason to continue...
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public PathingCommand doTheStuff() {
|
||||
List<IBaritoneProcess> inContention = processes.stream().filter(IBaritoneProcess::isActive).sorted(Comparator.comparingDouble(IBaritoneProcess::priority)).collect(Collectors.toList());
|
||||
boolean found = false;
|
||||
boolean cancelOthers = false;
|
||||
PathingCommand exec = null;
|
||||
for (int i = inContention.size() - 1; i >= 0; i--) { // truly a gamer moment
|
||||
IBaritoneProcess proc = inContention.get(i);
|
||||
if (found) {
|
||||
if (cancelOthers) {
|
||||
proc.onLostControl();
|
||||
}
|
||||
} else {
|
||||
exec = proc.onTick(Objects.equals(proc, inControlLastTick) && baritone.getPathingBehavior().calcFailedLastTick(), baritone.getPathingBehavior().isSafeToCancel());
|
||||
if (exec == null) {
|
||||
if (proc.isActive()) {
|
||||
throw new IllegalStateException(proc.displayName());
|
||||
}
|
||||
proc.onLostControl();
|
||||
continue;
|
||||
}
|
||||
//System.out.println("Executing command " + exec.commandType + " " + exec.goal + " from " + proc.displayName());
|
||||
inControlThisTick = proc;
|
||||
found = true;
|
||||
cancelOthers = !proc.isTemporary();
|
||||
}
|
||||
}
|
||||
return exec;
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@ package baritone.utils;
|
||||
import baritone.Baritone;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.enchantment.EnchantmentHelper;
|
||||
import net.minecraft.init.Enchantments;
|
||||
import net.minecraft.init.MobEffects;
|
||||
@@ -36,7 +37,7 @@ import java.util.function.Function;
|
||||
*
|
||||
* @author Avery, Brady, leijurv
|
||||
*/
|
||||
public class ToolSet implements Helper {
|
||||
public class ToolSet {
|
||||
/**
|
||||
* A cache mapping a {@link Block} to how long it will take to break
|
||||
* with this toolset, given the optimum tool is used.
|
||||
@@ -48,8 +49,11 @@ public class ToolSet implements Helper {
|
||||
*/
|
||||
private final Function<Block, Double> backendCalculation;
|
||||
|
||||
public ToolSet() {
|
||||
private final EntityPlayerSP player;
|
||||
|
||||
public ToolSet(EntityPlayerSP player) {
|
||||
breakStrengthCache = new HashMap<>();
|
||||
this.player = player;
|
||||
|
||||
if (Baritone.settings().considerPotionEffects.get()) {
|
||||
double amplifier = potionAmplifier();
|
||||
@@ -98,7 +102,7 @@ public class ToolSet implements Helper {
|
||||
int materialCost = Integer.MIN_VALUE;
|
||||
IBlockState blockState = b.getDefaultState();
|
||||
for (byte i = 0; i < 9; i++) {
|
||||
ItemStack itemStack = player().inventory.getStackInSlot(i);
|
||||
ItemStack itemStack = player.inventory.getStackInSlot(i);
|
||||
double v = calculateStrVsBlock(itemStack, blockState);
|
||||
if (v > value) {
|
||||
value = v;
|
||||
@@ -123,7 +127,7 @@ public class ToolSet implements Helper {
|
||||
* @return A double containing the destruction ticks with the best tool
|
||||
*/
|
||||
private double getBestDestructionTime(Block b) {
|
||||
ItemStack stack = player().inventory.getStackInSlot(getBestSlot(b));
|
||||
ItemStack stack = player.inventory.getStackInSlot(getBestSlot(b));
|
||||
return calculateStrVsBlock(stack, b.getDefaultState());
|
||||
}
|
||||
|
||||
@@ -164,11 +168,11 @@ public class ToolSet implements Helper {
|
||||
*/
|
||||
private double potionAmplifier() {
|
||||
double speed = 1;
|
||||
if (player().isPotionActive(MobEffects.HASTE)) {
|
||||
speed *= 1 + (player().getActivePotionEffect(MobEffects.HASTE).getAmplifier() + 1) * 0.2;
|
||||
if (player.isPotionActive(MobEffects.HASTE)) {
|
||||
speed *= 1 + (player.getActivePotionEffect(MobEffects.HASTE).getAmplifier() + 1) * 0.2;
|
||||
}
|
||||
if (player().isPotionActive(MobEffects.MINING_FATIGUE)) {
|
||||
switch (player().getActivePotionEffect(MobEffects.MINING_FATIGUE).getAmplifier()) {
|
||||
if (player.isPotionActive(MobEffects.MINING_FATIGUE)) {
|
||||
switch (player.getActivePotionEffect(MobEffects.MINING_FATIGUE).getAmplifier()) {
|
||||
case 0:
|
||||
speed *= 0.3;
|
||||
break;
|
||||
|
||||
@@ -17,9 +17,13 @@
|
||||
|
||||
package baritone.utils.accessor;
|
||||
|
||||
import baritone.cache.WorldProvider;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @see WorldProvider
|
||||
*
|
||||
* @author Brady
|
||||
* @since 8/4/2018 11:36 AM
|
||||
*/
|
||||
|
||||
@@ -17,9 +17,12 @@
|
||||
|
||||
package baritone.utils.accessor;
|
||||
|
||||
import net.minecraft.world.WorldProvider;
|
||||
import net.minecraft.world.chunk.storage.IChunkLoader;
|
||||
|
||||
/**
|
||||
* @see WorldProvider
|
||||
*
|
||||
* @author Brady
|
||||
* @since 8/4/2018 11:33 AM
|
||||
*/
|
||||
|
||||
@@ -17,10 +17,14 @@
|
||||
|
||||
package baritone.utils.pathing;
|
||||
|
||||
import baritone.utils.Helper;
|
||||
import net.minecraft.world.border.WorldBorder;
|
||||
|
||||
public class BetterWorldBorder implements Helper {
|
||||
/**
|
||||
* Essentially, a "rule" for the path finder, prevents proposed movements from attempting to venture
|
||||
* into the world border, and prevents actual movements from placing blocks in the world border.
|
||||
*/
|
||||
public class BetterWorldBorder {
|
||||
|
||||
private final double minX;
|
||||
private final double maxX;
|
||||
private final double minZ;
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.utils.pathing;
|
||||
|
||||
import baritone.api.BaritoneAPI;
|
||||
import baritone.api.pathing.calc.IPath;
|
||||
import baritone.api.pathing.goals.Goal;
|
||||
import baritone.pathing.path.CutoffPath;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.EmptyChunk;
|
||||
|
||||
public abstract class PathBase implements IPath {
|
||||
@Override
|
||||
public IPath cutoffAtLoadedChunks(World world) {
|
||||
for (int i = 0; i < positions().size(); i++) {
|
||||
BlockPos pos = positions().get(i);
|
||||
if (world.getChunk(pos) instanceof EmptyChunk) {
|
||||
return new CutoffPath(this, i);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPath staticCutoff(Goal destination) {
|
||||
if (length() < BaritoneAPI.getSettings().pathCutoffMinimumLength.get()) {
|
||||
return this;
|
||||
}
|
||||
if (destination == null || destination.isInGoal(getDest())) {
|
||||
return this;
|
||||
}
|
||||
double factor = BaritoneAPI.getSettings().pathCutoffFactor.get();
|
||||
int newLength = (int) ((length() - 1) * factor);
|
||||
return new CutoffPath(this, newLength);
|
||||
}
|
||||
}
|
||||
@@ -42,18 +42,6 @@ public enum PathingBlockType {
|
||||
}
|
||||
|
||||
public static PathingBlockType fromBits(boolean b1, boolean b2) {
|
||||
if (b1) {
|
||||
if (b2) {
|
||||
return PathingBlockType.SOLID;
|
||||
} else {
|
||||
return PathingBlockType.AVOID;
|
||||
}
|
||||
} else {
|
||||
if (b2) {
|
||||
return PathingBlockType.WATER;
|
||||
} else {
|
||||
return PathingBlockType.AIR;
|
||||
}
|
||||
}
|
||||
return b1 ? b2 ? SOLID : AVOID : b2 ? WATER : AIR;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user