revamp follow and fix some bugs in mine
This commit is contained in:
		| @@ -19,6 +19,9 @@ package baritone.api.process; | ||||
|  | ||||
| import net.minecraft.entity.Entity; | ||||
|  | ||||
| import java.util.List; | ||||
| import java.util.function.Predicate; | ||||
|  | ||||
| /** | ||||
|  * @author Brady | ||||
|  * @since 9/23/2018 | ||||
| @@ -26,16 +29,18 @@ import net.minecraft.entity.Entity; | ||||
| 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. | ||||
|   | ||||
| @@ -55,6 +55,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, | ||||
|  | ||||
|     private boolean safeToCancel; | ||||
|     private boolean pauseRequestedLastTick; | ||||
|     private boolean cancelRequested; | ||||
|     private boolean calcFailedLastTick; | ||||
|  | ||||
|     private volatile boolean isPathCalcInProgress; | ||||
| @@ -91,18 +92,22 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, | ||||
|             baritone.getPathingControlManager().cancelEverything(); | ||||
|             return; | ||||
|         } | ||||
|         baritone.getPathingControlManager().preTick(); | ||||
|         tickPath(); | ||||
|         dispatchEvents(); | ||||
|     } | ||||
|  | ||||
|     private void tickPath() { | ||||
|         baritone.getPathingControlManager().doTheThingWithTheStuff(); | ||||
|         if (pauseRequestedLastTick && safeToCancel) { | ||||
|             pauseRequestedLastTick = false; | ||||
|             baritone.getInputOverrideHandler().clearAllKeys(); | ||||
|             BlockBreakHelper.stopBreakingBlock(); | ||||
|             return; | ||||
|         } | ||||
|         if (cancelRequested) { | ||||
|             cancelRequested = false; | ||||
|             baritone.getInputOverrideHandler().clearAllKeys(); | ||||
|         } | ||||
|         if (current == null) { | ||||
|             return; | ||||
|         } | ||||
| @@ -273,6 +278,17 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, | ||||
|         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); | ||||
|   | ||||
| @@ -18,6 +18,8 @@ | ||||
| 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; | ||||
| @@ -27,6 +29,12 @@ 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 | ||||
|  * | ||||
| @@ -34,7 +42,8 @@ import net.minecraft.util.math.BlockPos; | ||||
|  */ | ||||
| public final class FollowProcess extends BaritoneProcessHelper implements IFollowProcess { | ||||
|  | ||||
|     private Entity following; | ||||
|     private Predicate<Entity> filter; | ||||
|     private List<Entity> cache; | ||||
|  | ||||
|     public FollowProcess(Baritone baritone) { | ||||
|         super(baritone, 1); | ||||
| @@ -42,39 +51,76 @@ public final class FollowProcess extends BaritoneProcessHelper implements IFollo | ||||
|  | ||||
|     @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 = following.getPosition(); | ||||
|             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 PathingCommand(new GoalNear(pos, Baritone.settings().followRadius.get()), PathingCommandType.FORCE_REVALIDATE_GOAL_AND_PATH); | ||||
|         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() { | ||||
|         return following != null; | ||||
|         if (filter == null) { | ||||
|             return false; | ||||
|         } | ||||
|         scanWorld(); | ||||
|         return !cache.isEmpty(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void onLostControl() { | ||||
|         following = null; | ||||
|         filter = null; | ||||
|         cache = null; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public String displayName() { | ||||
|         return "Follow " + following; | ||||
|         return "Follow " + cache; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void follow(Entity entity) { | ||||
|         this.following = entity; | ||||
|     public void follow(Predicate<Entity> filter) { | ||||
|         this.filter = filter; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Entity following() { | ||||
|         return this.following; | ||||
|     public List<Entity> following() { | ||||
|         return cache; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Predicate<Entity> currentFilter() { | ||||
|         return filter; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -241,6 +241,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro | ||||
|     } | ||||
|  | ||||
|     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++) { | ||||
| @@ -260,6 +261,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro | ||||
|         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()) || dropped.contains(pos)) | ||||
|   | ||||
| @@ -262,6 +262,11 @@ public class ExampleBaritoneControl extends Behavior implements Helper { | ||||
|             }); | ||||
|             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")) { | ||||
|             String name = msg.substring(6).trim(); | ||||
|             Optional<Entity> toFollow = Optional.empty(); | ||||
| @@ -279,7 +284,8 @@ public class ExampleBaritoneControl extends Behavior implements Helper { | ||||
|                 logDirect("Not found"); | ||||
|                 return true; | ||||
|             } | ||||
|             baritone.getFollowProcess().follow(toFollow.get()); | ||||
|             Entity effectivelyFinal = toFollow.get(); | ||||
|             baritone.getFollowProcess().follow(x -> effectivelyFinal.equals(x)); | ||||
|             logDirect("Following " + toFollow.get()); | ||||
|             return true; | ||||
|         } | ||||
|   | ||||
| @@ -18,10 +18,13 @@ | ||||
| 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; | ||||
|  | ||||
| @@ -36,10 +39,20 @@ public class PathingControlManager { | ||||
|     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) { | ||||
| @@ -61,38 +74,35 @@ public class PathingControlManager { | ||||
|         return inControlThisTick; | ||||
|     } | ||||
|  | ||||
|     public void doTheThingWithTheStuff() { | ||||
|     public void preTick() { | ||||
|         inControlLastTick = inControlThisTick; | ||||
|         PathingCommand cmd = doTheStuff(); | ||||
|         if (cmd == null) { | ||||
|         command = doTheStuff(); | ||||
|         if (command == null) { | ||||
|             return; | ||||
|         } | ||||
|         PathingBehavior p = baritone.getPathingBehavior(); | ||||
|         switch (cmd.commandType) { | ||||
|         switch (command.commandType) { | ||||
|             case REQUEST_PAUSE: | ||||
|                 p.requestPause(); | ||||
|                 break; | ||||
|             case CANCEL_AND_SET_GOAL: | ||||
|                 p.secretInternalSetGoal(cmd.goal); | ||||
|                 p.secretInternalSetGoal(command.goal); | ||||
|                 p.cancelSegmentIfSafe(); | ||||
|                 break; | ||||
|             case FORCE_REVALIDATE_GOAL_AND_PATH: | ||||
|                 p.secretInternalSetGoalAndPath(cmd.goal); | ||||
|                 if (cmd.goal == null || forceRevalidate(cmd.goal) || revalidateGoal(cmd.goal)) { | ||||
|                     // pwnage | ||||
|                     p.cancelSegmentIfSafe(); | ||||
|                 if (!p.isPathing() && !AbstractNodeCostSearch.getCurrentlyRunning().isPresent()) { | ||||
|                     p.secretInternalSetGoalAndPath(command.goal); | ||||
|                 } | ||||
|                 break; | ||||
|             case REVALIDATE_GOAL_AND_PATH: | ||||
|                 p.secretInternalSetGoalAndPath(cmd.goal); | ||||
|                 if (Baritone.settings().cancelOnGoalInvalidation.get() && (cmd.goal == null || revalidateGoal(cmd.goal))) { | ||||
|                     p.cancelSegmentIfSafe(); | ||||
|                 if (!p.isPathing() && !AbstractNodeCostSearch.getCurrentlyRunning().isPresent()) { | ||||
|                     p.secretInternalSetGoalAndPath(command.goal); | ||||
|                 } | ||||
|                 break; | ||||
|             case SET_GOAL_AND_PATH: | ||||
|                 // now this i can do | ||||
|                 if (cmd.goal != null) { | ||||
|                     baritone.getPathingBehavior().secretInternalSetGoalAndPath(cmd.goal); | ||||
|                 if (command.goal != null) { | ||||
|                     baritone.getPathingBehavior().secretInternalSetGoalAndPath(command.goal); | ||||
|                 } | ||||
|                 break; | ||||
|             default: | ||||
| @@ -100,6 +110,33 @@ public class PathingControlManager { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     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) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user