Compare commits
1 Commits
mapping
...
walkthroug
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
21b0f74a76 |
@@ -1,10 +1,3 @@
|
||||
# Baritone
|
||||
A Minecraft 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.
|
||||
|
||||
# Setup
|
||||
- Open the project in IntelliJ as a Gradle project
|
||||
- Run the Gradle task `setupDecompWorkspace`
|
||||
- Run the Gradle task `genIntellijRuns`
|
||||
- Restart IntelliJ and import Gradle changes
|
||||
- Select the "Minecraft Client" launch config and run
|
||||
the original version of the bot for Minecraft 1.8, rebuilt for 1.12.2.
|
||||
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
group 'baritone'
|
||||
version '1.0.0'
|
||||
version '1.0'
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
@@ -75,8 +75,3 @@ dependencies {
|
||||
}
|
||||
testImplementation 'junit:junit:4.12'
|
||||
}
|
||||
|
||||
mixin {
|
||||
defaultObfuscationEnv notch
|
||||
add sourceSets.main, 'mixins.baritone.refmap.json'
|
||||
}
|
||||
|
||||
@@ -1,337 +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 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone;
|
||||
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.item.Item;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Baritone's settings
|
||||
*
|
||||
* @author leijurv
|
||||
*/
|
||||
public class Settings {
|
||||
/**
|
||||
* Allow Baritone to break blocks
|
||||
*/
|
||||
public Setting<Boolean> allowBreak = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Allow Baritone to sprint
|
||||
*/
|
||||
public Setting<Boolean> allowSprint = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Allow Baritone to place blocks
|
||||
*/
|
||||
public Setting<Boolean> allowPlace = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* It doesn't actually take twenty ticks to place a block, this cost is so high
|
||||
* because we want to generally conserve blocks which might be limited
|
||||
*/
|
||||
public Setting<Double> blockPlacementPenalty = new Setting<>(20D);
|
||||
|
||||
/**
|
||||
* Allow Baritone to fall arbitrary distances and place a water bucket beneath it.
|
||||
* Reliability: questionable.
|
||||
*/
|
||||
public Setting<Boolean> allowWaterBucketFall = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Blocks that Baritone is allowed to place (as throwaway, for sneak bridging, pillaring, etc.)
|
||||
*/
|
||||
public Setting<List<Item>> acceptableThrowawayItems = new Setting<>(Arrays.asList(
|
||||
Item.getItemFromBlock(Blocks.DIRT),
|
||||
Item.getItemFromBlock(Blocks.COBBLESTONE),
|
||||
Item.getItemFromBlock(Blocks.NETHERRACK)
|
||||
));
|
||||
|
||||
/**
|
||||
* Enables some more advanced vine features. They're honestly just gimmicks and won't ever be needed in real
|
||||
* pathing scenarios. And they can cause Baritone to get trapped indefinitely in a strange scenario.
|
||||
*/
|
||||
public Setting<Boolean> allowVines = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* This is the big A* setting.
|
||||
* As long as your cost heuristic is an *underestimate*, it's guaranteed to find you the best path.
|
||||
* 3.5 is always an underestimate, even if you are sprinting.
|
||||
* If you're walking only (with allowSprint off) 4.6 is safe.
|
||||
* Any value below 3.5 is never worth it. It's just more computation to find the same path, guaranteed.
|
||||
* (specifically, it needs to be strictly slightly less than ActionCosts.WALK_ONE_BLOCK_COST, which is about 3.56)
|
||||
* <p>
|
||||
* Setting it at 3.57 or above with sprinting, or to 4.64 or above without sprinting, will result in
|
||||
* faster computation, at the cost of a suboptimal path. Any value above the walk / sprint cost will result
|
||||
* in it going straight at its goal, and not investigating alternatives, because the combined cost / heuristic
|
||||
* metric gets better and better with each block, instead of slightly worse.
|
||||
* <p>
|
||||
* Finding the optimal path is worth it, so it's the default.
|
||||
*/
|
||||
public Setting<Double> costHeuristic = this.new <Double>Setting<Double>(3.5D);
|
||||
|
||||
// a bunch of obscure internal A* settings that you probably don't want to change
|
||||
/**
|
||||
* The maximum number of times it will fetch outside loaded or cached chunks before assuming that
|
||||
* pathing has reached the end of the known area, and should therefore stop.
|
||||
*/
|
||||
public Setting<Integer> pathingMaxChunkBorderFetch = new Setting<>(50);
|
||||
|
||||
/**
|
||||
* See issue #18
|
||||
* Set to 1.0 to effectively disable this feature
|
||||
*/
|
||||
public Setting<Double> backtrackCostFavoringCoefficient = new Setting<>(0.9);
|
||||
|
||||
/**
|
||||
* Don't repropagate cost improvements below 0.01 ticks. They're all just floating point inaccuracies,
|
||||
* and there's no point.
|
||||
*/
|
||||
public Setting<Boolean> minimumImprovementRepropagation = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Use a pythagorean metric (as opposed to the more accurate hybrid diagonal / traverse).
|
||||
* You probably don't want this. It roughly triples nodes considered for no real advantage.
|
||||
*/
|
||||
public Setting<Boolean> pythagoreanMetric = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* After calculating a path (potentially through cached chunks), artificially cut it off to just the part that is
|
||||
* entirely within currently loaded chunks. Improves path safety because cached chunks are heavily simplified.
|
||||
*/
|
||||
public Setting<Boolean> cutoffAtLoadBoundary = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Stop 5 movements before anything that made the path COST_INF.
|
||||
* For example, if lava has spread across the path, don't walk right up to it then recalculate, it might
|
||||
* still be spreading lol
|
||||
*/
|
||||
public Setting<Integer> costVerificationLookahead = new Setting<>(5);
|
||||
|
||||
/**
|
||||
* Static cutoff factor. 0.9 means cut off the last 10% of all paths, regardless of chunk load state
|
||||
*/
|
||||
public Setting<Double> pathCutoffFactor = new Setting<>(0.9);
|
||||
|
||||
/**
|
||||
* Only apply static cutoff for paths of at least this length (in terms of number of movements)
|
||||
*/
|
||||
public Setting<Integer> pathCutoffMinimumLength = new Setting<>(30);
|
||||
|
||||
/**
|
||||
* Start planning the next path once the remaining movements tick estimates sum up to less than this value
|
||||
*/
|
||||
public Setting<Integer> planningTickLookAhead = new Setting<>(100);
|
||||
|
||||
/**
|
||||
* How far are you allowed to fall onto solid ground (without a water bucket)?
|
||||
* 3 won't deal any damage. But if you just want to get down the mountain quickly and you have
|
||||
* Feather Falling IV, you might set it a bit higher, like 4 or 5.
|
||||
*/
|
||||
public Setting<Integer> maxFallHeightNoWater = new Setting<>(3);
|
||||
|
||||
/**
|
||||
* How far are you allowed to fall onto solid ground (with a water bucket)?
|
||||
* It's not that reliable, so I've set it below what would kill an unarmored player (23)
|
||||
*/
|
||||
public Setting<Integer> maxFallHeightBucket = new Setting<>(20);
|
||||
|
||||
/**
|
||||
* Is it okay to sprint through a descend followed by a diagonal?
|
||||
* The player overshoots the landing, but not enough to fall off. And the diagonal ensures that there isn't
|
||||
* lava or anything that's !canWalkInto in that space, so it's technically safe, just a little sketchy.
|
||||
*/
|
||||
public Setting<Boolean> allowOvershootDiagonalDescend = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* If your goal is a GoalBlock in an unloaded chunk, assume it's far enough away that the Y coord
|
||||
* doesn't matter yet, and replace it with a GoalXZ to the same place before calculating a path.
|
||||
* Once a segment ends within chunk load range of the GoalBlock, it will go back to normal behavior
|
||||
* of considering the Y coord. The reasoning is that if your X and Z are 10,000 blocks away,
|
||||
* your Y coordinate's accuracy doesn't matter at all until you get much much closer.
|
||||
*/
|
||||
public Setting<Boolean> simplifyUnloadedYCoord = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* If a movement takes this many ticks more than its initial cost estimate, cancel it
|
||||
*/
|
||||
public Setting<Integer> movementTimeoutTicks = new Setting<>(100);
|
||||
|
||||
/**
|
||||
* Pathing can never take longer than this
|
||||
*/
|
||||
public Setting<Number> pathTimeoutMS = new Setting<>(4000L);
|
||||
|
||||
/**
|
||||
* For debugging, consider nodes much much slower
|
||||
*/
|
||||
public Setting<Boolean> slowPath = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* Milliseconds between each node
|
||||
*/
|
||||
public Setting<Number> slowPathTimeDelayMS = new Setting<>(100L);
|
||||
|
||||
/**
|
||||
* The alternative timeout number when slowPath is on
|
||||
*/
|
||||
public Setting<Number> slowPathTimeoutMS = new Setting<>(40000L);
|
||||
|
||||
/**
|
||||
* The big one. Download all chunks in simplified 2-bit format and save them for better very-long-distance pathing.
|
||||
*/
|
||||
public Setting<Boolean> chunkCaching = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Print all the debug messages to chat
|
||||
*/
|
||||
public Setting<Boolean> chatDebug = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Allow chat based control of Baritone. Most likely should be disabled when Baritone is imported for use in
|
||||
* something else
|
||||
*/
|
||||
public Setting<Boolean> chatControl = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Render the path
|
||||
*/
|
||||
public Setting<Boolean> renderPath = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Render the goal
|
||||
*/
|
||||
public Setting<Boolean> renderGoal = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Line width of the path when rendered, in pixels
|
||||
*/
|
||||
public Setting<Float> pathRenderLineWidthPixels = new Setting<>(5F);
|
||||
|
||||
/**
|
||||
* Line width of the goal when rendered, in pixels
|
||||
*/
|
||||
public Setting<Float> goalRenderLineWidthPixels = new Setting<>(3F);
|
||||
|
||||
/**
|
||||
* Start fading out the path at 20 movements ahead, and stop rendering it entirely 30 movements ahead.
|
||||
* Improves FPS.
|
||||
*/
|
||||
public Setting<Boolean> fadePath = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* Move without having to force the client-sided rotations
|
||||
*/
|
||||
public Setting<Boolean> freeLook = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Will cause some minor behavioral differences to ensure that Baritone works on anticheats.
|
||||
* <p>
|
||||
* At the moment this will silently set the player's rotations when using freeLook so you're not sprinting in
|
||||
* directions other than forward, which is picken up by more "advanced" anticheats like AAC, but not NCP.
|
||||
*/
|
||||
public Setting<Boolean> antiCheatCompatibility = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Exclusively use cached chunks for pathing
|
||||
*/
|
||||
public Setting<Boolean> pathThroughCachedOnly = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* Whether or not to use the "#" command prefix
|
||||
*/
|
||||
public Setting<Boolean> prefix = new Setting<>(false);
|
||||
|
||||
public final Map<String, Setting<?>> byLowerName;
|
||||
public final List<Setting<?>> allSettings;
|
||||
|
||||
public class Setting<T> {
|
||||
public T value;
|
||||
private String name;
|
||||
private final Class<T> klass;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Setting(T value) {
|
||||
if (value == null) {
|
||||
throw new IllegalArgumentException("Cannot determine value type class from null");
|
||||
}
|
||||
this.value = value;
|
||||
this.klass = (Class<T>) value.getClass();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public final <K extends T> K get() {
|
||||
return (K) value;
|
||||
}
|
||||
|
||||
public final String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Class<T> getValueClass() {
|
||||
return klass;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return name + ": " + value;
|
||||
}
|
||||
}
|
||||
|
||||
// here be dragons
|
||||
|
||||
{
|
||||
Field[] temp = getClass().getFields();
|
||||
HashMap<String, Setting<?>> tmpByName = new HashMap<>();
|
||||
List<Setting<?>> tmpAll = new ArrayList<>();
|
||||
try {
|
||||
for (Field field : temp) {
|
||||
if (field.getType().equals(Setting.class)) {
|
||||
Setting<?> setting = (Setting<?>) field.get(this);
|
||||
String name = field.getName();
|
||||
setting.name = name;
|
||||
name = name.toLowerCase();
|
||||
if (tmpByName.containsKey(name)) {
|
||||
throw new IllegalStateException("Duplicate setting name");
|
||||
}
|
||||
tmpByName.put(name, setting);
|
||||
tmpAll.add(setting);
|
||||
}
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
byLowerName = Collections.unmodifiableMap(tmpByName);
|
||||
allSettings = Collections.unmodifiableList(tmpAll);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> List<Setting<T>> getByValueType(Class<T> klass) {
|
||||
List<Setting<T>> result = new ArrayList<>();
|
||||
for (Setting<?> setting : allSettings) {
|
||||
if (setting.klass.equals(klass)) {
|
||||
result.add((Setting<T>) setting);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Settings() { }
|
||||
}
|
||||
@@ -1,53 +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 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.behavior.impl;
|
||||
|
||||
import baritone.behavior.Behavior;
|
||||
import baritone.chunk.Waypoint;
|
||||
import baritone.chunk.WorldProvider;
|
||||
import baritone.event.events.BlockInteractEvent;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import net.minecraft.block.BlockBed;
|
||||
|
||||
/**
|
||||
* A collection of event methods that are used to interact with Baritone's
|
||||
* waypoint system. This class probably needs a better name.
|
||||
*
|
||||
* @see Waypoint
|
||||
*
|
||||
* @author Brady
|
||||
* @since 8/22/2018
|
||||
*/
|
||||
public final class LocationTrackingBehavior extends Behavior {
|
||||
|
||||
public static final LocationTrackingBehavior INSTANCE = new LocationTrackingBehavior();
|
||||
|
||||
private LocationTrackingBehavior() {}
|
||||
|
||||
@Override
|
||||
public void onBlockInteract(BlockInteractEvent event) {
|
||||
if (event.getType() == BlockInteractEvent.Type.USE && BlockStateInterface.getBlock(event.getPos()) instanceof BlockBed) {
|
||||
WorldProvider.INSTANCE.getCurrentWorld().waypoints.addWaypoint(new Waypoint("bed", Waypoint.Tag.BED, event.getPos()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerDeath() {
|
||||
WorldProvider.INSTANCE.getCurrentWorld().waypoints.addWaypoint(new Waypoint("death", Waypoint.Tag.DEATH, playerFeet()));
|
||||
}
|
||||
}
|
||||
@@ -1,120 +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 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.behavior.impl;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.Settings;
|
||||
import baritone.behavior.Behavior;
|
||||
import baritone.event.events.PlayerUpdateEvent;
|
||||
import baritone.event.events.RelativeMoveEvent;
|
||||
import baritone.event.events.type.EventState;
|
||||
import baritone.utils.Rotation;
|
||||
|
||||
public class LookBehavior extends Behavior {
|
||||
|
||||
public static final LookBehavior INSTANCE = new LookBehavior();
|
||||
|
||||
private LookBehavior() {}
|
||||
|
||||
/**
|
||||
* Target's values are as follows:
|
||||
* <p>
|
||||
* getFirst() -> yaw
|
||||
* getSecond() -> pitch
|
||||
*/
|
||||
private Rotation target;
|
||||
|
||||
/**
|
||||
* Whether or not rotations are currently being forced
|
||||
*/
|
||||
private boolean force;
|
||||
|
||||
/**
|
||||
* The last player yaw angle. Used when free looking
|
||||
*
|
||||
* @see Settings#freeLook
|
||||
*/
|
||||
private float lastYaw;
|
||||
|
||||
public void updateTarget(Rotation target, boolean force) {
|
||||
this.target = target;
|
||||
this.force = force || !Baritone.settings().freeLook.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerUpdate(PlayerUpdateEvent event) {
|
||||
if (this.target == null)
|
||||
return;
|
||||
|
||||
// Whether or not we're going to silently set our angles
|
||||
boolean silent = Baritone.settings().antiCheatCompatibility.get();
|
||||
|
||||
switch (event.getState()) {
|
||||
case PRE: {
|
||||
if (this.force) {
|
||||
player().rotationYaw = this.target.getFirst();
|
||||
float oldPitch = player().rotationPitch;
|
||||
float desiredPitch = this.target.getSecond();
|
||||
player().rotationPitch = desiredPitch;
|
||||
if (desiredPitch == oldPitch) {
|
||||
nudgeToLevel();
|
||||
}
|
||||
this.target = null;
|
||||
} else if (silent) {
|
||||
this.lastYaw = player().rotationYaw;
|
||||
player().rotationYaw = this.target.getFirst();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case POST: {
|
||||
if (!this.force && silent) {
|
||||
player().rotationYaw = this.lastYaw;
|
||||
this.target = null;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerRelativeMove(RelativeMoveEvent event) {
|
||||
if (this.target != null && !this.force) {
|
||||
switch (event.getState()) {
|
||||
case PRE:
|
||||
this.lastYaw = player().rotationYaw;
|
||||
player().rotationYaw = this.target.getFirst();
|
||||
break;
|
||||
case POST:
|
||||
player().rotationYaw = this.lastYaw;
|
||||
|
||||
// If we have antiCheatCompatibility on, we're going to use the target value later in onPlayerUpdate()
|
||||
if (!Baritone.settings().antiCheatCompatibility.get())
|
||||
this.target = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void nudgeToLevel() {
|
||||
if (player().rotationPitch < -20) {
|
||||
player().rotationPitch++;
|
||||
} else if (player().rotationPitch > 10) {
|
||||
player().rotationPitch--;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,21 +15,20 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone;
|
||||
package baritone.bot;
|
||||
|
||||
import baritone.behavior.Behavior;
|
||||
import baritone.behavior.impl.LookBehavior;
|
||||
import baritone.behavior.impl.MemoryBehavior;
|
||||
import baritone.behavior.impl.PathingBehavior;
|
||||
import baritone.behavior.impl.LocationTrackingBehavior;
|
||||
import baritone.event.GameEventHandler;
|
||||
import baritone.map.Map;
|
||||
import baritone.utils.InputOverrideHandler;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import baritone.bot.behavior.Behavior;
|
||||
import baritone.bot.behavior.impl.LookBehavior;
|
||||
import baritone.bot.behavior.impl.MemoryBehavior;
|
||||
import baritone.bot.behavior.impl.PathingBehavior;
|
||||
import baritone.bot.event.GameEventHandler;
|
||||
import baritone.bot.pathing.movement.MovementHelper;
|
||||
import baritone.bot.utils.InputOverrideHandler;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.init.Blocks;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -53,7 +52,6 @@ public enum Baritone {
|
||||
private InputOverrideHandler inputOverrideHandler;
|
||||
private Settings settings;
|
||||
private List<Behavior> behaviors;
|
||||
private File dir;
|
||||
|
||||
/**
|
||||
* Whether or not Baritone is active
|
||||
@@ -68,23 +66,46 @@ public enum Baritone {
|
||||
this.inputOverrideHandler = new InputOverrideHandler();
|
||||
this.settings = new Settings();
|
||||
this.behaviors = new ArrayList<>();
|
||||
{
|
||||
registerBehavior(PathingBehavior.INSTANCE);
|
||||
registerBehavior(LookBehavior.INSTANCE);
|
||||
registerBehavior(MemoryBehavior.INSTANCE);
|
||||
registerBehavior(Map.INSTANCE);
|
||||
registerBehavior(LocationTrackingBehavior.INSTANCE);
|
||||
}
|
||||
|
||||
this.dir = new File(Minecraft.getMinecraft().gameDir, "baritone");
|
||||
if (!Files.exists(dir.toPath())) {
|
||||
try {
|
||||
Files.createDirectories(dir.toPath());
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
behaviors.add(PathingBehavior.INSTANCE);
|
||||
behaviors.add(LookBehavior.INSTANCE);
|
||||
behaviors.add(MemoryBehavior.INSTANCE);
|
||||
|
||||
this.active = true;
|
||||
this.initialized = true;
|
||||
Field[] temp = Blocks.class.getFields();
|
||||
try {
|
||||
for (Field field : temp) {
|
||||
if (field.getType().equals(Block.class)) {
|
||||
Block block = (Block) field.get(null);
|
||||
System.out.print(block);
|
||||
IBlockState state = block.getDefaultState();
|
||||
System.out.print(',');
|
||||
try {
|
||||
if (MovementHelper.canWalkThrough(null, state)) {
|
||||
System.out.print("true");
|
||||
} else {
|
||||
System.out.print("false");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.print("unknown");
|
||||
}
|
||||
System.out.print(',');
|
||||
try {
|
||||
if (MovementHelper.canWalkOn(null, state)) {
|
||||
System.out.print("true");
|
||||
} else {
|
||||
System.out.print("false");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.print("unknown");
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public final boolean isInitialized() {
|
||||
@@ -105,7 +126,6 @@ public enum Baritone {
|
||||
|
||||
public void registerBehavior(Behavior behavior) {
|
||||
this.behaviors.add(behavior);
|
||||
this.gameEventHandler.registerEventListener(behavior);
|
||||
}
|
||||
|
||||
public final boolean isActive() {
|
||||
@@ -119,8 +139,4 @@ public enum Baritone {
|
||||
public static Settings settings() {
|
||||
return Baritone.INSTANCE.settings; // yolo
|
||||
}
|
||||
|
||||
public final File getDir() {
|
||||
return this.dir;
|
||||
}
|
||||
}
|
||||
133
src/main/java/baritone/bot/Settings.java
Normal file
133
src/main/java/baritone/bot/Settings.java
Normal file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot;
|
||||
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.item.Item;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Baritone's settings
|
||||
*
|
||||
* @author leijurv
|
||||
*/
|
||||
public class Settings {
|
||||
public Setting<Boolean> allowBreak = new Setting<>(true);
|
||||
public Setting<Boolean> allowPlaceThrowaway = new Setting<>(true);
|
||||
/**
|
||||
* It doesn't actually take twenty ticks to place a block, this cost is so high
|
||||
* because we want to generally conserve blocks which might be limited
|
||||
*/
|
||||
public Setting<Double> blockPlacementPenalty = new Setting<>(20D);
|
||||
public Setting<Boolean> allowSprint = new Setting<>(true);
|
||||
public Setting<Double> costHeuristic = new <Double>Setting<Double>(4D);
|
||||
public Setting<Boolean> chuckCaching = new Setting<>(false);
|
||||
public Setting<Boolean> allowWaterBucketFall = new Setting<>(true);
|
||||
public Setting<Integer> planningTickLookAhead = new Setting<>(150);
|
||||
public Setting<Boolean> chatDebug = new Setting<>(true);
|
||||
public Setting<Boolean> chatControl = new Setting<>(true); // probably false in impact
|
||||
public Setting<Boolean> renderPath = new Setting<>(true);
|
||||
public Setting<Boolean> fadePath = new Setting<>(false); // give this a better name in the UI, like "better path fps" idk
|
||||
public Setting<Number> pathTimeoutMS = new Setting<>(4000L);
|
||||
public Setting<Boolean> slowPath = new Setting<>(false);
|
||||
public Setting<Number> slowPathTimeDelayMS = new Setting<>(100L);
|
||||
public Setting<Number> slowPathTimeoutMS = new Setting<>(40000L);
|
||||
public Setting<List<Item>> acceptableThrowawayItems = new Setting<>(Arrays.asList(
|
||||
Item.getItemFromBlock(Blocks.DIRT),
|
||||
Item.getItemFromBlock(Blocks.COBBLESTONE),
|
||||
Item.getItemFromBlock(Blocks.NETHERRACK)
|
||||
));
|
||||
public Setting<Boolean> renderGoal = new Setting<>(true);
|
||||
public Setting<Integer> pathingMaxChunkBorderFetch = new Setting<>(50);
|
||||
public Setting<Double> backtrackCostFavoringCoefficient = new Setting<>(0.9); // see issue #18
|
||||
public Setting<Float> pathRenderLineWidth = new Setting<>(5F);
|
||||
public Setting<Float> goalRenderLineWidth = new Setting<>(3F);
|
||||
|
||||
public final Map<String, Setting<?>> byName;
|
||||
public final List<Setting<?>> allSettings;
|
||||
|
||||
public class Setting<T> {
|
||||
public T value;
|
||||
private String name;
|
||||
private final Class<T> klass;
|
||||
|
||||
private Setting(T value) {
|
||||
if (value == null) {
|
||||
throw new IllegalArgumentException("Cannot determine value type class from null");
|
||||
}
|
||||
this.value = value;
|
||||
this.klass = (Class<T>) value.getClass();
|
||||
}
|
||||
|
||||
public final <K extends T> K get() {
|
||||
return (K) value;
|
||||
}
|
||||
|
||||
public final String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Class<T> getValueClass() {
|
||||
return klass;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return name + ": " + value;
|
||||
}
|
||||
}
|
||||
|
||||
// here be dragons
|
||||
|
||||
{
|
||||
Field[] temp = getClass().getFields();
|
||||
HashMap<String, Setting<?>> tmpByName = new HashMap<>();
|
||||
List<Setting<?>> tmpAll = new ArrayList<>();
|
||||
try {
|
||||
for (Field field : temp) {
|
||||
if (field.getType().equals(Setting.class)) {
|
||||
Setting<?> setting = (Setting<? extends Object>) field.get(this);
|
||||
String name = field.getName();
|
||||
setting.name = name;
|
||||
if (tmpByName.containsKey(name)) {
|
||||
throw new IllegalStateException("Duplicate setting name");
|
||||
}
|
||||
tmpByName.put(name, setting);
|
||||
tmpAll.add(setting);
|
||||
}
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
byName = Collections.unmodifiableMap(tmpByName);
|
||||
allSettings = Collections.unmodifiableList(tmpAll);
|
||||
}
|
||||
|
||||
public <T> List<Setting<T>> getByValueType(Class<T> klass) {
|
||||
ArrayList<Setting<T>> result = new ArrayList<>();
|
||||
for (Setting<?> setting : allSettings) {
|
||||
if (setting.klass.equals(klass)) {
|
||||
result.add((Setting<T>) setting);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Settings() { }
|
||||
}
|
||||
@@ -15,11 +15,10 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.behavior;
|
||||
package baritone.bot.behavior;
|
||||
|
||||
import baritone.event.listener.AbstractGameEventListener;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.interfaces.Toggleable;
|
||||
import baritone.bot.event.listener.AbstractGameEventListener;
|
||||
import baritone.bot.utils.Helper;
|
||||
|
||||
/**
|
||||
* A generic bot behavior.
|
||||
@@ -27,7 +26,7 @@ import baritone.utils.interfaces.Toggleable;
|
||||
* @author Brady
|
||||
* @since 8/1/2018 6:29 PM
|
||||
*/
|
||||
public class Behavior implements AbstractGameEventListener, Toggleable, Helper {
|
||||
public class Behavior implements AbstractGameEventListener, Helper {
|
||||
|
||||
/**
|
||||
* Whether or not this behavior is enabled
|
||||
@@ -39,7 +38,6 @@ public class Behavior implements AbstractGameEventListener, Toggleable, Helper {
|
||||
*
|
||||
* @return The new state.
|
||||
*/
|
||||
@Override
|
||||
public final boolean toggle() {
|
||||
return this.setEnabled(!this.enabled);
|
||||
}
|
||||
@@ -49,7 +47,6 @@ public class Behavior implements AbstractGameEventListener, Toggleable, Helper {
|
||||
*
|
||||
* @return The new state.
|
||||
*/
|
||||
@Override
|
||||
public final boolean setEnabled(boolean enabled) {
|
||||
boolean newState = getNewState(this.enabled, enabled);
|
||||
if (newState == this.enabled)
|
||||
@@ -82,7 +79,6 @@ public class Behavior implements AbstractGameEventListener, Toggleable, Helper {
|
||||
/**
|
||||
* @return Whether or not this {@link Behavior} is active.
|
||||
*/
|
||||
@Override
|
||||
public final boolean isEnabled() {
|
||||
return this.enabled;
|
||||
}
|
||||
62
src/main/java/baritone/bot/behavior/impl/LookBehavior.java
Normal file
62
src/main/java/baritone/bot/behavior/impl/LookBehavior.java
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.behavior.impl;
|
||||
|
||||
import baritone.bot.behavior.Behavior;
|
||||
import baritone.bot.utils.Rotation;
|
||||
|
||||
public class LookBehavior extends Behavior {
|
||||
|
||||
public static final LookBehavior INSTANCE = new LookBehavior();
|
||||
|
||||
private LookBehavior() {}
|
||||
|
||||
/**
|
||||
* Target's values are as follows:
|
||||
* <p>
|
||||
* getFirst() -> yaw
|
||||
* getSecond() -> pitch
|
||||
*/
|
||||
private Rotation target;
|
||||
|
||||
public void updateTarget(Rotation target) {
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerUpdate() {
|
||||
if (target != null) {
|
||||
player().rotationYaw = target.getFirst();
|
||||
float oldPitch = player().rotationPitch;
|
||||
float desiredPitch = target.getSecond();
|
||||
player().rotationPitch = desiredPitch;
|
||||
if (desiredPitch == oldPitch) {
|
||||
nudgeToLevel();
|
||||
}
|
||||
target = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void nudgeToLevel() {
|
||||
if (player().rotationPitch < -20) {
|
||||
player().rotationPitch++;
|
||||
} else if (player().rotationPitch > 10) {
|
||||
player().rotationPitch--;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,19 +15,19 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.behavior.impl;
|
||||
package baritone.bot.behavior.impl;
|
||||
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.Rotation;
|
||||
import baritone.utils.Utils;
|
||||
import baritone.bot.utils.BlockStateInterface;
|
||||
import baritone.bot.utils.Helper;
|
||||
import baritone.bot.utils.Rotation;
|
||||
import baritone.bot.utils.Utils;
|
||||
import net.minecraft.block.BlockFire;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.util.math.*;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import static baritone.utils.Utils.DEG_TO_RAD;
|
||||
import static baritone.bot.utils.Utils.DEG_TO_RAD;
|
||||
|
||||
public final class LookBehaviorUtils implements Helper {
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
package baritone.behavior.impl;
|
||||
package baritone.bot.behavior.impl;
|
||||
|
||||
import baritone.behavior.Behavior;
|
||||
import baritone.event.events.PacketEvent;
|
||||
import baritone.event.events.PlayerUpdateEvent;
|
||||
import baritone.event.events.type.EventState;
|
||||
import baritone.bot.behavior.Behavior;
|
||||
import baritone.bot.event.events.PacketEvent;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.Packet;
|
||||
import net.minecraft.network.play.client.CPacketCloseWindow;
|
||||
@@ -37,9 +35,8 @@ public class MemoryBehavior extends Behavior {
|
||||
private final Map<BlockPos, RememberedInventory> rememberedInventories = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void onPlayerUpdate(PlayerUpdateEvent event) {
|
||||
if (event.getState() == EventState.PRE)
|
||||
updateInventory();
|
||||
public void onPlayerUpdate() {
|
||||
updateInventory();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -15,27 +15,20 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.behavior.impl;
|
||||
package baritone.bot.behavior.impl;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.behavior.Behavior;
|
||||
import baritone.event.events.PathEvent;
|
||||
import baritone.event.events.PlayerUpdateEvent;
|
||||
import baritone.event.events.RenderEvent;
|
||||
import baritone.event.events.TickEvent;
|
||||
import baritone.pathing.calc.AStarPathFinder;
|
||||
import baritone.pathing.calc.AbstractNodeCostSearch;
|
||||
import baritone.pathing.calc.IPathFinder;
|
||||
import baritone.pathing.goals.Goal;
|
||||
import baritone.pathing.goals.GoalBlock;
|
||||
import baritone.pathing.goals.GoalXZ;
|
||||
import baritone.pathing.path.IPath;
|
||||
import baritone.pathing.path.PathExecutor;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.PathRenderer;
|
||||
import net.minecraft.init.Blocks;
|
||||
import baritone.bot.Baritone;
|
||||
import baritone.bot.behavior.Behavior;
|
||||
import baritone.bot.event.events.RenderEvent;
|
||||
import baritone.bot.event.events.TickEvent;
|
||||
import baritone.bot.pathing.calc.AStarPathFinder;
|
||||
import baritone.bot.pathing.calc.AbstractNodeCostSearch;
|
||||
import baritone.bot.pathing.calc.IPathFinder;
|
||||
import baritone.bot.pathing.goals.Goal;
|
||||
import baritone.bot.pathing.path.IPath;
|
||||
import baritone.bot.pathing.path.PathExecutor;
|
||||
import baritone.bot.utils.PathRenderer;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.chunk.EmptyChunk;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Collections;
|
||||
@@ -58,16 +51,11 @@ public class PathingBehavior extends Behavior {
|
||||
|
||||
private final Object pathPlanLock = new Object();
|
||||
|
||||
private boolean lastAutoJump;
|
||||
|
||||
private void dispatchPathEvent(PathEvent event) {
|
||||
new Thread(() -> Baritone.INSTANCE.getGameEventHandler().onPathEvent(event)).start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTick(TickEvent event) {
|
||||
if (event.getType() == TickEvent.Type.OUT) {
|
||||
this.cancel();
|
||||
current = null;
|
||||
next = null;
|
||||
return;
|
||||
}
|
||||
if (current == null) {
|
||||
@@ -79,7 +67,6 @@ public class PathingBehavior extends Behavior {
|
||||
current = null;
|
||||
if (goal == null || goal.isInGoal(playerFeet())) {
|
||||
displayChatMessageRaw("All done. At " + goal);
|
||||
dispatchPathEvent(PathEvent.AT_GOAL);
|
||||
next = null;
|
||||
return;
|
||||
}
|
||||
@@ -91,12 +78,10 @@ public class PathingBehavior extends Behavior {
|
||||
// but if we fail in the middle of current
|
||||
// we're nowhere close to our planned ahead path
|
||||
// so need to discard it sadly.
|
||||
dispatchPathEvent(PathEvent.DISCARD_NEXT);
|
||||
next = null;
|
||||
}
|
||||
if (next != null) {
|
||||
displayChatMessageRaw("Continuing on to planned next path");
|
||||
dispatchPathEvent(PathEvent.CONTINUING_ONTO_PLANNED_NEXT);
|
||||
current = next;
|
||||
next = null;
|
||||
return;
|
||||
@@ -104,12 +89,10 @@ public class PathingBehavior extends Behavior {
|
||||
// at this point, current just ended, but we aren't in the goal and have no plan for the future
|
||||
synchronized (pathCalcLock) {
|
||||
if (isPathCalcInProgress) {
|
||||
dispatchPathEvent(PathEvent.PATH_FINISHED_NEXT_STILL_CALCULATING);
|
||||
// if we aren't calculating right now
|
||||
return;
|
||||
}
|
||||
dispatchPathEvent(PathEvent.CALC_STARTED);
|
||||
findPathInNewThread(pathStart(), true, Optional.empty());
|
||||
findPathInNewThread(playerFeet(), true, Optional.empty());
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -120,7 +103,6 @@ public class PathingBehavior extends Behavior {
|
||||
if (next.getPath().positions().contains(playerFeet())) {
|
||||
// jump directly onto the next path
|
||||
displayChatMessageRaw("Splicing into planned next path early...");
|
||||
dispatchPathEvent(PathEvent.SPLICING_ONTO_NEXT_EARLY);
|
||||
current = next;
|
||||
next = null;
|
||||
return;
|
||||
@@ -143,28 +125,12 @@ public class PathingBehavior extends Behavior {
|
||||
if (ticksRemainingInSegment().get() < Baritone.settings().planningTickLookAhead.get()) {
|
||||
// and this path has 5 seconds or less left
|
||||
displayChatMessageRaw("Path almost over. Planning ahead...");
|
||||
dispatchPathEvent(PathEvent.NEXT_SEGMENT_CALC_STARTED);
|
||||
findPathInNewThread(current.getPath().getDest(), false, Optional.of(current.getPath()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerUpdate(PlayerUpdateEvent event) {
|
||||
if (current != null) {
|
||||
switch (event.getState()) {
|
||||
case PRE:
|
||||
lastAutoJump = mc.gameSettings.autoJump;
|
||||
mc.gameSettings.autoJump = false;
|
||||
break;
|
||||
case POST:
|
||||
mc.gameSettings.autoJump = lastAutoJump;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Optional<Double> ticksRemainingInSegment() {
|
||||
if (current == null) {
|
||||
return Optional.empty();
|
||||
@@ -176,17 +142,11 @@ public class PathingBehavior extends Behavior {
|
||||
this.goal = goal;
|
||||
}
|
||||
|
||||
public Goal getGoal() {
|
||||
return goal;
|
||||
}
|
||||
|
||||
public PathExecutor getCurrent() {
|
||||
return current;
|
||||
}
|
||||
|
||||
public PathExecutor getNext() {
|
||||
return next;
|
||||
}
|
||||
public PathExecutor getNext() {return next;}
|
||||
|
||||
public Optional<IPath> getPath() {
|
||||
return Optional.ofNullable(current).map(PathExecutor::getPath);
|
||||
@@ -208,20 +168,11 @@ public class PathingBehavior extends Behavior {
|
||||
if (isPathCalcInProgress) {
|
||||
return;
|
||||
}
|
||||
dispatchPathEvent(PathEvent.CALC_STARTED);
|
||||
findPathInNewThread(pathStart(), true, Optional.empty());
|
||||
findPathInNewThread(playerFeet(), true, Optional.empty());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public BlockPos pathStart() {
|
||||
BlockPos feet = playerFeet();
|
||||
if (BlockStateInterface.get(feet.down()).getBlock().equals(Blocks.AIR)) {
|
||||
return feet.down();
|
||||
}
|
||||
return feet;
|
||||
}
|
||||
|
||||
/**
|
||||
* In a new thread, pathfind to target blockpos
|
||||
*
|
||||
@@ -240,33 +191,19 @@ public class PathingBehavior extends Behavior {
|
||||
displayChatMessageRaw("Starting to search for path from " + start + " to " + goal);
|
||||
}
|
||||
|
||||
Optional<IPath> path = findPath(start, previous);
|
||||
if (Baritone.settings().cutoffAtLoadBoundary.get()) {
|
||||
path = path.map(IPath::cutoffAtLoadedChunks);
|
||||
}
|
||||
Optional<PathExecutor> executor = path.map(p -> p.staticCutoff(goal)).map(PathExecutor::new);
|
||||
synchronized (pathPlanLock) {
|
||||
if (current == null) {
|
||||
if (executor.isPresent()) {
|
||||
dispatchPathEvent(PathEvent.CALC_FINISHED_NOW_EXECUTING);
|
||||
current = executor.get();
|
||||
findPath(start, previous).map(IPath::cutoffAtLoadedChunks).map(PathExecutor::new).ifPresent(path -> {
|
||||
synchronized (pathPlanLock) {
|
||||
if (current == null) {
|
||||
current = path;
|
||||
} else {
|
||||
dispatchPathEvent(PathEvent.CALC_FAILED);
|
||||
}
|
||||
} else {
|
||||
if (next == null) {
|
||||
if (executor.isPresent()) {
|
||||
dispatchPathEvent(PathEvent.NEXT_SEGMENT_CALC_FINISHED);
|
||||
next = executor.get();
|
||||
if (next == null) {
|
||||
next = path;
|
||||
} else {
|
||||
dispatchPathEvent(PathEvent.NEXT_CALC_FAILED);
|
||||
throw new IllegalStateException("I have no idea what to do with this path");
|
||||
}
|
||||
} else {
|
||||
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())) {
|
||||
displayChatMessageRaw("Finished finding a path from " + start + " to " + goal + ". " + current.getPath().getNumNodesConsidered() + " nodes considered");
|
||||
@@ -288,18 +225,10 @@ public class PathingBehavior extends Behavior {
|
||||
* @return
|
||||
*/
|
||||
private Optional<IPath> findPath(BlockPos start, Optional<IPath> previous) {
|
||||
Goal goal = this.goal;
|
||||
if (goal == null) {
|
||||
displayChatMessageRaw("no goal");
|
||||
return Optional.empty();
|
||||
}
|
||||
if (Baritone.settings().simplifyUnloadedYCoord.get() && goal instanceof GoalBlock) {
|
||||
BlockPos pos = ((GoalBlock) goal).getGoalPos();
|
||||
if (world().getChunk(pos) instanceof EmptyChunk) {
|
||||
displayChatMessageRaw("Simplifying GoalBlock to GoalXZ due to distance");
|
||||
goal = new GoalXZ(pos.getX(), pos.getZ());
|
||||
}
|
||||
}
|
||||
try {
|
||||
IPathFinder pf = new AStarPathFinder(start, goal, previous.map(IPath::positions));
|
||||
return pf.calculate();
|
||||
@@ -336,7 +265,7 @@ public class PathingBehavior extends Behavior {
|
||||
PathRenderer.drawPath(current.getPath(), renderBegin, player(), partialTicks, Color.RED, Baritone.settings().fadePath.get(), 10, 20);
|
||||
}
|
||||
if (next != null && next.getPath() != null) {
|
||||
PathRenderer.drawPath(next.getPath(), 0, player(), partialTicks, Color.MAGENTA, Baritone.settings().fadePath.get(), 10, 20);
|
||||
PathRenderer.drawPath(next.getPath(), 0, player(), partialTicks, Color.GREEN, Baritone.settings().fadePath.get(), 10, 20);
|
||||
}
|
||||
|
||||
long split = System.nanoTime();
|
||||
131
src/main/java/baritone/bot/chunk/CachedChunk.java
Normal file
131
src/main/java/baritone/bot/chunk/CachedChunk.java
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.chunk;
|
||||
|
||||
import baritone.bot.utils.pathing.IBlockTypeAccess;
|
||||
import baritone.bot.utils.pathing.PathingBlockType;
|
||||
|
||||
import java.util.BitSet;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/3/2018 1:04 AM
|
||||
*/
|
||||
public final class CachedChunk implements IBlockTypeAccess {
|
||||
|
||||
/**
|
||||
* The size of the chunk data in bits. Equal to 16 KiB.
|
||||
* <p>
|
||||
* Chunks are 16x16x256, each block requires 2 bits.
|
||||
*/
|
||||
public static final int SIZE = 2 * 16 * 16 * 256;
|
||||
|
||||
/**
|
||||
* The size of the chunk data in bytes. Equal to 16 KiB.
|
||||
*/
|
||||
public static final int SIZE_IN_BYTES = SIZE / 8;
|
||||
|
||||
/**
|
||||
* An array of just 0s with the length of {@link CachedChunk#SIZE_IN_BYTES}
|
||||
*/
|
||||
public static final byte[] EMPTY_CHUNK = new byte[SIZE_IN_BYTES];
|
||||
|
||||
/**
|
||||
* The chunk x coordinate
|
||||
*/
|
||||
private final int x;
|
||||
|
||||
/**
|
||||
* The chunk z coordinate
|
||||
*/
|
||||
private final int z;
|
||||
|
||||
/**
|
||||
* The actual raw data of this packed chunk.
|
||||
* <p>
|
||||
* Each block is expressed as 2 bits giving a total of 16 KiB
|
||||
*/
|
||||
private final BitSet data;
|
||||
|
||||
CachedChunk(int x, int z, BitSet data) {
|
||||
validateSize(data);
|
||||
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final PathingBlockType getBlockType(int x, int y, int z) {
|
||||
int index = getPositionIndex(x, y, z);
|
||||
return PathingBlockType.fromBits(data.get(index), data.get(index + 1));
|
||||
}
|
||||
|
||||
void updateContents(BitSet data) {
|
||||
validateSize(data);
|
||||
|
||||
for (int i = 0; i < data.length(); i++)
|
||||
this.data.set(i, data.get(i));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Thee chunk x coordinat
|
||||
*/
|
||||
public final int getX() {
|
||||
return this.x;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The chunk z coordinate
|
||||
*/
|
||||
public final int getZ() {
|
||||
return this.z;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the raw packed chunk data as a byte array
|
||||
*/
|
||||
public final byte[] toByteArray() {
|
||||
return this.data.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw bit index of the specified position
|
||||
*
|
||||
* @param x The x position
|
||||
* @param y The y position
|
||||
* @param z The z position
|
||||
* @return The bit index
|
||||
*/
|
||||
public static int getPositionIndex(int x, int y, int z) {
|
||||
return (x + (z << 4) + (y << 8)) * 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the size of an input {@link BitSet} containing the raw
|
||||
* packed chunk data. Sizes that exceed {@link CachedChunk#SIZE} are
|
||||
* considered invalid, and thus, an exception will be thrown.
|
||||
*
|
||||
* @param data The raw data
|
||||
* @throws IllegalArgumentException if the bitset size exceeds the maximum size
|
||||
*/
|
||||
private static void validateSize(BitSet data) {
|
||||
if (data.size() > SIZE)
|
||||
throw new IllegalArgumentException("BitSet of invalid length provided");
|
||||
}
|
||||
}
|
||||
180
src/main/java/baritone/bot/chunk/CachedRegion.java
Normal file
180
src/main/java/baritone/bot/chunk/CachedRegion.java
Normal file
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.chunk;
|
||||
|
||||
import baritone.bot.utils.pathing.PathingBlockType;
|
||||
import baritone.bot.utils.GZIPUtils;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
import java.util.BitSet;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/3/2018 9:35 PM
|
||||
*/
|
||||
public final class CachedRegion implements ICachedChunkAccess {
|
||||
|
||||
/**
|
||||
* All of the chunks in this region: A 32x32 array of them.
|
||||
*/
|
||||
private final CachedChunk[][] chunks = new CachedChunk[32][32];
|
||||
|
||||
/**
|
||||
* The region x coordinate
|
||||
*/
|
||||
private final int x;
|
||||
|
||||
/**
|
||||
* The region z coordinate
|
||||
*/
|
||||
private final int z;
|
||||
|
||||
CachedRegion(int x, int z) {
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final PathingBlockType getBlockType(int x, int y, int z) {
|
||||
CachedChunk chunk = this.getChunk(x >> 4, z >> 4);
|
||||
if (chunk != null) {
|
||||
return chunk.getBlockType(x & 15, y, z & 15);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void updateCachedChunk(int chunkX, int chunkZ, BitSet data) {
|
||||
CachedChunk chunk = this.getChunk(chunkX, chunkZ);
|
||||
if (chunk == null) {
|
||||
this.chunks[chunkX][chunkZ] = new CachedChunk(chunkX, chunkZ, data);
|
||||
} else {
|
||||
chunk.updateContents(data);
|
||||
}
|
||||
}
|
||||
|
||||
private CachedChunk getChunk(int chunkX, int chunkZ) {
|
||||
return this.chunks[chunkX][chunkZ];
|
||||
}
|
||||
|
||||
public void forEachChunk(Consumer<CachedChunk> consumer) {
|
||||
for (int x = 0; x < 32; x++) {
|
||||
for (int z = 0; z < 32; z++) {
|
||||
CachedChunk chunk = getChunk(x, z);
|
||||
if (chunk != null) {
|
||||
consumer.accept(chunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final void save(String directory) {
|
||||
try {
|
||||
Path path = Paths.get(directory);
|
||||
if (!Files.exists(path))
|
||||
Files.createDirectories(path);
|
||||
|
||||
Path regionFile = getRegionFile(path, this.x, this.z);
|
||||
if (!Files.exists(regionFile))
|
||||
Files.createFile(regionFile);
|
||||
try (FileOutputStream fileOut = new FileOutputStream(regionFile.toFile()); GZIPOutputStream out = new GZIPOutputStream(fileOut)) {
|
||||
for (int z = 0; z < 32; z++) {
|
||||
for (int x = 0; x < 32; x++) {
|
||||
CachedChunk chunk = this.chunks[x][z];
|
||||
if (chunk == null) {
|
||||
out.write(CachedChunk.EMPTY_CHUNK);
|
||||
} else {
|
||||
byte[] chunkBytes = chunk.toByteArray();
|
||||
out.write(chunkBytes);
|
||||
// Messy, but fills the empty 0s that should be trailing to fill up the space.
|
||||
out.write(new byte[CachedChunk.SIZE_IN_BYTES - chunkBytes.length]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
|
||||
public void load(String directory) {
|
||||
try {
|
||||
Path path = Paths.get(directory);
|
||||
if (!Files.exists(path))
|
||||
Files.createDirectories(path);
|
||||
|
||||
Path regionFile = getRegionFile(path, this.x, this.z);
|
||||
if (!Files.exists(regionFile))
|
||||
return;
|
||||
|
||||
byte[] decompressed;
|
||||
try (FileInputStream in = new FileInputStream(regionFile.toFile())) {
|
||||
decompressed = GZIPUtils.decompress(in);
|
||||
}
|
||||
|
||||
if (decompressed == null)
|
||||
return;
|
||||
|
||||
for (int z = 0; z < 32; z++) {
|
||||
for (int x = 0; x < 32; x++) {
|
||||
int index = (x + (z << 5)) * CachedChunk.SIZE_IN_BYTES;
|
||||
byte[] bytes = Arrays.copyOfRange(decompressed, index, index + CachedChunk.SIZE_IN_BYTES);
|
||||
if (isAllZeros(bytes)) {
|
||||
this.chunks[x][z] = null;
|
||||
} else {
|
||||
BitSet bits = BitSet.valueOf(bytes);
|
||||
updateCachedChunk(x, z, bits);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
|
||||
private static boolean isAllZeros(final byte[] array) {
|
||||
for (byte b : array) {
|
||||
if (b != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The region x coordinate
|
||||
*/
|
||||
public final int getX() {
|
||||
return this.x;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The region z coordinate
|
||||
*/
|
||||
public final int getZ() {
|
||||
return this.z;
|
||||
}
|
||||
|
||||
private static Path getRegionFile(Path cacheDir, int regionX, int regionZ) {
|
||||
return Paths.get(cacheDir.toString(), "r." + regionX + "." + regionZ + ".bcr");
|
||||
}
|
||||
}
|
||||
144
src/main/java/baritone/bot/chunk/CachedWorld.java
Normal file
144
src/main/java/baritone/bot/chunk/CachedWorld.java
Normal file
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.chunk;
|
||||
|
||||
import baritone.bot.utils.pathing.PathingBlockType;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||
|
||||
import java.util.BitSet;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/4/2018 12:02 AM
|
||||
*/
|
||||
public final class CachedWorld implements ICachedChunkAccess {
|
||||
|
||||
/**
|
||||
* The maximum number of regions in any direction from (0,0)
|
||||
*/
|
||||
private static final int REGION_MAX = 117188;
|
||||
|
||||
/**
|
||||
* A map of all of the cached regions.
|
||||
*/
|
||||
private Long2ObjectMap<CachedRegion> cachedRegions = new Long2ObjectOpenHashMap<>();
|
||||
|
||||
/**
|
||||
* The directory that the cached region files are saved to
|
||||
*/
|
||||
private final String directory;
|
||||
|
||||
public CachedWorld(String directory) {
|
||||
this.directory = directory;
|
||||
// Insert an invalid region element
|
||||
cachedRegions.put(0, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final PathingBlockType getBlockType(int x, int y, int z) {
|
||||
CachedRegion region = getRegion(x >> 9, z >> 9);
|
||||
if (region != null) {
|
||||
return region.getBlockType(x & 511, y, z & 511);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void updateCachedChunk(int chunkX, int chunkZ, BitSet data) {
|
||||
CachedRegion region = getOrCreateRegion(chunkX >> 5, chunkZ >> 5);
|
||||
if (region != null) {
|
||||
region.updateCachedChunk(chunkX & 31, chunkZ & 31, data);
|
||||
}
|
||||
}
|
||||
|
||||
public final void save() {
|
||||
this.cachedRegions.values().forEach(region -> {
|
||||
if (region != null)
|
||||
region.save(this.directory);
|
||||
});
|
||||
}
|
||||
|
||||
public final void load() {
|
||||
this.cachedRegions.values().forEach(region -> {
|
||||
if (region != null)
|
||||
region.load(this.directory);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the region at the specified region coordinates
|
||||
*
|
||||
* @param regionX The region X coordinate
|
||||
* @param regionZ The region Z coordinate
|
||||
* @return The region located at the specified coordinates
|
||||
*/
|
||||
public final CachedRegion getRegion(int regionX, int regionZ) {
|
||||
return cachedRegions.get(getRegionID(regionX, regionZ));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the region at the specified region coordinates. If a
|
||||
* region is not found, then a new one is created.
|
||||
*
|
||||
* @param regionX The region X coordinate
|
||||
* @param regionZ The region Z coordinate
|
||||
* @return The region located at the specified coordinates
|
||||
*/
|
||||
CachedRegion getOrCreateRegion(int regionX, int regionZ) {
|
||||
return cachedRegions.computeIfAbsent(getRegionID(regionX, regionZ), id -> {
|
||||
CachedRegion newRegion = new CachedRegion(regionX, regionZ);
|
||||
newRegion.load(this.directory);
|
||||
return newRegion;
|
||||
});
|
||||
}
|
||||
|
||||
public void forEachRegion(Consumer<CachedRegion> consumer) {
|
||||
this.cachedRegions.forEach((id, r) -> {
|
||||
if (r != null)
|
||||
consumer.accept(r);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the region ID based on the region coordinates. 0 will be
|
||||
* returned if the specified region coordinates are out of bounds.
|
||||
*
|
||||
* @param regionX The region X coordinate
|
||||
* @param regionZ The region Z coordinate
|
||||
* @return The region ID
|
||||
*/
|
||||
private long getRegionID(int regionX, int regionZ) {
|
||||
if (!isRegionInWorld(regionX, regionZ))
|
||||
return 0;
|
||||
|
||||
return (long) regionX & 0xFFFFFFFFL | ((long) regionZ & 0xFFFFFFFFL) << 32;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the specified region coordinates is within the world bounds.
|
||||
*
|
||||
* @param regionX The region X coordinate
|
||||
* @param regionZ The region Z coordinate
|
||||
* @return Whether or not the region is in world bounds
|
||||
*/
|
||||
private boolean isRegionInWorld(int regionX, int regionZ) {
|
||||
return regionX <= REGION_MAX && regionX >= -REGION_MAX && regionZ <= REGION_MAX && regionZ >= -REGION_MAX;
|
||||
}
|
||||
}
|
||||
98
src/main/java/baritone/bot/chunk/CachedWorldProvider.java
Normal file
98
src/main/java/baritone/bot/chunk/CachedWorldProvider.java
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.chunk;
|
||||
|
||||
import baritone.bot.utils.Helper;
|
||||
import baritone.launch.mixins.accessor.IAnvilChunkLoader;
|
||||
import baritone.launch.mixins.accessor.IChunkProviderServer;
|
||||
import net.minecraft.client.multiplayer.WorldClient;
|
||||
import net.minecraft.server.integrated.IntegratedServer;
|
||||
import net.minecraft.world.WorldServer;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/4/2018 11:06 AM
|
||||
*/
|
||||
public enum CachedWorldProvider implements Helper {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
private static final Pattern REGION_REGEX = Pattern.compile("r\\.(-?[0-9]+)\\.(-?[0-9]+)\\.bcr");
|
||||
|
||||
private final Map<String, CachedWorld> singlePlayerWorldCache = new HashMap<>();
|
||||
|
||||
private CachedWorld currentWorld;
|
||||
|
||||
public final CachedWorld getCurrentWorld() {
|
||||
return this.currentWorld;
|
||||
}
|
||||
|
||||
public final void initWorld(WorldClient world) {
|
||||
IntegratedServer integratedServer;
|
||||
if ((integratedServer = mc.getIntegratedServer()) != null) {
|
||||
|
||||
WorldServer localServerWorld = integratedServer.getWorld(world.provider.getDimensionType().getId());
|
||||
IChunkProviderServer provider = (IChunkProviderServer) localServerWorld.getChunkProvider();
|
||||
IAnvilChunkLoader loader = (IAnvilChunkLoader) provider.getChunkLoader();
|
||||
|
||||
Path dir = new File(new File(loader.getChunkSaveLocation(), "region"), "cache").toPath();
|
||||
if (!Files.exists(dir)) {
|
||||
try {
|
||||
Files.createDirectories(dir);
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
|
||||
this.currentWorld = this.singlePlayerWorldCache.computeIfAbsent(dir.toString(), CachedWorld::new);
|
||||
|
||||
try {
|
||||
Files.list(dir).forEach(path -> {
|
||||
String file = path.getFileName().toString();
|
||||
Matcher matcher = REGION_REGEX.matcher(file);
|
||||
if (matcher.matches()) {
|
||||
int rx = Integer.parseInt(matcher.group(1));
|
||||
int ry = Integer.parseInt(matcher.group(2));
|
||||
// Recognize the region for when we load from file
|
||||
this.currentWorld.getOrCreateRegion(rx, ry);
|
||||
}
|
||||
});
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
this.currentWorld.load();
|
||||
}
|
||||
// TODO: Store server worlds
|
||||
}
|
||||
|
||||
public final void closeWorld() {
|
||||
this.currentWorld = null;
|
||||
}
|
||||
|
||||
public final void ifWorldLoaded(Consumer<CachedWorld> currentWorldConsumer) {
|
||||
if (this.currentWorld != null)
|
||||
currentWorldConsumer.accept(this.currentWorld);
|
||||
}
|
||||
}
|
||||
78
src/main/java/baritone/bot/chunk/ChunkPacker.java
Normal file
78
src/main/java/baritone/bot/chunk/ChunkPacker.java
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.chunk;
|
||||
|
||||
import baritone.bot.pathing.movement.MovementHelper;
|
||||
import baritone.bot.utils.pathing.PathingBlockType;
|
||||
import baritone.bot.utils.BlockStateInterface;
|
||||
import baritone.bot.utils.Helper;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockAir;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
|
||||
import java.util.BitSet;
|
||||
|
||||
import static net.minecraft.block.Block.NULL_AABB;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/3/2018 1:09 AM
|
||||
*/
|
||||
public final class ChunkPacker implements Helper {
|
||||
|
||||
private ChunkPacker() {}
|
||||
|
||||
public static BitSet createPackedChunk(Chunk chunk) {
|
||||
BitSet bitSet = new BitSet(CachedChunk.SIZE);
|
||||
try {
|
||||
for (int y = 0; y < 256; y++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
int index = CachedChunk.getPositionIndex(x, y, z);
|
||||
boolean[] bits = getPathingBlockType(new BlockPos(x, y, z), chunk.getBlockState(x, y, z)).getBits();
|
||||
bitSet.set(index, bits[0]);
|
||||
bitSet.set(index + 1, bits[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return bitSet;
|
||||
}
|
||||
|
||||
private static PathingBlockType getPathingBlockType(BlockPos pos, IBlockState state) {
|
||||
Block block = state.getBlock();
|
||||
|
||||
if (BlockStateInterface.isWater(block)) {
|
||||
return PathingBlockType.WATER;
|
||||
}
|
||||
|
||||
if (MovementHelper.avoidWalkingInto(block)) {
|
||||
return PathingBlockType.AVOID;
|
||||
}
|
||||
|
||||
if (block instanceof BlockAir || state.getCollisionBoundingBox(mc.world, pos) == NULL_AABB) {
|
||||
return PathingBlockType.AIR;
|
||||
}
|
||||
|
||||
return PathingBlockType.SOLID;
|
||||
}
|
||||
}
|
||||
@@ -15,18 +15,17 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.event.events;
|
||||
package baritone.bot.chunk;
|
||||
|
||||
public enum PathEvent {
|
||||
CALC_STARTED,
|
||||
CALC_FINISHED_NOW_EXECUTING,
|
||||
CALC_FAILED,
|
||||
NEXT_SEGMENT_CALC_STARTED,
|
||||
NEXT_SEGMENT_CALC_FINISHED,
|
||||
CONTINUING_ONTO_PLANNED_NEXT,
|
||||
SPLICING_ONTO_NEXT_EARLY,
|
||||
AT_GOAL,
|
||||
PATH_FINISHED_NEXT_STILL_CALCULATING,
|
||||
NEXT_CALC_FAILED,
|
||||
DISCARD_NEXT
|
||||
import baritone.bot.utils.pathing.IBlockTypeAccess;
|
||||
|
||||
import java.util.BitSet;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/4/2018 1:10 AM
|
||||
*/
|
||||
public interface ICachedChunkAccess extends IBlockTypeAccess {
|
||||
|
||||
void updateCachedChunk(int chunkX, int chunkZ, BitSet data);
|
||||
}
|
||||
189
src/main/java/baritone/bot/event/GameEventHandler.java
Normal file
189
src/main/java/baritone/bot/event/GameEventHandler.java
Normal file
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.event;
|
||||
|
||||
import baritone.bot.Baritone;
|
||||
import baritone.bot.behavior.Behavior;
|
||||
import baritone.bot.chunk.CachedWorld;
|
||||
import baritone.bot.chunk.CachedWorldProvider;
|
||||
import baritone.bot.chunk.ChunkPacker;
|
||||
import baritone.bot.event.events.*;
|
||||
import baritone.bot.event.events.type.EventState;
|
||||
import baritone.bot.event.listener.IGameEventListener;
|
||||
import baritone.bot.utils.Helper;
|
||||
import baritone.bot.utils.InputOverrideHandler;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.client.settings.KeyBinding;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 7/31/2018 11:04 PM
|
||||
*/
|
||||
public final class GameEventHandler implements IGameEventListener, Helper {
|
||||
|
||||
@Override
|
||||
public final void onTick(TickEvent event) {
|
||||
dispatch(behavior -> behavior.onTick(event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerUpdate() {
|
||||
dispatch(Behavior::onPlayerUpdate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public 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);
|
||||
}
|
||||
}
|
||||
|
||||
dispatch(Behavior::onProcessKeyBinds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSendChatMessage(ChatEvent event) {
|
||||
dispatch(behavior -> behavior.onSendChatMessage(event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkEvent(ChunkEvent event) {
|
||||
EventState state = event.getState();
|
||||
ChunkEvent.Type type = event.getType();
|
||||
|
||||
boolean isPostPopulate = state == EventState.POST
|
||||
&& type == ChunkEvent.Type.POPULATE;
|
||||
|
||||
// Whenever the server sends us to another dimension, chunks are unloaded
|
||||
// technically after the new world has been loaded, so we perform a check
|
||||
// to make sure the chunk being unloaded is already loaded.
|
||||
boolean isPreUnload = state == EventState.PRE
|
||||
&& type == ChunkEvent.Type.UNLOAD
|
||||
&& mc.world.getChunkProvider().isChunkGeneratedAt(event.getX(), event.getZ());
|
||||
|
||||
if (Baritone.settings().chuckCaching.get()) {
|
||||
if (isPostPopulate || isPreUnload) {
|
||||
CachedWorldProvider.INSTANCE.ifWorldLoaded(world ->
|
||||
world.updateCachedChunk(event.getX(), event.getZ(),
|
||||
ChunkPacker.createPackedChunk(mc.world.getChunk(event.getX(), event.getZ()))));
|
||||
}
|
||||
}
|
||||
|
||||
dispatch(behavior -> behavior.onChunkEvent(event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRenderPass(RenderEvent event) {
|
||||
/*
|
||||
CachedWorldProvider.INSTANCE.ifWorldLoaded(world -> world.forEachRegion(region -> region.forEachChunk(chunk -> {
|
||||
drawChunkLine(region.getX() * 512 + chunk.getX() * 16, region.getZ() * 512 + chunk.getZ() * 16, event.getPartialTicks());
|
||||
})));
|
||||
*/
|
||||
|
||||
dispatch(behavior -> behavior.onRenderPass(event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWorldEvent(WorldEvent event) {
|
||||
if (Baritone.settings().chuckCaching.get()) {
|
||||
CachedWorldProvider cache = CachedWorldProvider.INSTANCE;
|
||||
|
||||
switch (event.getState()) {
|
||||
case PRE:
|
||||
cache.ifWorldLoaded(CachedWorld::save);
|
||||
break;
|
||||
case POST:
|
||||
cache.closeWorld();
|
||||
if (event.getWorld() != null)
|
||||
cache.initWorld(event.getWorld());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dispatch(behavior -> behavior.onWorldEvent(event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSendPacket(PacketEvent event) {
|
||||
dispatch(behavior -> behavior.onSendPacket(event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceivePacket(PacketEvent event) {
|
||||
dispatch(behavior -> behavior.onReceivePacket(event));
|
||||
}
|
||||
|
||||
private void dispatch(Consumer<Behavior> dispatchFunction) {
|
||||
Baritone.INSTANCE.getBehaviors().stream().filter(Behavior::isEnabled).forEach(dispatchFunction);
|
||||
}
|
||||
|
||||
private void drawChunkLine(int posX, int posZ, float partialTicks) {
|
||||
GlStateManager.enableBlend();
|
||||
GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0);
|
||||
GlStateManager.color(1.0F, 1.0F, 0.0F, 0.4F);
|
||||
GlStateManager.glLineWidth(2.0F);
|
||||
GlStateManager.disableTexture2D();
|
||||
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
double d0 = mc.getRenderManager().viewerPosX;
|
||||
double d1 = mc.getRenderManager().viewerPosY;
|
||||
double d2 = mc.getRenderManager().viewerPosZ;
|
||||
buffer.begin(3, DefaultVertexFormats.POSITION);
|
||||
buffer.pos(posX - d0, 0 - d1, posZ - d2).endVertex();
|
||||
buffer.pos(posX - d0, 256 - d1, posZ - d2).endVertex();
|
||||
tessellator.draw();
|
||||
|
||||
GlStateManager.enableDepth();
|
||||
GlStateManager.depthMask(true);
|
||||
GlStateManager.enableTexture2D();
|
||||
GlStateManager.disableBlend();
|
||||
}
|
||||
}
|
||||
@@ -15,9 +15,9 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.event.events;
|
||||
package baritone.bot.event.events;
|
||||
|
||||
import baritone.event.events.type.Cancellable;
|
||||
import baritone.bot.event.events.type.Cancellable;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
@@ -15,9 +15,9 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.event.events;
|
||||
package baritone.bot.event.events;
|
||||
|
||||
import baritone.event.events.type.EventState;
|
||||
import baritone.bot.event.events.type.EventState;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
@@ -15,9 +15,9 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.event.events;
|
||||
package baritone.bot.event.events;
|
||||
|
||||
import baritone.event.events.type.EventState;
|
||||
import baritone.bot.event.events.type.EventState;
|
||||
import net.minecraft.network.Packet;
|
||||
|
||||
/**
|
||||
@@ -15,7 +15,7 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.event.events;
|
||||
package baritone.bot.event.events;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
@@ -15,9 +15,9 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.event.events;
|
||||
package baritone.bot.event.events;
|
||||
|
||||
import baritone.event.events.type.EventState;
|
||||
import baritone.bot.event.events.type.EventState;
|
||||
|
||||
public final class TickEvent {
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.event.events;
|
||||
package baritone.bot.event.events;
|
||||
|
||||
import baritone.event.events.type.EventState;
|
||||
import baritone.bot.event.events.type.EventState;
|
||||
import net.minecraft.client.multiplayer.WorldClient;
|
||||
|
||||
/**
|
||||
@@ -15,7 +15,7 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.event.events.type;
|
||||
package baritone.bot.event.events.type;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
@@ -15,7 +15,7 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.event.events.type;
|
||||
package baritone.bot.event.events.type;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
@@ -32,17 +32,18 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.event.listener;
|
||||
package baritone.bot.event.listener;
|
||||
|
||||
import baritone.event.events.*;
|
||||
import baritone.bot.event.events.*;
|
||||
|
||||
/**
|
||||
* An implementation of {@link IGameEventListener} that has all methods
|
||||
* overridden with empty bodies, allowing inheritors of this class to choose
|
||||
* which events they would like to listen in on.
|
||||
*
|
||||
* @author Brady
|
||||
* @see IGameEventListener
|
||||
*
|
||||
* @author Brady
|
||||
* @since 8/1/2018 6:29 PM
|
||||
*/
|
||||
public interface AbstractGameEventListener extends IGameEventListener {
|
||||
@@ -51,7 +52,7 @@ public interface AbstractGameEventListener extends IGameEventListener {
|
||||
default void onTick(TickEvent event) {}
|
||||
|
||||
@Override
|
||||
default void onPlayerUpdate(PlayerUpdateEvent event) {}
|
||||
default void onPlayerUpdate() {}
|
||||
|
||||
@Override
|
||||
default void onProcessKeyBinds() {}
|
||||
@@ -73,19 +74,4 @@ public interface AbstractGameEventListener extends IGameEventListener {
|
||||
|
||||
@Override
|
||||
default void onReceivePacket(PacketEvent event) {}
|
||||
|
||||
@Override
|
||||
default void onQueryItemSlotForBlocks(ItemSlotEvent event) {}
|
||||
|
||||
@Override
|
||||
default void onPlayerRelativeMove(RelativeMoveEvent event) {}
|
||||
|
||||
@Override
|
||||
default void onBlockInteract(BlockInteractEvent event) {}
|
||||
|
||||
@Override
|
||||
default void onPlayerDeath() {}
|
||||
|
||||
@Override
|
||||
default void onPathEvent(PathEvent event) {}
|
||||
}
|
||||
@@ -32,22 +32,17 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.event.listener;
|
||||
package baritone.bot.event.listener;
|
||||
|
||||
import baritone.event.events.*;
|
||||
import baritone.bot.event.events.*;
|
||||
import io.netty.util.concurrent.GenericFutureListener;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.client.gui.GuiGameOver;
|
||||
import net.minecraft.client.multiplayer.WorldClient;
|
||||
import net.minecraft.client.renderer.EntityRenderer;
|
||||
import net.minecraft.client.settings.GameSettings;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
import net.minecraft.network.NetworkManager;
|
||||
import net.minecraft.network.Packet;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
@@ -63,11 +58,10 @@ public interface IGameEventListener {
|
||||
void onTick(TickEvent event);
|
||||
|
||||
/**
|
||||
* Run once per game tick from before and after the player rotation is sent to the server.
|
||||
*
|
||||
* Run once per game tick from before the player rotation is sent to the server.
|
||||
* @see EntityPlayerSP#onUpdate()
|
||||
*/
|
||||
void onPlayerUpdate(PlayerUpdateEvent event);
|
||||
void onPlayerUpdate();
|
||||
|
||||
/**
|
||||
* Run once per game tick from before keybinds are processed.
|
||||
@@ -120,40 +114,5 @@ public interface IGameEventListener {
|
||||
*/
|
||||
void onReceivePacket(PacketEvent event);
|
||||
|
||||
/**
|
||||
* Run when a query is made for a player's inventory current slot in the context of blocks
|
||||
*
|
||||
* @see InventoryPlayer#getDestroySpeed(IBlockState)
|
||||
* @see InventoryPlayer#canHarvestBlock(IBlockState)
|
||||
*/
|
||||
void onQueryItemSlotForBlocks(ItemSlotEvent event);
|
||||
|
||||
/**
|
||||
* Run once per game tick from before and after the player's moveRelative method is called
|
||||
*
|
||||
* @see Entity#moveRelative(float, float, float, float)
|
||||
*/
|
||||
void onPlayerRelativeMove(RelativeMoveEvent event);
|
||||
|
||||
/**
|
||||
* Called when the local player interacts with a block, whether it is breaking or opening/placing.
|
||||
*
|
||||
* @see Minecraft#clickMouse()
|
||||
* @see Minecraft#rightClickMouse()
|
||||
*/
|
||||
void onBlockInteract(BlockInteractEvent event);
|
||||
|
||||
/**
|
||||
* Called when the local player dies, as indicated by the creation of the {@link GuiGameOver} screen.
|
||||
*
|
||||
* @see GuiGameOver(ITextComponent)
|
||||
*/
|
||||
void onPlayerDeath();
|
||||
|
||||
/**
|
||||
* When the pathfinder's state changes
|
||||
*
|
||||
* @param event
|
||||
*/
|
||||
void onPathEvent(PathEvent event);
|
||||
}
|
||||
@@ -15,21 +15,38 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.calc;
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.chunk.WorldProvider;
|
||||
import baritone.pathing.calc.openset.BinaryHeapOpenSet;
|
||||
import baritone.pathing.calc.openset.IOpenSet;
|
||||
import baritone.pathing.goals.Goal;
|
||||
import baritone.pathing.movement.ActionCosts;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.pathing.movement.movements.*;
|
||||
import baritone.pathing.path.IPath;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.pathing.BetterBlockPos;
|
||||
package baritone.bot.pathing.calc;
|
||||
|
||||
import baritone.bot.Baritone;
|
||||
import baritone.bot.chunk.CachedWorldProvider;
|
||||
import baritone.bot.pathing.calc.openset.BinaryHeapOpenSet;
|
||||
import baritone.bot.pathing.calc.openset.IOpenSet;
|
||||
import baritone.bot.pathing.goals.Goal;
|
||||
import baritone.bot.pathing.movement.ActionCosts;
|
||||
import baritone.bot.pathing.movement.CalculationContext;
|
||||
import baritone.bot.pathing.movement.Movement;
|
||||
import baritone.bot.pathing.movement.MovementHelper;
|
||||
import baritone.bot.pathing.movement.movements.*;
|
||||
import baritone.bot.pathing.path.IPath;
|
||||
import baritone.bot.utils.Helper;
|
||||
import baritone.bot.utils.pathing.BetterBlockPos;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
@@ -76,10 +93,10 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
|
||||
long lastPrintout = 0;
|
||||
int numNodes = 0;
|
||||
int numEmptyChunk = 0;
|
||||
boolean favoring = favoredPositions.isPresent();
|
||||
int pathingMaxChunkBorderFetch = Baritone.settings().pathingMaxChunkBorderFetch.get(); // grab all settings beforehand so that changing settings during pathing doesn't cause a crash or unpredictable behavior
|
||||
boolean favoring = favoredPositions.isPresent(); // grab all settings beforehand so that changing settings during pathing doesn't cause a crash or unpredictable behavior
|
||||
boolean cache = Baritone.settings().chuckCaching.get();
|
||||
int pathingMaxChunkBorderFetch = Baritone.settings().pathingMaxChunkBorderFetch.get();
|
||||
double favorCoeff = Baritone.settings().backtrackCostFavoringCoefficient.get();
|
||||
boolean minimumImprovementRepropagation = Baritone.settings().minimumImprovementRepropagation.get();
|
||||
while (!openSet.isEmpty() && numEmptyChunk < pathingMaxChunkBorderFetch && System.currentTimeMillis() < timeoutTime) {
|
||||
if (slowPath) {
|
||||
try {
|
||||
@@ -111,9 +128,11 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
|
||||
}
|
||||
BetterBlockPos dest = (BetterBlockPos) movementToGetToNeighbor.getDest();
|
||||
boolean isPositionCached = false;
|
||||
if (WorldProvider.INSTANCE.getCurrentWorld() != null) {
|
||||
if (WorldProvider.INSTANCE.getCurrentWorld().cache.getBlock(dest) != null) {
|
||||
isPositionCached = true;
|
||||
if (cache) {
|
||||
if (CachedWorldProvider.INSTANCE.getCurrentWorld() != null) {
|
||||
if (CachedWorldProvider.INSTANCE.getCurrentWorld().getBlockType(dest) != null) {
|
||||
isPositionCached = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!isPositionCached && Minecraft.getMinecraft().world.getChunk(dest) instanceof EmptyChunk) {
|
||||
@@ -141,14 +160,6 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
|
||||
if (tentativeCost < 0) {
|
||||
throw new IllegalStateException(movementToGetToNeighbor.getClass() + " " + movementToGetToNeighbor + " overflowed into negative " + actionCost + " " + neighbor.cost + " " + tentativeCost);
|
||||
}
|
||||
double improvementBy = neighbor.cost - tentativeCost;
|
||||
// there are floating point errors caused by random combinations of traverse and diagonal over a flat area
|
||||
// that means that sometimes there's a cost improvement of like 10 ^ -16
|
||||
// it's not worth the time to update the costs, decrease-key the heap, potentially repropagate, etc
|
||||
if (improvementBy < 0.01 && minimumImprovementRepropagation) {
|
||||
// who cares about a hundredth of a tick? that's half a millisecond for crying out loud!
|
||||
continue;
|
||||
}
|
||||
neighbor.previous = currentNode;
|
||||
neighbor.previousMovement = movementToGetToNeighbor;
|
||||
neighbor.cost = tentativeCost;
|
||||
@@ -179,7 +190,7 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
|
||||
bestDist = dist;
|
||||
}
|
||||
if (dist > MIN_DIST_PATH * MIN_DIST_PATH) { // square the comparison since distFromStartSq is squared
|
||||
displayChatMessageRaw("Took " + (System.currentTimeMillis() - startTime) + "ms, A* cost coefficient " + COEFFICIENTS[i]);
|
||||
displayChatMessageRaw("A* cost coefficient " + COEFFICIENTS[i]);
|
||||
if (COEFFICIENTS[i] >= 3) {
|
||||
System.out.println("Warning: cost coefficient is greater than three! Probably means that");
|
||||
System.out.println("the path I found is pretty terrible (like sneak-bridging for dozens of blocks)");
|
||||
@@ -197,7 +208,7 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
|
||||
}
|
||||
|
||||
|
||||
public static Movement[] getConnectedPositions(BetterBlockPos pos, CalculationContext calcContext) {
|
||||
private static Movement[] getConnectedPositions(BetterBlockPos pos, CalculationContext calcContext) {
|
||||
int x = pos.getX();
|
||||
int y = pos.getY();
|
||||
int z = pos.getZ();
|
||||
@@ -15,11 +15,11 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.calc;
|
||||
package baritone.bot.pathing.calc;
|
||||
|
||||
import baritone.pathing.goals.Goal;
|
||||
import baritone.pathing.path.IPath;
|
||||
import baritone.utils.pathing.BetterBlockPos;
|
||||
import baritone.bot.pathing.goals.Goal;
|
||||
import baritone.bot.pathing.path.IPath;
|
||||
import baritone.bot.utils.pathing.BetterBlockPos;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.HashMap;
|
||||
@@ -58,7 +58,7 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
|
||||
*
|
||||
* @see <a href="https://docs.google.com/document/d/1WVHHXKXFdCR1Oz__KtK8sFqyvSwJN_H4lftkHFgmzlc/edit"></a>
|
||||
*/
|
||||
protected static final double[] COEFFICIENTS = {1.5, 2, 2.5, 3, 4, 5, 10}; // big TODO tune
|
||||
protected static final double[] COEFFICIENTS = {1.25, 1.5, 2, 2.5, 3, 4, 5, 10}; // big TODO tune
|
||||
/**
|
||||
* If a path goes less than 5 blocks and doesn't make it to its goal, it's not worth considering.
|
||||
*/
|
||||
@@ -115,20 +115,10 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
|
||||
|
||||
@Override
|
||||
public Optional<IPath> bestPathSoFar() {
|
||||
if (startNode == null || bestSoFar[0] == null) {
|
||||
if (startNode == null || bestSoFar[0] == null)
|
||||
return Optional.empty();
|
||||
}
|
||||
for (int i = 0; i < bestSoFar.length; i++) {
|
||||
if (bestSoFar[i] == null) {
|
||||
continue;
|
||||
}
|
||||
if (getDistFromStartSq(bestSoFar[i]) > MIN_DIST_PATH * MIN_DIST_PATH) { // square the comparison since distFromStartSq is squared
|
||||
return Optional.of(new Path(startNode, bestSoFar[i], 0));
|
||||
}
|
||||
}
|
||||
// instead of returning bestSoFar[0], be less misleading
|
||||
// if it actually won't find any path, don't make them think it will by rendering a dark blue that will never actually happen
|
||||
return Optional.empty();
|
||||
|
||||
return Optional.of(new Path(startNode, bestSoFar[0], 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -15,10 +15,10 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.calc;
|
||||
package baritone.bot.pathing.calc;
|
||||
|
||||
import baritone.pathing.goals.Goal;
|
||||
import baritone.pathing.path.IPath;
|
||||
import baritone.bot.pathing.goals.Goal;
|
||||
import baritone.bot.pathing.path.IPath;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.Optional;
|
||||
@@ -15,11 +15,11 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.calc;
|
||||
package baritone.bot.pathing.calc;
|
||||
|
||||
import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.path.IPath;
|
||||
import baritone.utils.pathing.BetterBlockPos;
|
||||
import baritone.bot.pathing.movement.Movement;
|
||||
import baritone.bot.pathing.path.IPath;
|
||||
import baritone.bot.utils.pathing.BetterBlockPos;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -15,11 +15,11 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.calc;
|
||||
package baritone.bot.pathing.calc;
|
||||
|
||||
import baritone.pathing.goals.Goal;
|
||||
import baritone.pathing.movement.Movement;
|
||||
import baritone.utils.pathing.BetterBlockPos;
|
||||
import baritone.bot.pathing.goals.Goal;
|
||||
import baritone.bot.pathing.movement.Movement;
|
||||
import baritone.bot.utils.pathing.BetterBlockPos;
|
||||
|
||||
/**
|
||||
* A node in the path, containing the cost and steps to get to it.
|
||||
@@ -95,7 +95,7 @@ public class PathNode {
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return pos.hashCode() * 7 + 3;
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -15,9 +15,9 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.calc.openset;
|
||||
package baritone.bot.pathing.calc.openset;
|
||||
|
||||
import baritone.pathing.calc.PathNode;
|
||||
import baritone.bot.pathing.calc.PathNode;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@@ -53,40 +53,27 @@ public class BinaryHeapOpenSet implements IOpenSet {
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void insert(PathNode value) {
|
||||
public void insert(PathNode value) {
|
||||
if (size >= array.length - 1) {
|
||||
array = Arrays.copyOf(array, array.length * 2);
|
||||
}
|
||||
size++;
|
||||
value.heapPosition = size;
|
||||
array[size] = value;
|
||||
update(value);
|
||||
upHeap(size);
|
||||
}
|
||||
|
||||
public void update(PathNode node) {
|
||||
upHeap(node.heapPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void update(PathNode val) {
|
||||
int index = val.heapPosition;
|
||||
int parentInd = index >>> 1;
|
||||
double cost = val.combinedCost;
|
||||
PathNode parentNode = array[parentInd];
|
||||
while (index > 1 && parentNode.combinedCost > cost) {
|
||||
array[index] = parentNode;
|
||||
array[parentInd] = val;
|
||||
val.heapPosition = parentInd;
|
||||
parentNode.heapPosition = index;
|
||||
index = parentInd;
|
||||
parentInd = index >>> 1;
|
||||
parentNode = array[parentInd];
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isEmpty() {
|
||||
public boolean isEmpty() {
|
||||
return size == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final PathNode removeLowest() {
|
||||
public PathNode removeLowest() {
|
||||
if (size == 0) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
@@ -128,4 +115,20 @@ public class BinaryHeapOpenSet implements IOpenSet {
|
||||
} while (smallerChild <= size);
|
||||
return result;
|
||||
}
|
||||
|
||||
private void upHeap(int index) {
|
||||
int parentInd = index >>> 1;
|
||||
PathNode val = array[index];
|
||||
double cost = val.combinedCost;
|
||||
PathNode parentNode = array[parentInd];
|
||||
while (index > 1 && parentNode.combinedCost > cost) {
|
||||
array[index] = parentNode;
|
||||
array[parentInd] = val;
|
||||
val.heapPosition = parentInd;
|
||||
parentNode.heapPosition = index;
|
||||
index = parentInd;
|
||||
parentInd = index >>> 1;
|
||||
parentNode = array[parentInd];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,9 +15,9 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.calc.openset;
|
||||
package baritone.bot.pathing.calc.openset;
|
||||
|
||||
import baritone.pathing.calc.PathNode;
|
||||
import baritone.bot.pathing.calc.PathNode;
|
||||
|
||||
/**
|
||||
* An open set for A* or similar graph search algorithm
|
||||
@@ -15,9 +15,9 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.calc.openset;
|
||||
package baritone.bot.pathing.calc.openset;
|
||||
|
||||
import baritone.pathing.calc.PathNode;
|
||||
import baritone.bot.pathing.calc.PathNode;
|
||||
|
||||
/**
|
||||
* A linked list implementation of an open set. This is the original implementation from MineBot.
|
||||
@@ -15,9 +15,9 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.goals;
|
||||
package baritone.bot.pathing.goals;
|
||||
|
||||
import baritone.pathing.movement.ActionCosts;
|
||||
import baritone.bot.pathing.movement.ActionCosts;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
/**
|
||||
@@ -15,7 +15,7 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.goals;
|
||||
package baritone.bot.pathing.goals;
|
||||
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
@@ -87,12 +87,23 @@ public class GoalBlock implements Goal {
|
||||
}
|
||||
|
||||
public static double calculate(double xDiff, int yDiff, double zDiff) {
|
||||
double pythaDist = Math.sqrt(xDiff * xDiff + zDiff * zDiff);
|
||||
double heuristic = 0;
|
||||
if (pythaDist < MAX) {//if we are more than MAX away, ignore the Y coordinate. It really doesn't matter how far away your Y coordinate is if you X coordinate is 1000 blocks away.
|
||||
//as we get closer, slowly reintroduce the Y coordinate as a heuristic cost
|
||||
double multiplier;
|
||||
if (pythaDist < MIN) {
|
||||
multiplier = 1;
|
||||
} else {
|
||||
multiplier = 1 - (pythaDist - MIN) / (MAX - MIN);
|
||||
}
|
||||
|
||||
// if yDiff is 1 that means that pos.getY()-this.y==1 which means that we're 1 block below where we should be
|
||||
// therefore going from 0,0,0 to a GoalYLevel of pos.getY()-this.y is accurate
|
||||
heuristic += new GoalYLevel(yDiff).heuristic(new BlockPos(0, 0, 0));
|
||||
// if yDiff is 1 that means that pos.getY()-this.y==1 which means that we're 1 block below where we should be
|
||||
// therefore going from 0,0,0 to a GoalYLevel of pos.getY()-this.y is accurate
|
||||
heuristic += new GoalYLevel(yDiff).heuristic(new BlockPos(0, 0, 0));
|
||||
|
||||
heuristic *= multiplier;
|
||||
}
|
||||
//use the pythagorean and manhattan mixture from GoalXZ
|
||||
heuristic += GoalXZ.calculate(xDiff, zDiff);
|
||||
return heuristic;
|
||||
@@ -15,7 +15,7 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.goals;
|
||||
package baritone.bot.pathing.goals;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
@@ -15,7 +15,7 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.goals;
|
||||
package baritone.bot.pathing.goals;
|
||||
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
@@ -15,7 +15,7 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.goals;
|
||||
package baritone.bot.pathing.goals;
|
||||
|
||||
import java.util.Arrays;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
@@ -15,7 +15,7 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.goals;
|
||||
package baritone.bot.pathing.goals;
|
||||
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.goals;
|
||||
package baritone.bot.pathing.goals;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.utils.Utils;
|
||||
import baritone.bot.Baritone;
|
||||
import baritone.bot.utils.Utils;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
@@ -64,9 +64,6 @@ public class GoalXZ implements Goal {
|
||||
}
|
||||
|
||||
public static double calculate(double xDiff, double zDiff) {
|
||||
if (Baritone.settings().pythagoreanMetric.get()) {
|
||||
return Math.sqrt(xDiff * xDiff + zDiff * zDiff) * Baritone.settings().costHeuristic.get();
|
||||
}
|
||||
//This is a combination of pythagorean and manhattan distance
|
||||
//It takes into account the fact that pathing can either walk diagonally or forwards
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.goals;
|
||||
package baritone.bot.pathing.goals;
|
||||
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
@@ -44,7 +44,7 @@ public class GoalYLevel implements Goal {
|
||||
public double heuristic(BlockPos pos) {
|
||||
if (pos.getY() > level) {
|
||||
// need to descend
|
||||
return FALL_N_BLOCKS_COST[2] / 2 * (pos.getY() - level);
|
||||
return FALL_N_BLOCKS_COST[pos.getY() - level];
|
||||
}
|
||||
if (pos.getY() < level) {
|
||||
// need to ascend
|
||||
@@ -15,7 +15,7 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.movement;
|
||||
package baritone.bot.pathing.movement;
|
||||
|
||||
public interface ActionCosts extends ActionCostsButOnlyTheOnesThatMakeMickeyDieInside {
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.movement;
|
||||
package baritone.bot.pathing.movement;
|
||||
|
||||
public interface ActionCostsButOnlyTheOnesThatMakeMickeyDieInside {
|
||||
double[] FALL_N_BLOCKS_COST = generateFallNBlocksCost();
|
||||
@@ -15,11 +15,11 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.movement;
|
||||
package baritone.bot.pathing.movement;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.ToolSet;
|
||||
import baritone.bot.Baritone;
|
||||
import baritone.bot.utils.Helper;
|
||||
import baritone.bot.utils.ToolSet;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.item.ItemStack;
|
||||
@@ -38,8 +38,6 @@ public class CalculationContext implements Helper {
|
||||
private final boolean canSprint;
|
||||
private final double placeBlockCost;
|
||||
private final boolean allowBreak;
|
||||
private final int maxFallHeightNoWater;
|
||||
private final int maxFallHeightBucket;
|
||||
|
||||
public CalculationContext() {
|
||||
this(new ToolSet());
|
||||
@@ -48,13 +46,11 @@ public class CalculationContext implements Helper {
|
||||
public CalculationContext(ToolSet toolSet) {
|
||||
player().setSprinting(true);
|
||||
this.toolSet = toolSet;
|
||||
this.hasThrowaway = Baritone.settings().allowPlace.get() && MovementHelper.throwaway(false);
|
||||
this.hasThrowaway = Baritone.settings().allowPlaceThrowaway.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.placeBlockCost = Baritone.settings().blockPlacementPenalty.get();
|
||||
this.allowBreak = Baritone.settings().allowBreak.get();
|
||||
this.maxFallHeightNoWater = Baritone.settings().maxFallHeightNoWater.get();
|
||||
this.maxFallHeightBucket = Baritone.settings().maxFallHeightBucket.get();
|
||||
// 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.
|
||||
@@ -83,13 +79,4 @@ public class CalculationContext implements Helper {
|
||||
public boolean allowBreak() {
|
||||
return allowBreak;
|
||||
}
|
||||
|
||||
public int maxFallHeightNoWater() {
|
||||
return maxFallHeightNoWater;
|
||||
}
|
||||
|
||||
public int maxFallHeightBucket() {
|
||||
return maxFallHeightBucket;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,29 +15,29 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.movement;
|
||||
package baritone.bot.pathing.movement;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.behavior.impl.LookBehavior;
|
||||
import baritone.behavior.impl.LookBehaviorUtils;
|
||||
import baritone.pathing.movement.MovementState.MovementStatus;
|
||||
import baritone.pathing.movement.movements.MovementDownward;
|
||||
import baritone.pathing.movement.movements.MovementPillar;
|
||||
import baritone.pathing.movement.movements.MovementTraverse;
|
||||
import baritone.utils.*;
|
||||
import baritone.bot.Baritone;
|
||||
import baritone.bot.behavior.impl.LookBehavior;
|
||||
import baritone.bot.behavior.impl.LookBehaviorUtils;
|
||||
import baritone.bot.pathing.movement.MovementState.MovementStatus;
|
||||
import baritone.bot.pathing.movement.movements.MovementDownward;
|
||||
import baritone.bot.pathing.movement.movements.MovementPillar;
|
||||
import baritone.bot.pathing.movement.movements.MovementTraverse;
|
||||
import baritone.bot.utils.BlockStateInterface;
|
||||
import baritone.bot.utils.Helper;
|
||||
import baritone.bot.utils.Rotation;
|
||||
import baritone.bot.utils.ToolSet;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockLadder;
|
||||
import net.minecraft.block.BlockVine;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static baritone.utils.InputOverrideHandler.Input;
|
||||
import static baritone.bot.utils.InputOverrideHandler.Input;
|
||||
|
||||
public abstract class Movement implements Helper, MovementHelper {
|
||||
|
||||
@@ -57,8 +57,6 @@ public abstract class Movement implements Helper, MovementHelper {
|
||||
*/
|
||||
protected final BlockPos[] positionsToPlace;
|
||||
|
||||
private boolean didBreakLastTick;
|
||||
|
||||
private Double cost;
|
||||
|
||||
protected Movement(BlockPos src, BlockPos dest, BlockPos[] toBreak, BlockPos[] toPlace) {
|
||||
@@ -105,42 +103,18 @@ public abstract class Movement implements Helper, MovementHelper {
|
||||
* @return Status
|
||||
*/
|
||||
public MovementStatus update() {
|
||||
player().setSprinting(false);
|
||||
MovementState latestState = updateState(currentState);
|
||||
if (BlockStateInterface.isLiquid(playerFeet())) {
|
||||
latestState.setInput(Input.JUMP, 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 ->
|
||||
LookBehavior.INSTANCE.updateTarget(
|
||||
rotation,
|
||||
latestState.getTarget().hasToForceRotations()));
|
||||
|
||||
latestState.getTarget().getRotation().ifPresent(LookBehavior.INSTANCE::updateTarget);
|
||||
// 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) -> {
|
||||
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;
|
||||
}
|
||||
|
||||
Baritone.INSTANCE.getInputOverrideHandler().setInputForceState(input, forced);
|
||||
});
|
||||
latestState.getInputStates().replaceAll((input, forced) -> false);
|
||||
|
||||
if (!this.didBreakLastTick)
|
||||
BlockBreakHelper.stopBreakingBlock();
|
||||
|
||||
currentState = latestState;
|
||||
|
||||
if (isFinished())
|
||||
@@ -150,9 +124,9 @@ public abstract class Movement implements Helper, MovementHelper {
|
||||
}
|
||||
|
||||
protected boolean prepared(MovementState state) {
|
||||
if (state.getStatus() == MovementStatus.WAITING) {
|
||||
if (state.getStatus() == MovementStatus.WAITING)
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean somethingInTheWay = false;
|
||||
for (BlockPos blockPos : positionsToBreak) {
|
||||
if (!MovementHelper.canWalkThrough(blockPos)) {
|
||||
@@ -160,17 +134,9 @@ public abstract class Movement implements Helper, MovementHelper {
|
||||
Optional<Rotation> reachable = LookBehaviorUtils.reachable(blockPos);
|
||||
if (reachable.isPresent()) {
|
||||
player().inventory.currentItem = new ToolSet().getBestSlot(BlockStateInterface.get(blockPos));
|
||||
state.setTarget(new MovementState.MovementTarget(reachable.get(), true)).setInput(Input.CLICK_LEFT, true);
|
||||
state.setTarget(new MovementState.MovementTarget(reachable.get())).setInput(Input.CLICK_LEFT, true);
|
||||
return false;
|
||||
}
|
||||
//get rekt minecraft
|
||||
//i'm doing it anyway
|
||||
//i dont care if theres snow in the way!!!!!!!
|
||||
//you dont own me!!!!
|
||||
state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(mc.player.getPositionEyes(1.0F),
|
||||
Utils.getBlockPosCenter(blockPos)), true)
|
||||
).setInput(InputOverrideHandler.Input.CLICK_LEFT, true);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (somethingInTheWay) {
|
||||
@@ -202,6 +168,7 @@ public abstract class Movement implements Helper, MovementHelper {
|
||||
public void onFinish(MovementState state) {
|
||||
state.getInputStates().replaceAll((input, forced) -> false);
|
||||
state.getInputStates().forEach((input, forced) -> Baritone.INSTANCE.getInputOverrideHandler().setInputForceState(input, forced));
|
||||
state.setStatus(MovementStatus.SUCCESS);
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
@@ -210,58 +177,41 @@ public abstract class Movement implements Helper, MovementHelper {
|
||||
currentState.setStatus(MovementStatus.CANCELED);
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
currentState = new MovementState().setStatus(MovementStatus.PREPPING);
|
||||
}
|
||||
|
||||
public double getTotalHardnessOfBlocksToBreak(CalculationContext ctx) {
|
||||
if (positionsToBreak.length == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (positionsToBreak.length == 1) {
|
||||
return MovementHelper.getMiningDurationTicks(ctx, positionsToBreak[0], true);
|
||||
}
|
||||
int firstColumnX = positionsToBreak[0].getX();
|
||||
int firstColumnZ = positionsToBreak[0].getZ();
|
||||
int firstColumnMaxY = positionsToBreak[0].getY();
|
||||
int firstColumnMaximalIndex = 0;
|
||||
boolean hasSecondColumn = false;
|
||||
int secondColumnX = -1;
|
||||
int secondColumnZ = -1;
|
||||
int secondColumnMaxY = -1;
|
||||
int secondColumnMaximalIndex = -1;
|
||||
for (int i = 0; i < positionsToBreak.length; i++) {
|
||||
BlockPos pos = positionsToBreak[i];
|
||||
if (pos.getX() == firstColumnX && pos.getZ() == firstColumnZ) {
|
||||
if (pos.getY() > firstColumnMaxY) {
|
||||
firstColumnMaxY = pos.getY();
|
||||
firstColumnMaximalIndex = i;
|
||||
}
|
||||
} else {
|
||||
if (!hasSecondColumn || (pos.getX() == secondColumnX && pos.getZ() == secondColumnZ)) {
|
||||
if (hasSecondColumn) {
|
||||
if (pos.getY() > secondColumnMaxY) {
|
||||
secondColumnMaxY = pos.getY();
|
||||
secondColumnMaximalIndex = i;
|
||||
}
|
||||
} else {
|
||||
hasSecondColumn = true;
|
||||
secondColumnX = pos.getX();
|
||||
secondColumnZ = pos.getZ();
|
||||
secondColumnMaxY = pos.getY();
|
||||
secondColumnMaximalIndex = i;
|
||||
}
|
||||
} else {
|
||||
throw new IllegalStateException("I literally have no idea " + Arrays.asList(positionsToBreak));
|
||||
}
|
||||
/*
|
||||
double sum = 0;
|
||||
HashSet<BlockPos> toBreak = new HashSet();
|
||||
for (BlockPos positionsToBreak1 : positionsToBreak) {
|
||||
toBreak.add(positionsToBreak1);
|
||||
if (this instanceof ActionFall) {//if we are digging straight down, assume we have already broken the sand above us
|
||||
continue;
|
||||
}
|
||||
BlockPos tmp = positionsToBreak1.up();
|
||||
while (canFall(tmp)) {
|
||||
toBreak.add(tmp);
|
||||
tmp = tmp.up();
|
||||
}
|
||||
}
|
||||
|
||||
double sum = 0;
|
||||
for (int i = 0; i < positionsToBreak.length; i++) {
|
||||
sum += MovementHelper.getMiningDurationTicks(ctx, positionsToBreak[i], firstColumnMaximalIndex == i || secondColumnMaximalIndex == i);
|
||||
for (BlockPos pos : toBreak) {
|
||||
sum += getHardness(ts, Baritone.get(pos), pos);
|
||||
if (sum >= COST_INF) {
|
||||
break;
|
||||
return COST_INF;
|
||||
}
|
||||
}
|
||||
if (!Baritone.allowBreakOrPlace || !Baritone.hasThrowaway) {
|
||||
for (int i = 0; i < blocksToPlace.length; i++) {
|
||||
if (!canWalkOn(positionsToPlace[i])) {
|
||||
return COST_INF;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
//^ the above implementation properly deals with falling blocks, TODO integrate
|
||||
double sum = 0;
|
||||
for (BlockPos pos : positionsToBreak) {
|
||||
sum += MovementHelper.getMiningDurationTicks(ctx, pos);
|
||||
if (sum >= COST_INF) {
|
||||
return COST_INF;
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
@@ -275,27 +225,23 @@ public abstract class Movement implements Helper, MovementHelper {
|
||||
* @return
|
||||
*/
|
||||
public MovementState updateState(MovementState state) {
|
||||
if (!prepared(state)) {
|
||||
if (!prepared(state))
|
||||
return state.setStatus(MovementStatus.PREPPING);
|
||||
} else if (state.getStatus() == MovementStatus.PREPPING) {
|
||||
else if (state.getStatus() == MovementStatus.PREPPING) {
|
||||
state.setStatus(MovementStatus.WAITING);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
public BlockPos getDirection() {
|
||||
return getDest().subtract(getSrc());
|
||||
}
|
||||
public ArrayList<BlockPos> toBreakCached = null;
|
||||
public ArrayList<BlockPos> toPlaceCached = null;
|
||||
public ArrayList<BlockPos> toWalkIntoCached = null;
|
||||
|
||||
public List<BlockPos> toBreakCached = null;
|
||||
public List<BlockPos> toPlaceCached = null;
|
||||
public List<BlockPos> toWalkIntoCached = null;
|
||||
|
||||
public List<BlockPos> toBreak() {
|
||||
public ArrayList<BlockPos> toBreak() {
|
||||
if (toBreakCached != null) {
|
||||
return toBreakCached;
|
||||
}
|
||||
List<BlockPos> result = new ArrayList<>();
|
||||
ArrayList<BlockPos> result = new ArrayList<>();
|
||||
for (BlockPos positionToBreak : positionsToBreak) {
|
||||
if (!MovementHelper.canWalkThrough(positionToBreak)) {
|
||||
result.add(positionToBreak);
|
||||
@@ -305,11 +251,11 @@ public abstract class Movement implements Helper, MovementHelper {
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<BlockPos> toPlace() {
|
||||
public ArrayList<BlockPos> toPlace() {
|
||||
if (toPlaceCached != null) {
|
||||
return toPlaceCached;
|
||||
}
|
||||
List<BlockPos> result = new ArrayList<>();
|
||||
ArrayList<BlockPos> result = new ArrayList<>();
|
||||
for (BlockPos positionToBreak : positionsToPlace) {
|
||||
if (!MovementHelper.canWalkOn(positionToBreak)) {
|
||||
result.add(positionToBreak);
|
||||
@@ -319,7 +265,7 @@ public abstract class Movement implements Helper, MovementHelper {
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<BlockPos> toWalkInto() { // overridden by movementdiagonal
|
||||
public ArrayList<BlockPos> toWalkInto() { // overridden by movementdiagonal
|
||||
if (toWalkIntoCached == null) {
|
||||
toWalkIntoCached = new ArrayList<>();
|
||||
}
|
||||
@@ -15,27 +15,24 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.movement;
|
||||
package baritone.bot.pathing.movement;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.behavior.impl.LookBehaviorUtils;
|
||||
import baritone.pathing.movement.MovementState.MovementTarget;
|
||||
import baritone.pathing.movement.movements.MovementDescend;
|
||||
import baritone.pathing.movement.movements.MovementFall;
|
||||
import baritone.utils.*;
|
||||
import baritone.bot.Baritone;
|
||||
import baritone.bot.behavior.impl.LookBehaviorUtils;
|
||||
import baritone.bot.pathing.movement.MovementState.MovementTarget;
|
||||
import baritone.bot.pathing.movement.movements.MovementDescend;
|
||||
import baritone.bot.pathing.movement.movements.MovementFall;
|
||||
import baritone.bot.utils.*;
|
||||
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.entity.Entity;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.NonNullList;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.world.chunk.EmptyChunk;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -50,14 +47,13 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
Block b = state.getBlock();
|
||||
BlockPos below = new BlockPos(pos.getX(), pos.getY() - 1, pos.getZ());
|
||||
return Blocks.ICE.equals(b) // ice becomes water, and water can mess up the path
|
||||
|| b instanceof BlockSilverfish // obvious reasons
|
||||
|| b instanceof BlockSilverfish
|
||||
|| BlockStateInterface.isLiquid(new BlockPos(pos.getX(), pos.getY() + 1, pos.getZ()))//don't break anything touching liquid on any side
|
||||
|| BlockStateInterface.isLiquid(new BlockPos(pos.getX() + 1, pos.getY(), pos.getZ()))
|
||||
|| BlockStateInterface.isLiquid(new BlockPos(pos.getX() - 1, pos.getY(), pos.getZ()))
|
||||
|| BlockStateInterface.isLiquid(new BlockPos(pos.getX(), pos.getY(), pos.getZ() + 1))
|
||||
|| BlockStateInterface.isLiquid(new BlockPos(pos.getX(), pos.getY(), pos.getZ() - 1))
|
||||
|| (!(b instanceof BlockLilyPad && BlockStateInterface.isWater(below)) && BlockStateInterface.isLiquid(below));//if it's a lilypad above water, it's ok to break, otherwise don't break if its liquid
|
||||
// TODO revisit this. why is it not okay to break non-lilypads that are right above water?
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,93 +68,58 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
|
||||
static boolean canWalkThrough(BlockPos pos, IBlockState state) {
|
||||
Block block = state.getBlock();
|
||||
if (block instanceof BlockFire
|
||||
if (block instanceof BlockLilyPad
|
||||
|| block instanceof BlockFire
|
||||
|| block instanceof BlockTripWire
|
||||
|| block instanceof BlockWeb
|
||||
|| block instanceof BlockEndPortal) {//you can't actually walk through a lilypad from the side, and you shouldn't walk through fire
|
||||
return false;
|
||||
}
|
||||
if (block instanceof BlockDoor || block instanceof BlockFenceGate) {
|
||||
if (block == Blocks.IRON_DOOR) {
|
||||
return false;
|
||||
}
|
||||
return true; // we can just open the door
|
||||
}
|
||||
if (block instanceof BlockSnow || block instanceof BlockTrapDoor) {
|
||||
// we've already checked doors
|
||||
// so the only remaining dynamic isPassables are snow, fence gate, and trapdoor
|
||||
// if they're cached as a top block, we don't know their metadata
|
||||
// default to true (mostly because it would otherwise make long distance pathing through snowy biomes impossible)
|
||||
if (mc.world.getChunk(pos) instanceof EmptyChunk) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
IBlockState up = BlockStateInterface.get(pos.up());
|
||||
if (BlockStateInterface.isFlowing(state) || up.getBlock() instanceof BlockLiquid || up.getBlock() instanceof BlockLilyPad) {
|
||||
if (BlockStateInterface.isFlowing(state) || BlockStateInterface.isLiquid(pos.up())) {
|
||||
return false; // Don't walk through flowing liquids
|
||||
}
|
||||
if (block instanceof BlockDoor) {
|
||||
return true; // we can just open the door
|
||||
}
|
||||
return block.isPassable(mc.world, pos);
|
||||
}
|
||||
|
||||
static boolean isReplacable(BlockPos pos, IBlockState state) {
|
||||
// for MovementTraverse and MovementAscend
|
||||
// block double plant defaults to true when the block doesn't match, so don't need to check that case
|
||||
// all other overrides just return true or false
|
||||
// the only case to deal with is snow
|
||||
/*
|
||||
* public boolean isReplaceable(IBlockAccess worldIn, BlockPos pos)
|
||||
* {
|
||||
* return ((Integer)worldIn.getBlockState(pos).getValue(LAYERS)).intValue() == 1;
|
||||
* }
|
||||
*/
|
||||
if (state.getBlock() instanceof BlockSnow) {
|
||||
// as before, default to true (mostly because it would otherwise make long distance pathing through snowy biomes impossible)
|
||||
if (mc.world.getChunk(pos) instanceof EmptyChunk) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return state.getBlock().isReplaceable(mc.world, pos);
|
||||
}
|
||||
|
||||
static boolean isDoorPassable(BlockPos doorPos, BlockPos playerPos) {
|
||||
if (playerPos.equals(doorPos))
|
||||
return false;
|
||||
|
||||
IBlockState state = BlockStateInterface.get(doorPos);
|
||||
if (!(state.getBlock() instanceof BlockDoor))
|
||||
IBlockState door = BlockStateInterface.get(doorPos);
|
||||
if (!(door.getBlock() instanceof BlockDoor)) {
|
||||
return true;
|
||||
|
||||
return isHorizontalBlockPassable(doorPos, state, playerPos, BlockDoor.OPEN);
|
||||
}
|
||||
|
||||
static boolean isGatePassable(BlockPos gatePos, BlockPos playerPos) {
|
||||
if (playerPos.equals(gatePos))
|
||||
}
|
||||
String facing = door.getValue(BlockDoor.FACING).getName();
|
||||
boolean open = door.getValue(BlockDoor.OPEN).booleanValue();
|
||||
/**
|
||||
* yes this is dumb
|
||||
* change it if you want
|
||||
*/
|
||||
String playerFacing = "";
|
||||
if (playerPos.equals(doorPos)) {
|
||||
return false;
|
||||
|
||||
IBlockState state = BlockStateInterface.get(gatePos);
|
||||
if (!(state.getBlock() instanceof BlockFenceGate))
|
||||
return true;
|
||||
|
||||
return isHorizontalBlockPassable(gatePos, state, playerPos, BlockFenceGate.OPEN);
|
||||
}
|
||||
|
||||
static boolean isHorizontalBlockPassable(BlockPos blockPos, IBlockState blockState, BlockPos playerPos, PropertyBool propertyOpen) {
|
||||
if (playerPos.equals(blockPos))
|
||||
return false;
|
||||
|
||||
EnumFacing.Axis facing = blockState.getValue(BlockHorizontal.FACING).getAxis();
|
||||
boolean open = blockState.getValue(propertyOpen);
|
||||
|
||||
EnumFacing.Axis playerFacing;
|
||||
if (playerPos.north().equals(blockPos) || playerPos.south().equals(blockPos)) {
|
||||
playerFacing = EnumFacing.Axis.Z;
|
||||
} else if (playerPos.east().equals(blockPos) || playerPos.west().equals(blockPos)) {
|
||||
playerFacing = EnumFacing.Axis.X;
|
||||
}
|
||||
if (playerPos.north().equals(doorPos) || playerPos.south().equals(doorPos)) {
|
||||
playerFacing = "northsouth";
|
||||
} else if (playerPos.east().equals(doorPos) || playerPos.west().equals(doorPos)) {
|
||||
playerFacing = "eastwest";
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
return facing == playerFacing == open;
|
||||
if (facing == "north" || facing == "south") {
|
||||
if (open) {
|
||||
return playerFacing == "northsouth";
|
||||
} else {
|
||||
return playerFacing == "eastwest";
|
||||
}
|
||||
} else {
|
||||
if (open) {
|
||||
return playerFacing == "eastwest";
|
||||
} else {
|
||||
return playerFacing == "northsouth";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static boolean avoidWalkingInto(Block block) {
|
||||
@@ -177,22 +138,16 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
* @return
|
||||
*/
|
||||
static boolean canWalkOn(BlockPos pos, IBlockState state) {
|
||||
|
||||
Block block = state.getBlock();
|
||||
if (block instanceof BlockLadder || (Baritone.settings().allowVines.get() && block instanceof BlockVine)) { // TODO reconsider this
|
||||
return true;
|
||||
}
|
||||
if (block instanceof BlockGlass || block instanceof BlockStainedGlass) {
|
||||
return true;
|
||||
}
|
||||
if (Blocks.FARMLAND.equals(block) || Blocks.GRASS_PATH.equals(block)) {
|
||||
if (block instanceof BlockLadder || block instanceof BlockVine) { // TODO reconsider this
|
||||
return true;
|
||||
}
|
||||
if (block instanceof BlockAir) {
|
||||
return false;
|
||||
}
|
||||
if (BlockStateInterface.isWater(block)) {
|
||||
Block up = BlockStateInterface.get(pos.up()).getBlock();
|
||||
return BlockStateInterface.isWater(up) || up instanceof BlockLilyPad; // You can only walk on water if there is water above it
|
||||
return BlockStateInterface.isWater(pos.up()); // You can only walk on water if there is water above it
|
||||
}
|
||||
if (Blocks.MAGMA.equals(block)) {
|
||||
return false;
|
||||
@@ -208,12 +163,12 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
return BlockStateInterface.get(pos).getBlock() instanceof BlockFalling;
|
||||
}
|
||||
|
||||
static double getMiningDurationTicks(CalculationContext context, BlockPos position, boolean includeFalling) {
|
||||
static double getMiningDurationTicks(CalculationContext context, BlockPos position) {
|
||||
IBlockState state = BlockStateInterface.get(position);
|
||||
return getMiningDurationTicks(context, position, state, includeFalling);
|
||||
return getMiningDurationTicks(context, position, state);
|
||||
}
|
||||
|
||||
static double getMiningDurationTicks(CalculationContext context, BlockPos position, IBlockState state, boolean includeFalling) {
|
||||
static double getMiningDurationTicks(CalculationContext context, BlockPos position, IBlockState state) {
|
||||
Block block = state.getBlock();
|
||||
if (!block.equals(Blocks.AIR) && !canWalkThrough(position, state)) { // TODO is the air check really necessary? Isn't air canWalkThrough?
|
||||
if (!context.allowBreak()) {
|
||||
@@ -223,17 +178,9 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
return COST_INF;
|
||||
}
|
||||
double m = Blocks.CRAFTING_TABLE.equals(block) ? 10 : 1; // TODO see if this is still necessary. it's from MineBot when we wanted to penalize breaking its crafting table
|
||||
double result = m / context.getToolSet().getStrVsBlock(state, position);
|
||||
if (includeFalling) {
|
||||
BlockPos up = position.up();
|
||||
IBlockState above = BlockStateInterface.get(up);
|
||||
if (above.getBlock() instanceof BlockFalling) {
|
||||
result += getMiningDurationTicks(context, up, above, true);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return m / context.getToolSet().getStrVsBlock(state, position);
|
||||
}
|
||||
return 0; // we won't actually mine it, so don't check fallings above
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -301,40 +248,36 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
}
|
||||
|
||||
static void moveTowards(MovementState state, BlockPos pos) {
|
||||
state.setTarget(new MovementTarget(
|
||||
new Rotation(Utils.calcRotationFromVec3d(mc.player.getPositionEyes(1.0F),
|
||||
Utils.getBlockPosCenter(pos),
|
||||
new Rotation(mc.player.rotationYaw, mc.player.rotationPitch)).getFirst(), mc.player.rotationPitch),
|
||||
false
|
||||
)).setInput(InputOverrideHandler.Input.MOVE_FORWARD, true);
|
||||
state.setTarget(new MovementTarget(new Rotation(Utils.calcRotationFromVec3d(mc.player.getPositionEyes(1.0F),
|
||||
Utils.getBlockPosCenter(pos),
|
||||
new Rotation(mc.player.rotationYaw, mc.player.rotationPitch)).getFirst(), mc.player.rotationPitch))
|
||||
).setInput(InputOverrideHandler.Input.MOVE_FORWARD, true);
|
||||
}
|
||||
|
||||
static Movement generateMovementFallOrDescend(BlockPos pos, BlockPos dest, CalculationContext calcContext) {
|
||||
// A
|
||||
//SA
|
||||
// A
|
||||
// B
|
||||
// B
|
||||
// C
|
||||
// D
|
||||
//if S is where you start, B needs to be air for a movementfall
|
||||
//if S is where you start, both of B need to be air for a movementfall
|
||||
//A is plausibly breakable by either descend or fall
|
||||
//C, D, etc determine the length of the fall
|
||||
for (int i = 1; i < 3; i++) {
|
||||
if (!canWalkThrough(dest.down(i))) {
|
||||
//if any of these two (B in the diagram) aren't air
|
||||
//have to do a descend, because fall is impossible
|
||||
|
||||
if (!canWalkThrough(dest.down(2))) {
|
||||
//if B in the diagram aren't air
|
||||
//have to do a descend, because fall is impossible
|
||||
|
||||
//this doesn't guarantee descend is possible, it just guarantees fall is impossible
|
||||
return new MovementDescend(pos, dest.down()); // standard move out by 1 and descend by 1
|
||||
//this doesn't guarantee descend is possible, it just guarantees fall is impossible
|
||||
return new MovementDescend(pos, dest.down()); // standard move out by 1 and descend by 1
|
||||
}
|
||||
}
|
||||
|
||||
// we're clear for a fall 2
|
||||
// let's see how far we can fall
|
||||
for (int fallHeight = 3; true; fallHeight++) {
|
||||
BlockPos onto = dest.down(fallHeight);
|
||||
if (onto.getY() < 0) {
|
||||
// when pathing in the end, where you could plausibly fall into the void
|
||||
// this check prevents it from getting the block at y=-1 and crashing
|
||||
break;
|
||||
}
|
||||
IBlockState ontoBlock = BlockStateInterface.get(onto);
|
||||
@@ -345,7 +288,7 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
continue;
|
||||
}
|
||||
if (canWalkOn(onto, ontoBlock)) {
|
||||
if ((calcContext.hasWaterBucket() && fallHeight <= calcContext.maxFallHeightBucket() + 1) || fallHeight <= calcContext.maxFallHeightNoWater() + 1) {
|
||||
if (calcContext.hasWaterBucket() || fallHeight <= 4) {
|
||||
// fallHeight = 4 means onto.up() is 3 blocks down, which is the max
|
||||
return new MovementFall(pos, onto.up());
|
||||
} else {
|
||||
@@ -15,10 +15,10 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.movement;
|
||||
package baritone.bot.pathing.movement;
|
||||
|
||||
import baritone.utils.InputOverrideHandler.Input;
|
||||
import baritone.utils.Rotation;
|
||||
import baritone.bot.utils.InputOverrideHandler.Input;
|
||||
import baritone.bot.utils.Rotation;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
import java.util.HashMap;
|
||||
@@ -93,29 +93,21 @@ public class MovementState {
|
||||
*/
|
||||
public Rotation rotation;
|
||||
|
||||
/**
|
||||
* Whether or not this target must force rotations.
|
||||
* <p>
|
||||
* {@code true} if we're trying to place or break blocks, {@code false} if we're trying to look at the movement location
|
||||
*/
|
||||
private boolean forceRotations;
|
||||
|
||||
public MovementTarget() {
|
||||
this(null, null, false);
|
||||
this(null, null);
|
||||
}
|
||||
|
||||
public MovementTarget(Vec3d position) {
|
||||
this(position, null, false);
|
||||
this(position, null);
|
||||
}
|
||||
|
||||
public MovementTarget(Rotation rotation, boolean forceRotations) {
|
||||
this(null, rotation, forceRotations);
|
||||
public MovementTarget(Rotation rotation) {
|
||||
this(null, rotation);
|
||||
}
|
||||
|
||||
public MovementTarget(Vec3d position, Rotation rotation, boolean forceRotations) {
|
||||
public MovementTarget(Vec3d position, Rotation rotation) {
|
||||
this.position = position;
|
||||
this.rotation = rotation;
|
||||
this.forceRotations = forceRotations;
|
||||
}
|
||||
|
||||
public final Optional<Vec3d> getPosition() {
|
||||
@@ -125,9 +117,5 @@ public class MovementState {
|
||||
public final Optional<Rotation> getRotation() {
|
||||
return Optional.ofNullable(this.rotation);
|
||||
}
|
||||
|
||||
public boolean hasToForceRotations() {
|
||||
return this.forceRotations;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,17 +15,17 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.movement.movements;
|
||||
package baritone.bot.pathing.movement.movements;
|
||||
|
||||
import baritone.behavior.impl.LookBehaviorUtils;
|
||||
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.MovementStatus;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.InputOverrideHandler;
|
||||
import baritone.utils.Utils;
|
||||
import baritone.bot.behavior.impl.LookBehaviorUtils;
|
||||
import baritone.bot.pathing.movement.CalculationContext;
|
||||
import baritone.bot.pathing.movement.Movement;
|
||||
import baritone.bot.pathing.movement.MovementHelper;
|
||||
import baritone.bot.pathing.movement.MovementState;
|
||||
import baritone.bot.pathing.movement.MovementState.MovementStatus;
|
||||
import baritone.bot.utils.BlockStateInterface;
|
||||
import baritone.bot.utils.InputOverrideHandler;
|
||||
import baritone.bot.utils.Utils;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockFalling;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
@@ -64,20 +64,15 @@ public class MovementAscend extends Movement {
|
||||
// Counterpoint to the above TODO ^ you should move then pillar instead of ascend
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
ticksWithoutPlacement = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double calculateCost(CalculationContext context) {
|
||||
IBlockState toPlace = BlockStateInterface.get(positionsToPlace[0]);
|
||||
if (!MovementHelper.canWalkOn(positionsToPlace[0], toPlace)) {
|
||||
if (!context.hasThrowaway()) {
|
||||
if (!BlockStateInterface.isAir(toPlace) && !BlockStateInterface.isWater(toPlace.getBlock())) {
|
||||
// TODO replace this check with isReplacable or similar
|
||||
return COST_INF;
|
||||
}
|
||||
if (!BlockStateInterface.isAir(toPlace) && !BlockStateInterface.isWater(toPlace.getBlock()) && !MovementHelper.isReplacable(positionsToPlace[0], toPlace)) {
|
||||
if (!context.hasThrowaway()) {
|
||||
return COST_INF;
|
||||
}
|
||||
for (BlockPos against1 : against) {
|
||||
@@ -124,15 +119,14 @@ public class MovementAscend extends Movement {
|
||||
// for efficiency in ascending minimal height staircases, which is just repeated MovementAscend, so that it doesn't bonk its head on the ceiling repeatedly)
|
||||
switch (state.getStatus()) {
|
||||
case WAITING:
|
||||
state.setStatus(MovementStatus.RUNNING);
|
||||
case RUNNING:
|
||||
break;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
||||
if (playerFeet().equals(dest)) {
|
||||
return state.setStatus(MovementStatus.SUCCESS);
|
||||
state.setStatus(MovementStatus.SUCCESS);
|
||||
return state;
|
||||
}
|
||||
|
||||
if (!MovementHelper.canWalkOn(positionsToPlace[0])) {
|
||||
@@ -144,58 +138,36 @@ public class MovementAscend extends Movement {
|
||||
double faceX = (dest.getX() + anAgainst.getX() + 1.0D) * 0.5D;
|
||||
double faceY = (dest.getY() + anAgainst.getY()) * 0.5D;
|
||||
double faceZ = (dest.getZ() + anAgainst.getZ() + 1.0D) * 0.5D;
|
||||
state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(playerHead(), new Vec3d(faceX, faceY, faceZ), playerRotations()), true));
|
||||
state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(playerHead(), new Vec3d(faceX, faceY, faceZ), playerRotations())));
|
||||
EnumFacing side = Minecraft.getMinecraft().objectMouseOver.sideHit;
|
||||
|
||||
LookBehaviorUtils.getSelectedBlock().ifPresent(selectedBlock -> {
|
||||
if (Objects.equals(selectedBlock, anAgainst) && selectedBlock.offset(side).equals(positionsToPlace[0])) {
|
||||
ticksWithoutPlacement++;
|
||||
state.setInput(InputOverrideHandler.Input.SNEAK, true);
|
||||
if (player().isSneaking()) {
|
||||
state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true);
|
||||
}
|
||||
if (ticksWithoutPlacement > 20) {
|
||||
// After 20 ticks without placement, we might be standing in the way, move back
|
||||
state.setInput(InputOverrideHandler.Input.MOVE_BACK, true);
|
||||
}
|
||||
if (Objects.equals(LookBehaviorUtils.getSelectedBlock().orElse(null), anAgainst) && LookBehaviorUtils.getSelectedBlock().get().offset(side).equals(positionsToPlace[0])) {
|
||||
ticksWithoutPlacement++;
|
||||
state.setInput(InputOverrideHandler.Input.SNEAK, true);
|
||||
if (player().isSneaking()) {
|
||||
state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true);
|
||||
}
|
||||
System.out.println("Trying to look at " + anAgainst + ", actually looking at" + selectedBlock);
|
||||
});
|
||||
if (ticksWithoutPlacement > 20) {
|
||||
state.setInput(InputOverrideHandler.Input.MOVE_BACK, true);//we might be standing in the way, move back
|
||||
}
|
||||
}
|
||||
System.out.println("Trying to look at " + anAgainst + ", actually looking at" + LookBehaviorUtils.getSelectedBlock());
|
||||
return state;
|
||||
}
|
||||
}
|
||||
return state.setStatus(MovementStatus.UNREACHABLE);
|
||||
}
|
||||
MovementHelper.moveTowards(state, dest);
|
||||
state.setInput(InputOverrideHandler.Input.JUMP, true);
|
||||
|
||||
if (headBonkClear()) {
|
||||
return state.setInput(InputOverrideHandler.Input.JUMP, true);
|
||||
}
|
||||
// TODO check if the below actually helps or hurts, it's weird
|
||||
//double flatDistToNext = Math.abs(to.getX() - from.getX()) * Math.abs((to.getX() + 0.5D) - thePlayer.posX) + Math.abs(to.getZ() - from.getZ()) * Math.abs((to.getZ() + 0.5D) - thePlayer.posZ);
|
||||
//boolean pointingInCorrectDirection = MovementManager.moveTowardsBlock(to);
|
||||
//MovementManager.jumping = flatDistToNext < 1.2 && pointingInCorrectDirection;
|
||||
//once we are pointing the right way and moving, start jumping
|
||||
//this is slightly more efficient because otherwise we might start jumping before moving, and fall down without moving onto the block we want to jump onto
|
||||
//also wait until we are close enough, because we might jump and hit our head on an adjacent block
|
||||
//return Baritone.playerFeet.equals(to);
|
||||
|
||||
int xAxis = Math.abs(src.getX() - dest.getX()); // either 0 or 1
|
||||
int zAxis = Math.abs(src.getZ() - dest.getZ()); // either 0 or 1
|
||||
double flatDistToNext = xAxis * Math.abs((dest.getX() + 0.5D) - player().posX) + zAxis * Math.abs((dest.getZ() + 0.5D) - player().posZ);
|
||||
double sideDist = zAxis * Math.abs((dest.getX() + 0.5D) - player().posX) + xAxis * Math.abs((dest.getZ() + 0.5D) - player().posZ);
|
||||
// System.out.println(flatDistToNext + " " + sideDist);
|
||||
if (flatDistToNext > 1.2 || sideDist > 0.2) {
|
||||
return state;
|
||||
}
|
||||
|
||||
// Once we are pointing the right way and moving, start jumping
|
||||
// This is slightly more efficient because otherwise we might start jumping before moving, and fall down without moving onto the block we want to jump onto
|
||||
// Also wait until we are close enough, because we might jump and hit our head on an adjacent block
|
||||
return state.setInput(InputOverrideHandler.Input.JUMP, true);
|
||||
}
|
||||
|
||||
private boolean headBonkClear() {
|
||||
BlockPos startUp = src.up(2);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
BlockPos check = startUp.offset(EnumFacing.byHorizontalIndex(i));
|
||||
if (!MovementHelper.canWalkThrough(check)) {
|
||||
// We might bonk our head
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return state;
|
||||
}
|
||||
}
|
||||
@@ -15,15 +15,15 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.movement.movements;
|
||||
package baritone.bot.pathing.movement.movements;
|
||||
|
||||
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.MovementStatus;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.InputOverrideHandler;
|
||||
import baritone.bot.pathing.movement.CalculationContext;
|
||||
import baritone.bot.pathing.movement.Movement;
|
||||
import baritone.bot.pathing.movement.MovementHelper;
|
||||
import baritone.bot.pathing.movement.MovementState;
|
||||
import baritone.bot.pathing.movement.MovementState.MovementStatus;
|
||||
import baritone.bot.utils.BlockStateInterface;
|
||||
import baritone.bot.utils.InputOverrideHandler;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockLadder;
|
||||
import net.minecraft.block.BlockVine;
|
||||
@@ -36,12 +36,6 @@ public class MovementDescend extends Movement {
|
||||
super(start, end, new BlockPos[]{end.up(2), end.up(), end}, new BlockPos[]{end.down()});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
numTicks = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double calculateCost(CalculationContext context) {
|
||||
if (!MovementHelper.canWalkOn(positionsToPlace[0])) {
|
||||
@@ -73,10 +67,9 @@ public class MovementDescend extends Movement {
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
||||
BlockPos playerFeet = playerFeet();
|
||||
if (playerFeet.equals(dest)) {
|
||||
if (BlockStateInterface.isLiquid(dest) || player().posY - playerFeet.getY() < 0.094) { // lilypads
|
||||
if (BlockStateInterface.isLiquid(dest) || player().posY - playerFeet.getY() < 0.01) {
|
||||
// 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
|
||||
state.setStatus(MovementStatus.SUCCESS);
|
||||
return state;
|
||||
@@ -92,6 +85,9 @@ public class MovementDescend extends Movement {
|
||||
double fromStart = Math.sqrt(x * x + z * z);
|
||||
if (!playerFeet.equals(dest) || ab > 0.25) {
|
||||
BlockPos fakeDest = new BlockPos(dest.getX() * 2 - src.getX(), dest.getY(), dest.getZ() * 2 - src.getZ());
|
||||
double diffX2 = player().posX - (fakeDest.getX() + 0.5);
|
||||
double diffZ2 = player().posZ - (fakeDest.getZ() + 0.5);
|
||||
double d = Math.sqrt(diffX2 * diffX2 + diffZ2 * diffZ2);
|
||||
if (numTicks++ < 20) {
|
||||
MovementHelper.moveTowards(state, fakeDest);
|
||||
if (fromStart > 1.25) {
|
||||
@@ -15,14 +15,13 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.movement.movements;
|
||||
package baritone.bot.pathing.movement.movements;
|
||||
|
||||
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.bot.pathing.movement.CalculationContext;
|
||||
import baritone.bot.pathing.movement.Movement;
|
||||
import baritone.bot.pathing.movement.MovementHelper;
|
||||
import baritone.bot.pathing.movement.MovementState;
|
||||
import baritone.bot.utils.BlockStateInterface;
|
||||
import net.minecraft.block.BlockMagma;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.init.Blocks;
|
||||
@@ -30,7 +29,6 @@ import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class MovementDiagonal extends Movement {
|
||||
|
||||
@@ -54,19 +52,17 @@ public class MovementDiagonal extends Movement {
|
||||
super.updateState(state);
|
||||
switch (state.getStatus()) {
|
||||
case WAITING:
|
||||
state.setStatus(MovementState.MovementStatus.RUNNING);
|
||||
case RUNNING:
|
||||
break;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
||||
if (playerFeet().equals(dest)) {
|
||||
state.setStatus(MovementState.MovementStatus.SUCCESS);
|
||||
return state;
|
||||
}
|
||||
if (!BlockStateInterface.isLiquid(playerFeet())) {
|
||||
state.setInput(InputOverrideHandler.Input.SPRINT, true);
|
||||
player().setSprinting(true);
|
||||
}
|
||||
MovementHelper.moveTowards(state, dest);
|
||||
return state;
|
||||
@@ -83,7 +79,7 @@ public class MovementDiagonal extends Movement {
|
||||
}
|
||||
double multiplier = WALK_ONE_BLOCK_COST;
|
||||
|
||||
// For either possible soul sand, that affects half of our walking
|
||||
// for either possible soul sand, that affects half of our walking
|
||||
if (destWalkOn.getBlock().equals(Blocks.SOUL_SAND)) {
|
||||
multiplier += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2;
|
||||
}
|
||||
@@ -97,8 +93,8 @@ public class MovementDiagonal extends Movement {
|
||||
if (BlockStateInterface.get(positionsToBreak[4].down()).getBlock() instanceof BlockMagma) {
|
||||
return COST_INF;
|
||||
}
|
||||
double optionA = MovementHelper.getMiningDurationTicks(context, positionsToBreak[0], false) + MovementHelper.getMiningDurationTicks(context, positionsToBreak[1], true);
|
||||
double optionB = MovementHelper.getMiningDurationTicks(context, positionsToBreak[2], false) + MovementHelper.getMiningDurationTicks(context, positionsToBreak[3], true);
|
||||
double optionA = MovementHelper.getMiningDurationTicks(context, positionsToBreak[0]) + MovementHelper.getMiningDurationTicks(context, positionsToBreak[1]);
|
||||
double optionB = MovementHelper.getMiningDurationTicks(context, positionsToBreak[2]) + MovementHelper.getMiningDurationTicks(context, positionsToBreak[3]);
|
||||
if (optionA != 0 && optionB != 0) {
|
||||
return COST_INF;
|
||||
}
|
||||
@@ -119,17 +115,17 @@ public class MovementDiagonal extends Movement {
|
||||
}
|
||||
}
|
||||
if (BlockStateInterface.isWater(src) || BlockStateInterface.isWater(dest)) {
|
||||
// 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
|
||||
// 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
|
||||
multiplier = WALK_ONE_IN_WATER_COST;
|
||||
}
|
||||
if (optionA != 0 || optionB != 0) {
|
||||
multiplier *= SQRT_2 - 0.001; // TODO tune
|
||||
}
|
||||
if (multiplier == WALK_ONE_BLOCK_COST && context.canSprint()) {
|
||||
// If we aren't edging around anything, and we aren't in water or soul sand
|
||||
// We can sprint =D
|
||||
// if we aren't edging around anything, and we aren't in water or soul sand
|
||||
// we can sprint =D
|
||||
multiplier = SPRINT_ONE_BLOCK_COST;
|
||||
}
|
||||
return multiplier * SQRT_2;
|
||||
@@ -141,11 +137,11 @@ public class MovementDiagonal extends Movement {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BlockPos> toBreak() {
|
||||
public ArrayList<BlockPos> toBreak() {
|
||||
if (toBreakCached != null) {
|
||||
return toBreakCached;
|
||||
}
|
||||
List<BlockPos> result = new ArrayList<>();
|
||||
ArrayList<BlockPos> result = new ArrayList<>();
|
||||
for (int i = 4; i < 6; i++) {
|
||||
if (!MovementHelper.canWalkThrough(positionsToBreak[i])) {
|
||||
result.add(positionsToBreak[i]);
|
||||
@@ -156,11 +152,11 @@ public class MovementDiagonal extends Movement {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BlockPos> toWalkInto() {
|
||||
public ArrayList<BlockPos> toWalkInto() {
|
||||
if (toWalkIntoCached == null) {
|
||||
toWalkIntoCached = new ArrayList<>();
|
||||
}
|
||||
List<BlockPos> result = new ArrayList<>();
|
||||
ArrayList<BlockPos> result = new ArrayList<>();
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (!MovementHelper.canWalkThrough(positionsToBreak[i])) {
|
||||
result.add(positionsToBreak[i]);
|
||||
@@ -15,13 +15,13 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.movement.movements;
|
||||
package baritone.bot.pathing.movement.movements;
|
||||
|
||||
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.bot.pathing.movement.CalculationContext;
|
||||
import baritone.bot.pathing.movement.Movement;
|
||||
import baritone.bot.pathing.movement.MovementHelper;
|
||||
import baritone.bot.pathing.movement.MovementState;
|
||||
import baritone.bot.utils.BlockStateInterface;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockLadder;
|
||||
import net.minecraft.block.BlockVine;
|
||||
@@ -36,12 +36,6 @@ public class MovementDownward extends Movement {
|
||||
super(start, end, new BlockPos[]{end}, new BlockPos[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
numTicks = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double calculateCost(CalculationContext context) {
|
||||
if (!MovementHelper.canWalkOn(dest.down())) {
|
||||
@@ -53,8 +47,7 @@ public class MovementDownward extends Movement {
|
||||
if (ladder) {
|
||||
return LADDER_DOWN_ONE_COST;
|
||||
} else {
|
||||
// we're standing on it, while it might be block falling, it'll be air by the time we get here in the movement
|
||||
return FALL_N_BLOCKS_COST[1] + MovementHelper.getMiningDurationTicks(context, dest, d, false);
|
||||
return FALL_N_BLOCKS_COST[1] + MovementHelper.getMiningDurationTicks(context, dest, d);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,13 +56,11 @@ public class MovementDownward extends Movement {
|
||||
super.updateState(state);
|
||||
switch (state.getStatus()) {
|
||||
case WAITING:
|
||||
state.setStatus(MovementState.MovementStatus.RUNNING);
|
||||
case RUNNING:
|
||||
break;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
||||
if (playerFeet().equals(dest)) {
|
||||
state.setStatus(MovementState.MovementStatus.SUCCESS);
|
||||
return state;
|
||||
@@ -15,23 +15,27 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.movement.movements;
|
||||
package baritone.bot.pathing.movement.movements;
|
||||
|
||||
import baritone.Baritone;
|
||||
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.MovementStatus;
|
||||
import baritone.pathing.movement.MovementState.MovementTarget;
|
||||
import baritone.utils.*;
|
||||
import net.minecraft.block.BlockFalling;
|
||||
import baritone.bot.behavior.impl.LookBehaviorUtils;
|
||||
import baritone.bot.pathing.movement.CalculationContext;
|
||||
import baritone.bot.pathing.movement.Movement;
|
||||
import baritone.bot.pathing.movement.MovementHelper;
|
||||
import baritone.bot.pathing.movement.MovementState;
|
||||
import baritone.bot.pathing.movement.MovementState.MovementStatus;
|
||||
import baritone.bot.pathing.movement.MovementState.MovementTarget;
|
||||
import baritone.bot.utils.BlockStateInterface;
|
||||
import baritone.bot.utils.InputOverrideHandler;
|
||||
import baritone.bot.utils.Rotation;
|
||||
import baritone.bot.utils.Utils;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class MovementFall extends Movement {
|
||||
|
||||
private static final ItemStack STACK_BUCKET_WATER = new ItemStack(Items.WATER_BUCKET);
|
||||
@@ -47,38 +51,28 @@ public class MovementFall extends Movement {
|
||||
return COST_INF;
|
||||
}
|
||||
double placeBucketCost = 0.0;
|
||||
if (!BlockStateInterface.isWater(dest) && src.getY() - dest.getY() > context.maxFallHeightNoWater()) {
|
||||
if (!BlockStateInterface.isWater(dest) && src.getY() - dest.getY() > 3) {
|
||||
if (!context.hasWaterBucket()) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (src.getY() - dest.getY() > context.maxFallHeightBucket()) {
|
||||
return COST_INF;
|
||||
}
|
||||
placeBucketCost = context.placeBlockCost();
|
||||
}
|
||||
double frontThree = 0;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
frontThree += MovementHelper.getMiningDurationTicks(context, positionsToBreak[i], false);
|
||||
// don't include falling because we will check falling right after this, and if it's there it's COST_INF
|
||||
if (frontThree >= COST_INF) {
|
||||
return COST_INF;
|
||||
}
|
||||
}
|
||||
if (BlockStateInterface.get(positionsToBreak[0].up()).getBlock() instanceof BlockFalling) {
|
||||
double frontTwo = MovementHelper.getMiningDurationTicks(context, positionsToBreak[0]) + MovementHelper.getMiningDurationTicks(context, positionsToBreak[1]);
|
||||
if (frontTwo >= COST_INF) {
|
||||
return COST_INF;
|
||||
}
|
||||
for (int i = 3; i < positionsToBreak.length; i++) {
|
||||
for (int i = 2; i < positionsToBreak.length; i++) {
|
||||
// TODO is this the right check here?
|
||||
// MiningDurationTicks is all right, but shouldn't it be canWalkThrough instead?
|
||||
// Lilypads (i think?) are 0 ticks to mine, but they definitely cause fall damage
|
||||
// Same thing for falling through water... we can't actually do that
|
||||
// And falling through signs is possible, but they do have a mining duration, right?
|
||||
if (MovementHelper.getMiningDurationTicks(context, positionsToBreak[i], false) > 0) {
|
||||
// miningDurationTicks is all right, but shouldn't it be canWalkThrough instead?
|
||||
// lilypads (i think?) are 0 ticks to mine, but they definitely cause fall damage
|
||||
// same thing for falling through water... we can't actually do that
|
||||
// and falling through signs is possible, but they do have a mining duration, right?
|
||||
if (MovementHelper.getMiningDurationTicks(context, positionsToBreak[i]) > 0) {
|
||||
//can't break while falling
|
||||
return COST_INF;
|
||||
}
|
||||
}
|
||||
return WALK_OFF_BLOCK_COST + FALL_N_BLOCKS_COST[positionsToBreak.length - 1] + placeBucketCost + frontThree;
|
||||
return WALK_OFF_BLOCK_COST + FALL_N_BLOCKS_COST[positionsToBreak.length - 1] + placeBucketCost + frontTwo;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -92,32 +86,25 @@ public class MovementFall extends Movement {
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
||||
BlockPos playerFeet = playerFeet();
|
||||
Rotation targetRotation = null;
|
||||
if (!BlockStateInterface.isWater(dest) && src.getY() - dest.getY() > Baritone.settings().maxFallHeightNoWater.get() && !playerFeet.equals(dest)) {
|
||||
if (!player().inventory.hasItemStack(STACK_BUCKET_WATER) || world().provider.isNether()) {
|
||||
Optional<Rotation> targetRotation = Optional.empty();
|
||||
if (!BlockStateInterface.isWater(dest) && src.getY() - dest.getY() > 3 && !playerFeet.equals(dest)) {
|
||||
if (!player().inventory.hasItemStack(STACK_BUCKET_WATER) || world().provider.isNether()) { // TODO check if water bucket is on hotbar or main inventory
|
||||
state.setStatus(MovementStatus.UNREACHABLE);
|
||||
return state;
|
||||
}
|
||||
|
||||
if (player().posY - dest.getY() < mc.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) {
|
||||
state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true);
|
||||
}
|
||||
targetRotation = LookBehaviorUtils.reachable((BlockStateInterface.get(dest).getCollisionBoundingBox(mc.world, dest) == Block.NULL_AABB) ? dest : dest.down());
|
||||
}
|
||||
}
|
||||
if (targetRotation != null) {
|
||||
state.setTarget(new MovementTarget(targetRotation, true));
|
||||
if (targetRotation.isPresent()) {
|
||||
state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true)
|
||||
.setTarget(new MovementTarget(targetRotation.get()));
|
||||
} else {
|
||||
state.setTarget(new MovementTarget(Utils.calcRotationFromVec3d(playerHead(), Utils.getBlockPosCenter(dest)), false));
|
||||
state.setTarget(new MovementTarget(Utils.calcRotationFromVec3d(playerHead(), Utils.getBlockPosCenter(dest))));
|
||||
}
|
||||
if (playerFeet.equals(dest) && (player().posY - playerFeet.getY() < 0.094 // lilypads
|
||||
if (playerFeet.equals(dest) && (player().posY - playerFeet.getY() < 0.01
|
||||
|| BlockStateInterface.isWater(dest))) {
|
||||
if (BlockStateInterface.isWater(dest) && player().inventory.hasItemStack(STACK_BUCKET_EMPTY)) {
|
||||
player().inventory.currentItem = player().inventory.getSlotFor(STACK_BUCKET_EMPTY);
|
||||
@@ -15,16 +15,16 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.movement.movements;
|
||||
package baritone.bot.pathing.movement.movements;
|
||||
|
||||
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.Rotation;
|
||||
import baritone.utils.Utils;
|
||||
import baritone.bot.pathing.movement.CalculationContext;
|
||||
import baritone.bot.pathing.movement.Movement;
|
||||
import baritone.bot.pathing.movement.MovementHelper;
|
||||
import baritone.bot.pathing.movement.MovementState;
|
||||
import baritone.bot.utils.BlockStateInterface;
|
||||
import baritone.bot.utils.InputOverrideHandler;
|
||||
import baritone.bot.utils.Rotation;
|
||||
import baritone.bot.utils.Utils;
|
||||
import net.minecraft.block.*;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
@@ -38,12 +38,6 @@ public class MovementPillar extends Movement {
|
||||
super(start, end, new BlockPos[]{start.up(2)}, new BlockPos[]{start});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
numTicks = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double calculateCost(CalculationContext context) {
|
||||
Block fromDown = BlockStateInterface.get(src).getBlock();
|
||||
@@ -93,13 +87,13 @@ public class MovementPillar extends Movement {
|
||||
return vine.north();
|
||||
}
|
||||
if (BlockStateInterface.get(vine.south()).isBlockNormalCube()) {
|
||||
return vine.south();
|
||||
return vine.north();
|
||||
}
|
||||
if (BlockStateInterface.get(vine.east()).isBlockNormalCube()) {
|
||||
return vine.east();
|
||||
return vine.north();
|
||||
}
|
||||
if (BlockStateInterface.get(vine.west()).isBlockNormalCube()) {
|
||||
return vine.west();
|
||||
return vine.north();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -109,83 +103,70 @@ public class MovementPillar extends Movement {
|
||||
super.updateState(state);
|
||||
switch (state.getStatus()) {
|
||||
case WAITING:
|
||||
state.setStatus(MovementState.MovementStatus.RUNNING);
|
||||
case RUNNING:
|
||||
break;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
||||
IBlockState fromDown = BlockStateInterface.get(src);
|
||||
boolean ladder = fromDown.getBlock() instanceof BlockLadder || fromDown.getBlock() instanceof BlockVine;
|
||||
boolean vine = fromDown.getBlock() instanceof BlockVine;
|
||||
if (!ladder) {
|
||||
state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(mc.player.getPositionEyes(1.0F),
|
||||
Utils.getBlockPosCenter(positionsToPlace[0]),
|
||||
new Rotation(mc.player.rotationYaw, mc.player.rotationPitch)), true));
|
||||
new Rotation(mc.player.rotationYaw, mc.player.rotationPitch))));
|
||||
}
|
||||
|
||||
EntityPlayerSP thePlayer = Minecraft.getMinecraft().player;
|
||||
boolean blockIsThere = MovementHelper.canWalkOn(src) || ladder;
|
||||
if (ladder) {
|
||||
BlockPos against = vine ? getAgainst(src) : src.offset(fromDown.getValue(BlockLadder.FACING).getOpposite());
|
||||
if (against == null) {
|
||||
displayChatMessageRaw("Unable to climb vines");
|
||||
return state.setStatus(MovementState.MovementStatus.UNREACHABLE);
|
||||
}
|
||||
|
||||
if (playerFeet().equals(against.up()) || playerFeet().equals(dest))
|
||||
return state.setStatus(MovementState.MovementStatus.SUCCESS);
|
||||
|
||||
/*
|
||||
if (thePlayer.getPosition0().getX() != from.getX() || thePlayer.getPosition0().getZ() != from.getZ()) {
|
||||
Baritone.moveTowardsBlock(from);
|
||||
}
|
||||
*/
|
||||
|
||||
MovementHelper.moveTowards(state, against);
|
||||
return state;
|
||||
} else {
|
||||
// Get ready to place a throwaway block
|
||||
if (!MovementHelper.throwaway(true)) {
|
||||
state.setStatus(MovementState.MovementStatus.UNREACHABLE);
|
||||
return state;
|
||||
}
|
||||
|
||||
if (playerFeet().equals(against.up()) || playerFeet().equals(dest)) {
|
||||
state.setStatus(MovementState.MovementStatus.SUCCESS);
|
||||
return state;
|
||||
}
|
||||
/*if (thePlayer.getPosition0().getX() != from.getX() || thePlayer.getPosition0().getZ() != from.getZ()) {
|
||||
Baritone.moveTowardsBlock(from);
|
||||
}*/
|
||||
MovementHelper.moveTowards(state, against);
|
||||
return state;
|
||||
} else {
|
||||
if (!MovementHelper.throwaway(true)) {//get ready to place a throwaway block
|
||||
state.setStatus(MovementState.MovementStatus.UNREACHABLE);
|
||||
return state;
|
||||
}
|
||||
numTicks++;
|
||||
// If our Y coordinate is above our goal, stop jumping
|
||||
state.setInput(InputOverrideHandler.Input.JUMP, player().posY < dest.getY());
|
||||
state.setInput(InputOverrideHandler.Input.JUMP, thePlayer.posY < dest.getY()); //if our Y coordinate is above our goal, stop jumping
|
||||
state.setInput(InputOverrideHandler.Input.SNEAK, true);
|
||||
|
||||
// Otherwise jump
|
||||
//otherwise jump
|
||||
if (numTicks > 40) {
|
||||
double diffX = player().posX - (dest.getX() + 0.5);
|
||||
double diffZ = player().posZ - (dest.getZ() + 0.5);
|
||||
double diffX = thePlayer.posX - (dest.getX() + 0.5);
|
||||
double diffZ = thePlayer.posZ - (dest.getZ() + 0.5);
|
||||
double dist = Math.sqrt(diffX * diffX + diffZ * diffZ);
|
||||
if (dist > 0.17) {//why 0.17? because it seemed like a good number, that's why
|
||||
//[explanation added after baritone port lol] also because it needs to be less than 0.2 because of the 0.3 sneak limit
|
||||
//and 0.17 is reasonably less than 0.2
|
||||
|
||||
// If it's been more than forty ticks of trying to jump and we aren't done yet, go forward, maybe we are stuck
|
||||
state.setInput(InputOverrideHandler.Input.MOVE_FORWARD, true);
|
||||
state.setInput(InputOverrideHandler.Input.MOVE_FORWARD, true);//if it's been more than forty ticks of trying to jump and we aren't done yet, go forward, maybe we are stuck
|
||||
}
|
||||
}
|
||||
|
||||
if (!blockIsThere) {
|
||||
Block fr = BlockStateInterface.get(src).getBlock();
|
||||
if (!(fr instanceof BlockAir || fr.isReplaceable(Minecraft.getMinecraft().world, src))) {
|
||||
state.setInput(InputOverrideHandler.Input.CLICK_LEFT, true);
|
||||
blockIsThere = false;
|
||||
} else if (Minecraft.getMinecraft().player.isSneaking()) {
|
||||
state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true);
|
||||
state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true);//constantly right click
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we are at our goal and the block below us is placed
|
||||
if (playerFeet().equals(dest) && blockIsThere) {
|
||||
return state.setStatus(MovementState.MovementStatus.SUCCESS);
|
||||
if (playerFeet().equals(dest) && blockIsThere) {//if we are at our goal and the block below us is placed
|
||||
state.setStatus(MovementState.MovementStatus.SUCCESS);
|
||||
return state;//we are done
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
}
|
||||
@@ -15,17 +15,20 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.movement.movements;
|
||||
package baritone.bot.pathing.movement.movements;
|
||||
|
||||
import baritone.behavior.impl.LookBehaviorUtils;
|
||||
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.Utils;
|
||||
import net.minecraft.block.*;
|
||||
import baritone.bot.behavior.impl.LookBehaviorUtils;
|
||||
import baritone.bot.pathing.movement.CalculationContext;
|
||||
import baritone.bot.pathing.movement.Movement;
|
||||
import baritone.bot.pathing.movement.MovementHelper;
|
||||
import baritone.bot.pathing.movement.MovementState;
|
||||
import baritone.bot.utils.BlockStateInterface;
|
||||
import baritone.bot.utils.InputOverrideHandler;
|
||||
import baritone.bot.utils.Utils;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockDoor;
|
||||
import net.minecraft.block.BlockLadder;
|
||||
import net.minecraft.block.BlockVine;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.init.Blocks;
|
||||
@@ -63,12 +66,6 @@ public class MovementTraverse extends Movement {
|
||||
//note: do NOT add ability to place against .down().down()
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
wasTheBridgeBlockAlwaysThere = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double calculateCost(CalculationContext context) {
|
||||
IBlockState pb0 = BlockStateInterface.get(positionsToBreak[0]);
|
||||
@@ -86,17 +83,17 @@ public class MovementTraverse extends Movement {
|
||||
WC += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2;
|
||||
}
|
||||
}
|
||||
if (MovementHelper.canWalkThrough(positionsToBreak[0], pb0) && MovementHelper.canWalkThrough(positionsToBreak[1], pb1)) {
|
||||
if (MovementHelper.canWalkThrough(positionsToBreak[0]) && MovementHelper.canWalkThrough(positionsToBreak[1])) {
|
||||
if (WC == WALK_ONE_BLOCK_COST && context.canSprint()) {
|
||||
// If there's nothing in the way, and this isn't water or soul sand, and we aren't sneak placing
|
||||
// We can sprint =D
|
||||
// if there's nothing in the way, and this isn't water or soul sand, and we aren't sneak placing
|
||||
// we can sprint =D
|
||||
WC = SPRINT_ONE_BLOCK_COST;
|
||||
}
|
||||
return WC;
|
||||
}
|
||||
// double hardness1 = blocksToBreak[0].getBlockHardness(Minecraft.getMinecraft().world, positionsToBreak[0]);
|
||||
// double hardness2 = blocksToBreak[1].getBlockHardness(Minecraft.getMinecraft().world, positionsToBreak[1]);
|
||||
// Out.log("Can't walk through " + blocksToBreak[0] + " (hardness" + hardness1 + ") or " + blocksToBreak[1] + " (hardness " + hardness2 + ")");
|
||||
//double hardness1 = blocksToBreak[0].getBlockHardness(Minecraft.getMinecraft().world, positionsToBreak[0]);
|
||||
//double hardness2 = blocksToBreak[1].getBlockHardness(Minecraft.getMinecraft().world, positionsToBreak[1]);
|
||||
//Out.log("Can't walk through " + blocksToBreak[0] + " (hardness" + hardness1 + ") or " + blocksToBreak[1] + " (hardness " + hardness2 + ")");
|
||||
return WC + getTotalHardnessOfBlocksToBreak(context);
|
||||
} else {//this is a bridge, so we need to place a block
|
||||
Block srcDown = BlockStateInterface.get(src.down()).getBlock();
|
||||
@@ -104,7 +101,7 @@ public class MovementTraverse extends Movement {
|
||||
return COST_INF;
|
||||
}
|
||||
IBlockState pp0 = BlockStateInterface.get(positionsToPlace[0]);
|
||||
if (pp0.getBlock().equals(Blocks.AIR) || (!BlockStateInterface.isWater(pp0.getBlock()) && MovementHelper.isReplacable(positionsToPlace[0], pp0))) {
|
||||
if (pp0.getBlock().equals(Blocks.AIR) || (!BlockStateInterface.isWater(pp0.getBlock()) && pp0.getBlock().isReplaceable(Minecraft.getMinecraft().world, positionsToPlace[0]))) {
|
||||
if (!context.hasThrowaway()) {
|
||||
return COST_INF;
|
||||
}
|
||||
@@ -114,14 +111,14 @@ public class MovementTraverse extends Movement {
|
||||
return WC + context.placeBlockCost() + getTotalHardnessOfBlocksToBreak(context);
|
||||
}
|
||||
}
|
||||
if (Blocks.SOUL_SAND.equals(srcDown)) {
|
||||
if (BlockStateInterface.get(src).getBlock().equals(Blocks.SOUL_SAND)) {
|
||||
return COST_INF; // can't sneak and backplace against soul sand =/
|
||||
}
|
||||
WC = WC * SNEAK_ONE_BLOCK_COST / WALK_ONE_BLOCK_COST;//since we are placing, we are sneaking
|
||||
return WC + context.placeBlockCost() + getTotalHardnessOfBlocksToBreak(context);
|
||||
}
|
||||
return COST_INF;
|
||||
// Out.log("Can't walk on " + Baritone.get(positionsToPlace[0]).getBlock());
|
||||
//Out.log("Can't walk on " + Baritone.get(positionsToPlace[0]).getBlock());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,72 +127,46 @@ public class MovementTraverse extends Movement {
|
||||
super.updateState(state);
|
||||
switch (state.getStatus()) {
|
||||
case WAITING:
|
||||
state.setStatus(MovementState.MovementStatus.RUNNING);
|
||||
case RUNNING:
|
||||
break;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
||||
Block fd = BlockStateInterface.get(src.down()).getBlock();
|
||||
boolean ladder = fd instanceof BlockLadder || fd instanceof BlockVine;
|
||||
IBlockState pb0 = BlockStateInterface.get(positionsToBreak[0]);
|
||||
IBlockState pb1 = BlockStateInterface.get(positionsToBreak[1]);
|
||||
|
||||
boolean door = pb0.getBlock() instanceof BlockDoor || pb1.getBlock() instanceof BlockDoor;
|
||||
boolean door = BlockStateInterface.get(src).getBlock() instanceof BlockDoor || pb0.getBlock() instanceof BlockDoor || pb1.getBlock() instanceof BlockDoor;
|
||||
if (door) {
|
||||
boolean isDoorActuallyBlockingUs = false;
|
||||
if (pb0.getBlock() instanceof BlockDoor && !MovementHelper.isDoorPassable(src, dest)) {
|
||||
Block srcBlock = BlockStateInterface.get(src).getBlock();
|
||||
if (srcBlock instanceof BlockDoor && !MovementHelper.isDoorPassable(src, dest)) {
|
||||
isDoorActuallyBlockingUs = true;
|
||||
} else if (pb1.getBlock() instanceof BlockDoor && !MovementHelper.isDoorPassable(dest, src)) {
|
||||
isDoorActuallyBlockingUs = true;
|
||||
}
|
||||
if (isDoorActuallyBlockingUs) {
|
||||
if (!(Blocks.IRON_DOOR.equals(pb0.getBlock()) || Blocks.IRON_DOOR.equals(pb1.getBlock()))) {
|
||||
state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(playerHead(), Utils.calcCenterFromCoords(positionsToBreak[0], world())), true));
|
||||
state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true);
|
||||
return state;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pb0.getBlock() instanceof BlockFenceGate || pb1.getBlock() instanceof BlockFenceGate) {
|
||||
BlockPos blocked = null;
|
||||
if (!MovementHelper.isGatePassable(positionsToBreak[0], src.up())) {
|
||||
blocked = positionsToBreak[0];
|
||||
} else if (!MovementHelper.isGatePassable(positionsToBreak[1], src)) {
|
||||
blocked = positionsToBreak[1];
|
||||
}
|
||||
|
||||
if (blocked != null) {
|
||||
state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(playerHead(), Utils.calcCenterFromCoords(blocked, world())), true));
|
||||
state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(playerHead(), Utils.calcCenterFromCoords(positionsToBreak[0], world()))));
|
||||
state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true);
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
boolean isTheBridgeBlockThere = MovementHelper.canWalkOn(positionsToPlace[0]) || ladder;
|
||||
BlockPos whereAmI = playerFeet();
|
||||
if (whereAmI.getY() != dest.getY() && !ladder) {
|
||||
displayChatMessageRaw("Wrong Y coordinate");
|
||||
System.out.println("Wrong Y coordinate");
|
||||
if (whereAmI.getY() < dest.getY()) {
|
||||
state.setInput(InputOverrideHandler.Input.JUMP, true);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
if (isTheBridgeBlockThere) {
|
||||
if (playerFeet().equals(dest)) {
|
||||
state.setStatus(MovementState.MovementStatus.SUCCESS);
|
||||
return state;
|
||||
}
|
||||
if (wasTheBridgeBlockAlwaysThere && !BlockStateInterface.isLiquid(playerFeet())) {
|
||||
state.setInput(InputOverrideHandler.Input.SPRINT, true);
|
||||
}
|
||||
Block destDown = BlockStateInterface.get(dest.down()).getBlock();
|
||||
if (ladder && (destDown instanceof BlockVine || destDown instanceof BlockLadder)) {
|
||||
new MovementPillar(dest.down(), dest).updateState(state); // i'm sorry
|
||||
return state;
|
||||
player().setSprinting(true);
|
||||
}
|
||||
MovementHelper.moveTowards(state, positionsToBreak[0]);
|
||||
return state;
|
||||
@@ -211,23 +182,23 @@ public class MovementTraverse extends Movement {
|
||||
double faceX = (dest.getX() + against1.getX() + 1.0D) * 0.5D;
|
||||
double faceY = (dest.getY() + against1.getY()) * 0.5D;
|
||||
double faceZ = (dest.getZ() + against1.getZ() + 1.0D) * 0.5D;
|
||||
state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(playerHead(), new Vec3d(faceX, faceY, faceZ), playerRotations()), true));
|
||||
state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(playerHead(), new Vec3d(faceX, faceY, faceZ), playerRotations())));
|
||||
|
||||
EnumFacing side = Minecraft.getMinecraft().objectMouseOver.sideHit;
|
||||
if (Objects.equals(LookBehaviorUtils.getSelectedBlock().orElse(null), against1) && Minecraft.getMinecraft().player.isSneaking()) {
|
||||
if (LookBehaviorUtils.getSelectedBlock().get().offset(side).equals(positionsToPlace[0])) {
|
||||
return state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true);
|
||||
state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true);
|
||||
} else {
|
||||
// Out.gui("Wrong. " + side + " " + LookBehaviorUtils.getSelectedBlock().get().offset(side) + " " + positionsToPlace[0], Out.Mode.Debug);
|
||||
}
|
||||
}
|
||||
System.out.println("Trying to look at " + against1 + ", actually looking at" + LookBehaviorUtils.getSelectedBlock());
|
||||
return state.setInput(InputOverrideHandler.Input.CLICK_LEFT, true);
|
||||
return state;
|
||||
}
|
||||
}
|
||||
state.setInput(InputOverrideHandler.Input.SNEAK, true);
|
||||
if (whereAmI.equals(dest)) {
|
||||
// If we are in the block that we are trying to get to, we are sneaking over air and we need to place a block beneath us against the one we just walked off of
|
||||
// if we are in the block that we are trying to get to, we are sneaking over air and we need to place a block beneath us against the one we just walked off of
|
||||
// Out.log(from + " " + to + " " + faceX + "," + faceY + "," + faceZ + " " + whereAmI);
|
||||
if (!MovementHelper.throwaway(true)) {// get ready to place a throwaway block
|
||||
displayChatMessageRaw("bb pls get me some blocks. dirt or cobble");
|
||||
@@ -238,7 +209,7 @@ public class MovementTraverse extends Movement {
|
||||
double faceZ = (dest.getZ() + src.getZ() + 1.0D) * 0.5D;
|
||||
// faceX, faceY, faceZ is the middle of the face between from and to
|
||||
BlockPos goalLook = src.down(); // this is the block we were just standing on, and the one we want to place against
|
||||
state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(playerHead(), new Vec3d(faceX, faceY, faceZ), playerRotations()), true));
|
||||
state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(playerHead(), new Vec3d(faceX, faceY, faceZ), playerRotations())));
|
||||
|
||||
state.setInput(InputOverrideHandler.Input.MOVE_BACK, true);
|
||||
state.setInput(InputOverrideHandler.Input.SNEAK, true);
|
||||
@@ -15,10 +15,10 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.path;
|
||||
package baritone.bot.pathing.path;
|
||||
|
||||
import baritone.pathing.movement.Movement;
|
||||
import baritone.utils.pathing.BetterBlockPos;
|
||||
import baritone.bot.pathing.movement.Movement;
|
||||
import baritone.bot.utils.pathing.BetterBlockPos;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -15,14 +15,12 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.path;
|
||||
package baritone.bot.pathing.path;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.pathing.goals.Goal;
|
||||
import baritone.pathing.movement.Movement;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.Utils;
|
||||
import baritone.utils.pathing.BetterBlockPos;
|
||||
import baritone.bot.pathing.movement.Movement;
|
||||
import baritone.bot.utils.Helper;
|
||||
import baritone.bot.utils.Utils;
|
||||
import baritone.bot.utils.pathing.BetterBlockPos;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.util.Tuple;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
@@ -137,16 +135,4 @@ public interface IPath extends Helper {
|
||||
return this;
|
||||
}
|
||||
|
||||
default IPath staticCutoff(Goal destination) {
|
||||
if (length() < Baritone.settings().pathCutoffMinimumLength.get()) {
|
||||
return this;
|
||||
}
|
||||
if (destination == null || destination.isInGoal(getDest())) {
|
||||
return this;
|
||||
}
|
||||
double factor = Baritone.settings().pathCutoffFactor.get();
|
||||
int newLength = (int) (length() * factor);
|
||||
//displayChatMessageRaw("Static cutoff " + length() + " to " + newLength);
|
||||
return new CutoffPath(this, newLength);
|
||||
}
|
||||
}
|
||||
@@ -15,18 +15,15 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.path;
|
||||
package baritone.bot.pathing.path;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.event.events.TickEvent;
|
||||
import baritone.pathing.movement.ActionCosts;
|
||||
import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.movement.MovementState;
|
||||
import baritone.pathing.movement.movements.MovementDescend;
|
||||
import baritone.pathing.movement.movements.MovementDiagonal;
|
||||
import baritone.pathing.movement.movements.MovementTraverse;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.bot.Baritone;
|
||||
import baritone.bot.event.events.TickEvent;
|
||||
import baritone.bot.pathing.movement.ActionCosts;
|
||||
import baritone.bot.pathing.movement.Movement;
|
||||
import baritone.bot.pathing.movement.MovementState;
|
||||
import baritone.bot.utils.BlockStateInterface;
|
||||
import baritone.bot.utils.Helper;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.Tuple;
|
||||
@@ -36,7 +33,7 @@ import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static baritone.pathing.movement.MovementState.MovementStatus.*;
|
||||
import static baritone.bot.pathing.movement.MovementState.MovementStatus.*;
|
||||
|
||||
/**
|
||||
* Behavior to execute a precomputed path. Does not (yet) deal with path segmentation or stitching
|
||||
@@ -88,16 +85,12 @@ public class PathExecutor implements Helper {
|
||||
return true;
|
||||
}
|
||||
if (!whereShouldIBe.equals(whereAmI)) {
|
||||
//System.out.println("Should be at " + whereShouldIBe + " actually am at " + whereAmI);
|
||||
System.out.println("Should be at " + whereShouldIBe + " actually am at " + whereAmI);
|
||||
if (!Blocks.AIR.equals(BlockStateInterface.getBlock(whereAmI.down()))) {//do not skip if standing on air, because our position isn't stable to skip
|
||||
for (int i = 0; i < pathPosition - 2 && i < path.length(); i++) {//this happens for example when you lag out and get teleported back a couple blocks
|
||||
if (whereAmI.equals(path.positions().get(i))) {
|
||||
displayChatMessageRaw("Skipping back " + (pathPosition - i) + " steps, to " + i);
|
||||
int previousPos = pathPosition;
|
||||
pathPosition = Math.max(i - 1, 0); // previous step might not actually be done
|
||||
for (int j = pathPosition; j <= previousPos; j++) {
|
||||
path.movements().get(j).reset();
|
||||
}
|
||||
Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys();
|
||||
return false;
|
||||
}
|
||||
@@ -107,7 +100,6 @@ public class PathExecutor implements Helper {
|
||||
if (i - pathPosition > 2) {
|
||||
displayChatMessageRaw("Skipping forward " + (i - pathPosition) + " steps, to " + i);
|
||||
}
|
||||
System.out.println("Double skip sundae");
|
||||
pathPosition = i - 1;
|
||||
Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys();
|
||||
return false;
|
||||
@@ -214,15 +206,6 @@ public class PathExecutor implements Helper {
|
||||
if (costEstimateIndex == null || costEstimateIndex != pathPosition) {
|
||||
costEstimateIndex = pathPosition;
|
||||
currentMovementInitialCostEstimate = currentCost; // do this only once, when the movement starts
|
||||
for (int i = 1; i < Baritone.settings().costVerificationLookahead.get() && pathPosition + i < path.length() - 1; i++) {
|
||||
if (path.movements().get(pathPosition + i).recalculateCost() >= ActionCosts.COST_INF) {
|
||||
displayChatMessageRaw("Something has changed in the world and a future movement has become impossible. Cancelling.");
|
||||
pathPosition = path.length() + 3;
|
||||
failed = true;
|
||||
Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
MovementState.MovementStatus movementStatus = movement.update();
|
||||
if (movementStatus == UNREACHABLE || movementStatus == FAILED) {
|
||||
@@ -233,21 +216,20 @@ public class PathExecutor implements Helper {
|
||||
return true;
|
||||
}
|
||||
if (movementStatus == SUCCESS) {
|
||||
//System.out.println("Movement done, next path");
|
||||
System.out.println("Movement done, next path");
|
||||
pathPosition++;
|
||||
ticksOnCurrent = 0;
|
||||
Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys();
|
||||
onTick(event);
|
||||
return true;
|
||||
} else {
|
||||
sprintIfRequested();
|
||||
ticksOnCurrent++;
|
||||
if (ticksOnCurrent > currentMovementInitialCostEstimate + Baritone.settings().movementTimeoutTicks.get()) {
|
||||
if (ticksOnCurrent > currentMovementInitialCostEstimate + 100) {
|
||||
// only fail if the total time has exceeded the initial estimate
|
||||
// as you break the blocks required, the remaining cost goes down, to the point where
|
||||
// ticksOnCurrent is greater than recalculateCost + 100
|
||||
// ticksOnCurrent is greater than recalculateCost + 1000
|
||||
// this is why we cache cost at the beginning, and don't recalculate for this comparison every tick
|
||||
displayChatMessageRaw("This movement has taken too long (" + ticksOnCurrent + " ticks, expected " + currentMovementInitialCostEstimate + "). Cancelling.");
|
||||
displayChatMessageRaw("This movement has taken too long (" + ticksOnCurrent + " ticks, expected " + movement.getCost(null) + "). Cancelling.");
|
||||
movement.cancel();
|
||||
Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys();
|
||||
pathPosition = path.length() + 3;
|
||||
@@ -258,59 +240,6 @@ public class PathExecutor implements Helper {
|
||||
return false; // movement is in progress
|
||||
}
|
||||
|
||||
private void sprintIfRequested() {
|
||||
if (!Baritone.settings().allowSprint.get()) {
|
||||
player().setSprinting(false);
|
||||
return;
|
||||
}
|
||||
if (Baritone.INSTANCE.getInputOverrideHandler().isInputForcedDown(mc.gameSettings.keyBindSprint)) {
|
||||
if (!player().isSprinting()) {
|
||||
player().setSprinting(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
Movement movement = path.movements().get(pathPosition);
|
||||
if (movement instanceof MovementDescend && pathPosition < path.length() - 2) {
|
||||
Movement next = path.movements().get(pathPosition + 1);
|
||||
if (next instanceof MovementDescend) {
|
||||
if (next.getDirection().equals(movement.getDirection())) {
|
||||
if (playerFeet().equals(movement.getDest())) {
|
||||
pathPosition++;
|
||||
Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys();
|
||||
}
|
||||
if (!player().isSprinting()) {
|
||||
player().setSprinting(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (next instanceof MovementTraverse) {
|
||||
if (next.getDirection().down().equals(movement.getDirection())) {
|
||||
if (playerFeet().equals(movement.getDest())) {
|
||||
pathPosition++;
|
||||
Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys();
|
||||
}
|
||||
if (!player().isSprinting()) {
|
||||
player().setSprinting(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (next instanceof MovementDiagonal && Baritone.settings().allowOvershootDiagonalDescend.get()) {
|
||||
if (playerFeet().equals(movement.getDest())) {
|
||||
pathPosition++;
|
||||
Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys();
|
||||
}
|
||||
if (!player().isSprinting()) {
|
||||
player().setSprinting(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
//displayChatMessageRaw("Turning off sprinting " + movement + " " + next + " " + movement.getDirection() + " " + next.getDirection().down() + " " + next.getDirection().down().equals(movement.getDirection()));
|
||||
}
|
||||
player().setSprinting(false);
|
||||
}
|
||||
|
||||
public int getPosition() {
|
||||
return pathPosition;
|
||||
}
|
||||
@@ -15,11 +15,12 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.utils;
|
||||
package baritone.bot.utils;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.chunk.WorldData;
|
||||
import baritone.chunk.WorldProvider;
|
||||
import baritone.bot.Baritone;
|
||||
import baritone.bot.chunk.CachedWorld;
|
||||
import baritone.bot.chunk.CachedWorldProvider;
|
||||
import baritone.bot.utils.pathing.PathingBlockType;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockFalling;
|
||||
import net.minecraft.block.BlockLiquid;
|
||||
@@ -30,26 +31,34 @@ import net.minecraft.world.chunk.Chunk;
|
||||
|
||||
public class BlockStateInterface implements Helper {
|
||||
|
||||
public static IBlockState get(BlockPos pos) { // wrappers for chunk caching capability
|
||||
public static IBlockState get(BlockPos pos) { // wrappers for future chunk caching capability
|
||||
|
||||
// Invalid vertical position
|
||||
if (pos.getY() < 0 || pos.getY() >= 256)
|
||||
return Blocks.AIR.getDefaultState();
|
||||
|
||||
if (!Baritone.settings().pathThroughCachedOnly.get()) {
|
||||
Chunk chunk = mc.world.getChunk(pos);
|
||||
if (chunk.isLoaded()) {
|
||||
return chunk.getBlockState(pos);
|
||||
Chunk chunk = mc.world.getChunk(pos);
|
||||
if (chunk.isLoaded()) {
|
||||
return chunk.getBlockState(pos);
|
||||
}
|
||||
if (Baritone.settings().chuckCaching.get()) {
|
||||
CachedWorld world = CachedWorldProvider.INSTANCE.getCurrentWorld();
|
||||
if (world != null) {
|
||||
PathingBlockType type = world.getBlockType(pos);
|
||||
if (type != null) {
|
||||
switch (type) {
|
||||
case AIR:
|
||||
return Blocks.AIR.getDefaultState();
|
||||
case WATER:
|
||||
return Blocks.WATER.getDefaultState();
|
||||
case AVOID:
|
||||
return Blocks.LAVA.getDefaultState();
|
||||
case SOLID:
|
||||
return Blocks.OBSIDIAN.getDefaultState();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
WorldData world = WorldProvider.INSTANCE.getCurrentWorld();
|
||||
if (world != null) {
|
||||
IBlockState type = world.cache.getBlock(pos);
|
||||
if (type != null) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return Blocks.AIR.getDefaultState();
|
||||
}
|
||||
115
src/main/java/baritone/bot/utils/ExampleBaritoneControl.java
Normal file
115
src/main/java/baritone/bot/utils/ExampleBaritoneControl.java
Normal file
@@ -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 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.utils;
|
||||
|
||||
import baritone.bot.Baritone;
|
||||
import baritone.bot.Settings;
|
||||
import baritone.bot.behavior.Behavior;
|
||||
import baritone.bot.behavior.impl.PathingBehavior;
|
||||
import baritone.bot.event.events.ChatEvent;
|
||||
import baritone.bot.pathing.goals.Goal;
|
||||
import baritone.bot.pathing.goals.GoalBlock;
|
||||
import baritone.bot.pathing.goals.GoalXZ;
|
||||
import baritone.bot.pathing.goals.GoalYLevel;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ExampleBaritoneControl extends Behavior {
|
||||
public static ExampleBaritoneControl INSTANCE = new ExampleBaritoneControl();
|
||||
|
||||
private ExampleBaritoneControl() {
|
||||
|
||||
}
|
||||
|
||||
public void initAndRegister() {
|
||||
Baritone.INSTANCE.registerBehavior(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSendChatMessage(ChatEvent event) {
|
||||
if (!Baritone.settings().chatControl.get()) {
|
||||
return;
|
||||
}
|
||||
String msg = event.getMessage();
|
||||
if (msg.toLowerCase().startsWith("goal")) {
|
||||
event.cancel();
|
||||
String[] params = msg.toLowerCase().substring(4).trim().split(" ");
|
||||
if (params[0].equals("")) {
|
||||
params = new String[]{};
|
||||
}
|
||||
Goal goal;
|
||||
try {
|
||||
switch (params.length) {
|
||||
case 0:
|
||||
goal = new GoalBlock(playerFeet());
|
||||
break;
|
||||
case 1:
|
||||
if (params[0].equals("clear") || params[0].equals("none")) {
|
||||
goal = null;
|
||||
} else {
|
||||
goal = new GoalYLevel(Integer.parseInt(params[0]));
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
goal = new GoalXZ(Integer.parseInt(params[0]), Integer.parseInt(params[1]));
|
||||
break;
|
||||
case 3:
|
||||
goal = new GoalBlock(new BlockPos(Integer.parseInt(params[0]), Integer.parseInt(params[1]), Integer.parseInt(params[2])));
|
||||
break;
|
||||
default:
|
||||
displayChatMessageRaw("unable to understand lol");
|
||||
return;
|
||||
}
|
||||
} catch (NumberFormatException ex) {
|
||||
displayChatMessageRaw("unable to parse integer " + ex);
|
||||
return;
|
||||
}
|
||||
PathingBehavior.INSTANCE.setGoal(goal);
|
||||
displayChatMessageRaw("Goal: " + goal);
|
||||
return;
|
||||
}
|
||||
if (msg.equals("path")) {
|
||||
PathingBehavior.INSTANCE.path();
|
||||
event.cancel();
|
||||
return;
|
||||
}
|
||||
if (msg.toLowerCase().equals("cancel")) {
|
||||
PathingBehavior.INSTANCE.cancel();
|
||||
event.cancel();
|
||||
displayChatMessageRaw("ok canceled");
|
||||
return;
|
||||
}
|
||||
if (msg.toLowerCase().startsWith("thisway")) {
|
||||
Goal goal = GoalXZ.fromDirection(playerFeetAsVec(), player().rotationYaw, Double.parseDouble(msg.substring(7).trim()));
|
||||
PathingBehavior.INSTANCE.setGoal(goal);
|
||||
displayChatMessageRaw("Goal: " + goal);
|
||||
event.cancel();
|
||||
return;
|
||||
}
|
||||
List<Settings.Setting<Boolean>> toggleable = Baritone.settings().getByValueType(Boolean.class);
|
||||
for (Settings.Setting<Boolean> setting : toggleable) {
|
||||
if (msg.toLowerCase().equals(setting.getName().toLowerCase())) {
|
||||
setting.value ^= true;
|
||||
event.cancel();
|
||||
displayChatMessageRaw("Toggled " + setting.getName() + " to " + setting.value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
56
src/main/java/baritone/bot/utils/GZIPUtils.java
Normal file
56
src/main/java/baritone/bot/utils/GZIPUtils.java
Normal file
@@ -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 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.utils;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/3/2018 10:18 PM
|
||||
*/
|
||||
public final class GZIPUtils {
|
||||
|
||||
private GZIPUtils() {
|
||||
}
|
||||
|
||||
public static byte[] compress(byte[] in) throws IOException {
|
||||
ByteArrayOutputStream byteStream = new ByteArrayOutputStream(in.length);
|
||||
|
||||
try (GZIPOutputStream gzipStream = new GZIPOutputStream(byteStream)) {
|
||||
gzipStream.write(in);
|
||||
}
|
||||
return byteStream.toByteArray();
|
||||
}
|
||||
|
||||
public static byte[] decompress(InputStream in) throws IOException {
|
||||
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
|
||||
|
||||
try (GZIPInputStream gzipStream = new GZIPInputStream(in)) {
|
||||
byte[] buffer = new byte[1024];
|
||||
int len;
|
||||
while ((len = gzipStream.read(buffer)) > 0) {
|
||||
outStream.write(buffer, 0, len);
|
||||
}
|
||||
}
|
||||
return outStream.toByteArray();
|
||||
}
|
||||
}
|
||||
@@ -15,17 +15,21 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.utils;
|
||||
package baritone.bot.utils;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.bot.Baritone;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.client.gui.GuiNewChat;
|
||||
import net.minecraft.client.gui.GuiUtilRenderComponents;
|
||||
import net.minecraft.client.multiplayer.WorldClient;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraft.util.text.TextComponentString;
|
||||
import net.minecraft.util.text.TextFormatting;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
@@ -33,8 +37,6 @@ import net.minecraft.util.text.TextFormatting;
|
||||
*/
|
||||
public interface Helper {
|
||||
|
||||
ITextComponent MESSAGE_PREFIX = new TextComponentString("§5[§dBaritone§5]§7");
|
||||
|
||||
Minecraft mc = Minecraft.getMinecraft();
|
||||
|
||||
default EntityPlayerSP player() {
|
||||
@@ -71,10 +73,14 @@ public interface Helper {
|
||||
System.out.println(message);
|
||||
return;
|
||||
}
|
||||
GuiNewChat gui = mc.ingameGUI.getChatGUI();
|
||||
int normalMaxWidth = MathHelper.floor((float) gui.getChatWidth() / gui.getChatScale());
|
||||
int widthWithStyleFormat = normalMaxWidth - 2;
|
||||
List<ITextComponent> list = GuiUtilRenderComponents.splitText(new TextComponentString("§5[§dBaritone§5]§7 " + message), widthWithStyleFormat,
|
||||
this.mc.fontRenderer, false, true);
|
||||
for (ITextComponent component : list) {
|
||||
|
||||
ITextComponent component = MESSAGE_PREFIX.createCopy();
|
||||
component.getStyle().setColor(TextFormatting.GRAY);
|
||||
component.appendSibling(new TextComponentString(" " + message));
|
||||
mc.ingameGUI.getChatGUI().printChatMessage(component);
|
||||
gui.printChatMessage(new TextComponentString("§7" + component.getUnformattedText()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.utils;
|
||||
package baritone.bot.utils;
|
||||
|
||||
import net.minecraft.client.settings.KeyBinding;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
@@ -84,6 +84,8 @@ public final class InputOverrideHandler implements Helper {
|
||||
* @param forced Whether or not the state is being forced
|
||||
*/
|
||||
public final void setInputForceState(Input input, boolean forced) {
|
||||
if (!forced)
|
||||
System.out.println(input);
|
||||
inputForceStateMap.put(input.getKeyBinding(), forced);
|
||||
}
|
||||
|
||||
@@ -15,14 +15,14 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.utils;
|
||||
package baritone.bot.utils;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.pathing.goals.Goal;
|
||||
import baritone.pathing.goals.GoalBlock;
|
||||
import baritone.pathing.goals.GoalXZ;
|
||||
import baritone.pathing.path.IPath;
|
||||
import baritone.utils.pathing.BetterBlockPos;
|
||||
import baritone.bot.Baritone;
|
||||
import baritone.bot.pathing.goals.Goal;
|
||||
import baritone.bot.pathing.goals.GoalBlock;
|
||||
import baritone.bot.pathing.goals.GoalXZ;
|
||||
import baritone.bot.pathing.path.IPath;
|
||||
import baritone.bot.utils.pathing.BetterBlockPos;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
@@ -57,7 +57,7 @@ public final class PathRenderer implements Helper {
|
||||
GlStateManager.enableBlend();
|
||||
GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
|
||||
GlStateManager.color(color.getColorComponents(null)[0], color.getColorComponents(null)[1], color.getColorComponents(null)[2], 0.4F);
|
||||
GlStateManager.glLineWidth(Baritone.settings().pathRenderLineWidthPixels.get());
|
||||
GlStateManager.glLineWidth(Baritone.settings().pathRenderLineWidth.get());
|
||||
GlStateManager.disableTexture2D();
|
||||
GlStateManager.depthMask(false);
|
||||
List<BetterBlockPos> positions = path.positions();
|
||||
@@ -120,7 +120,7 @@ public final class PathRenderer implements Helper {
|
||||
GlStateManager.enableBlend();
|
||||
GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0);
|
||||
GlStateManager.color(color.getColorComponents(null)[0], color.getColorComponents(null)[1], color.getColorComponents(null)[2], 0.4F);
|
||||
GlStateManager.glLineWidth(Baritone.settings().pathRenderLineWidthPixels.get());
|
||||
GlStateManager.glLineWidth(Baritone.settings().pathRenderLineWidth.get());
|
||||
GlStateManager.disableTexture2D();
|
||||
GlStateManager.depthMask(false);
|
||||
float expand = 0.002F;
|
||||
@@ -170,6 +170,13 @@ public final class PathRenderer implements Helper {
|
||||
}
|
||||
|
||||
public static void drawLitDankGoalBox(EntityPlayer player, Goal goal, float partialTicks, Color color) {
|
||||
GlStateManager.enableBlend();
|
||||
GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0);
|
||||
GlStateManager.color(color.getColorComponents(null)[0], color.getColorComponents(null)[1], color.getColorComponents(null)[2], 0.6F);
|
||||
GlStateManager.glLineWidth(Baritone.settings().goalRenderLineWidth.get());
|
||||
GlStateManager.disableTexture2D();
|
||||
GlStateManager.depthMask(false);
|
||||
float expand = 0.002F;
|
||||
double renderPosX = player.lastTickPosX + (player.posX - player.lastTickPosX) * (double) partialTicks;
|
||||
double renderPosY = player.lastTickPosY + (player.posY - player.lastTickPosY) * (double) partialTicks;
|
||||
double renderPosZ = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * (double) partialTicks;
|
||||
@@ -210,13 +217,6 @@ public final class PathRenderer implements Helper {
|
||||
return;
|
||||
}
|
||||
|
||||
GlStateManager.enableBlend();
|
||||
GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0);
|
||||
GlStateManager.color(color.getColorComponents(null)[0], color.getColorComponents(null)[1], color.getColorComponents(null)[2], 0.6F);
|
||||
GlStateManager.glLineWidth(Baritone.settings().goalRenderLineWidthPixels.get());
|
||||
GlStateManager.disableTexture2D();
|
||||
GlStateManager.depthMask(false);
|
||||
|
||||
if (y1 != 0) {
|
||||
BUFFER.begin(GL_LINE_STRIP, DefaultVertexFormats.POSITION);
|
||||
BUFFER.pos(minX, y1, minZ).endVertex();
|
||||
@@ -15,7 +15,7 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.utils;
|
||||
package baritone.bot.utils;
|
||||
|
||||
import net.minecraft.util.Tuple;
|
||||
|
||||
@@ -15,11 +15,8 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.utils;
|
||||
package baritone.bot.utils;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.event.events.ItemSlotEvent;
|
||||
import baritone.event.listener.AbstractGameEventListener;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
@@ -39,19 +36,10 @@ import java.util.Map;
|
||||
/**
|
||||
* A cached list of the best tools on the hotbar for any block
|
||||
*
|
||||
* @author avecowa, Brady
|
||||
* @author avecowa
|
||||
*/
|
||||
public class ToolSet implements Helper {
|
||||
|
||||
/**
|
||||
* Instance of the internal event listener used to hook into Baritone's event bus
|
||||
*/
|
||||
private static final InternalEventListener INTERNAL_EVENT_LISTENER = new InternalEventListener();
|
||||
|
||||
static {
|
||||
Baritone.INSTANCE.getGameEventHandler().registerEventListener(INTERNAL_EVENT_LISTENER);
|
||||
}
|
||||
|
||||
/**
|
||||
* A list of tools on the hotbar that should be considered.
|
||||
* Note that if there are no tools on the hotbar this list will still have one (null) entry.
|
||||
@@ -69,13 +57,7 @@ public class ToolSet implements Helper {
|
||||
* The values in this map are *not* hotbar slots indexes, they need to be looked up in slots
|
||||
* in order to be converted into hotbar slots.
|
||||
*/
|
||||
private Map<Block, Byte> slotCache = new HashMap<>();
|
||||
|
||||
/**
|
||||
* A cache mapping a {@link IBlockState} to how long it will take to break
|
||||
* with this toolset, given the optimum tool is used.
|
||||
*/
|
||||
private Map<IBlockState, Double> breakStrengthCache = new HashMap<>();
|
||||
private Map<Block, Byte> cache = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Create a toolset from the current player's inventory (but don't calculate any hardness values just yet)
|
||||
@@ -102,7 +84,7 @@ public class ToolSet implements Helper {
|
||||
* @return get which tool on the hotbar is best for mining it
|
||||
*/
|
||||
public Item getBestTool(IBlockState state) {
|
||||
return tools.get(slotCache.computeIfAbsent(state.getBlock(), block -> getBestToolIndex(state)));
|
||||
return tools.get(cache.computeIfAbsent(state.getBlock(), block -> getBestToolIndex(state)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -135,7 +117,7 @@ public class ToolSet implements Helper {
|
||||
* @return a byte indicating which hotbar slot worked best
|
||||
*/
|
||||
public byte getBestSlot(IBlockState state) {
|
||||
return slots.get(slotCache.computeIfAbsent(state.getBlock(), block -> getBestToolIndex(state)));
|
||||
return slots.get(cache.computeIfAbsent(state.getBlock(), block -> getBestToolIndex(state)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,44 +128,21 @@ public class ToolSet implements Helper {
|
||||
* @return how long it would take in ticks
|
||||
*/
|
||||
public double getStrVsBlock(IBlockState state, BlockPos pos) {
|
||||
return this.breakStrengthCache.computeIfAbsent(state, s -> calculateStrVsBlock(s, pos));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates how long would it take to mine the specified block given the best tool
|
||||
* in this toolset is used.
|
||||
*
|
||||
* @param state the blockstate to be mined
|
||||
* @param pos the blockpos to be mined
|
||||
* @return how long it would take in ticks
|
||||
*/
|
||||
private double calculateStrVsBlock(IBlockState state, BlockPos pos) {
|
||||
// Calculate the slot with the best item
|
||||
byte slot = this.getBestSlot(state);
|
||||
|
||||
INTERNAL_EVENT_LISTENER.setOverrideSlot(slot);
|
||||
// Save the old current slot
|
||||
int oldSlot = player().inventory.currentItem;
|
||||
|
||||
// Set the best slot
|
||||
player().inventory.currentItem = slot;
|
||||
|
||||
// Calculate the relative hardness of the block to the player
|
||||
float hardness = state.getPlayerRelativeBlockHardness(player(), world(), pos);
|
||||
|
||||
// Restore the old slot
|
||||
INTERNAL_EVENT_LISTENER.setOverrideSlot(-1);
|
||||
player().inventory.currentItem = oldSlot;
|
||||
|
||||
return hardness;
|
||||
}
|
||||
|
||||
private static final class InternalEventListener implements AbstractGameEventListener {
|
||||
|
||||
private int overrideSlot;
|
||||
|
||||
@Override
|
||||
public void onQueryItemSlotForBlocks(ItemSlotEvent event) {
|
||||
if (this.overrideSlot >= 0)
|
||||
event.setSlot(this.overrideSlot);
|
||||
}
|
||||
|
||||
final void setOverrideSlot(int overrideSlot) {
|
||||
this.overrideSlot = overrideSlot;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.utils;
|
||||
package baritone.bot.utils;
|
||||
|
||||
import net.minecraft.block.BlockFire;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
@@ -15,7 +15,7 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.utils.pathing;
|
||||
package baritone.bot.utils.pathing;
|
||||
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
@@ -55,17 +55,13 @@ public class BetterBlockPos extends BlockPos {
|
||||
this.hashCode = hash;
|
||||
}
|
||||
|
||||
public BetterBlockPos(BlockPos pos) {
|
||||
this(pos.getX(), pos.getY(), pos.getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
public int hashCode() {
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean equals(Object o) {
|
||||
public boolean equals(Object o) {
|
||||
if (o == null) {
|
||||
return false;
|
||||
}
|
||||
@@ -15,10 +15,9 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.utils.pathing;
|
||||
package baritone.bot.utils.pathing;
|
||||
|
||||
import baritone.utils.Helper;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import baritone.bot.utils.Helper;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
/**
|
||||
@@ -27,9 +26,9 @@ import net.minecraft.util.math.BlockPos;
|
||||
*/
|
||||
public interface IBlockTypeAccess extends Helper {
|
||||
|
||||
IBlockState getBlock(int x, int y, int z);
|
||||
PathingBlockType getBlockType(int x, int y, int z);
|
||||
|
||||
default IBlockState getBlock(BlockPos pos) {
|
||||
return getBlock(pos.getX(), pos.getY(), pos.getZ());
|
||||
default PathingBlockType getBlockType(BlockPos pos) {
|
||||
return getBlockType(pos.getX(), pos.getY(), pos.getZ());
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.utils.pathing;
|
||||
package baritone.bot.utils.pathing;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
@@ -1,201 +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 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.chunk;
|
||||
|
||||
import baritone.utils.pathing.IBlockTypeAccess;
|
||||
import baritone.utils.pathing.PathingBlockType;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/3/2018 1:04 AM
|
||||
*/
|
||||
public final class CachedChunk implements IBlockTypeAccess {
|
||||
|
||||
public static final Set<Block> BLOCKS_TO_KEEP_TRACK_OF = Collections.unmodifiableSet(new HashSet<Block>() {{
|
||||
add(Blocks.DIAMOND_ORE);
|
||||
add(Blocks.DIAMOND_BLOCK);
|
||||
//add(Blocks.COAL_ORE);
|
||||
add(Blocks.COAL_BLOCK);
|
||||
//add(Blocks.IRON_ORE);
|
||||
add(Blocks.IRON_BLOCK);
|
||||
//add(Blocks.GOLD_ORE);
|
||||
add(Blocks.GOLD_BLOCK);
|
||||
add(Blocks.EMERALD_ORE);
|
||||
add(Blocks.EMERALD_BLOCK);
|
||||
|
||||
add(Blocks.ENDER_CHEST);
|
||||
add(Blocks.FURNACE);
|
||||
add(Blocks.CHEST);
|
||||
add(Blocks.END_PORTAL);
|
||||
add(Blocks.END_PORTAL_FRAME);
|
||||
add(Blocks.MOB_SPAWNER);
|
||||
// TODO add all shulker colors
|
||||
add(Blocks.PORTAL);
|
||||
add(Blocks.HOPPER);
|
||||
add(Blocks.BEACON);
|
||||
add(Blocks.BREWING_STAND);
|
||||
add(Blocks.SKULL);
|
||||
add(Blocks.ENCHANTING_TABLE);
|
||||
add(Blocks.ANVIL);
|
||||
add(Blocks.LIT_FURNACE);
|
||||
add(Blocks.BED);
|
||||
add(Blocks.DRAGON_EGG);
|
||||
add(Blocks.JUKEBOX);
|
||||
add(Blocks.END_GATEWAY);
|
||||
}});
|
||||
|
||||
/**
|
||||
* The size of the chunk data in bits. Equal to 16 KiB.
|
||||
* <p>
|
||||
* Chunks are 16x16x256, each block requires 2 bits.
|
||||
*/
|
||||
public static final int SIZE = 2 * 16 * 16 * 256;
|
||||
|
||||
/**
|
||||
* The size of the chunk data in bytes. Equal to 16 KiB.
|
||||
*/
|
||||
public static final int SIZE_IN_BYTES = SIZE / 8;
|
||||
|
||||
/**
|
||||
* The chunk x coordinate
|
||||
*/
|
||||
public final int x;
|
||||
|
||||
/**
|
||||
* The chunk z coordinate
|
||||
*/
|
||||
public final int z;
|
||||
|
||||
/**
|
||||
* The actual raw data of this packed chunk.
|
||||
* <p>
|
||||
* Each block is expressed as 2 bits giving a total of 16 KiB
|
||||
*/
|
||||
private final BitSet data;
|
||||
|
||||
/**
|
||||
* The block names of each surface level block for generating an overview
|
||||
*/
|
||||
private final String[] overview;
|
||||
|
||||
private final int[] heightMap;
|
||||
|
||||
private final Map<String, List<BlockPos>> specialBlockLocations;
|
||||
|
||||
CachedChunk(int x, int z, BitSet data, String[] overview, Map<String, List<BlockPos>> specialBlockLocations) {
|
||||
validateSize(data);
|
||||
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
this.data = data;
|
||||
this.overview = overview;
|
||||
this.heightMap = new int[256];
|
||||
this.specialBlockLocations = specialBlockLocations;
|
||||
calculateHeightMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final IBlockState getBlock(int x, int y, int z) {
|
||||
int internalPos = z << 4 | x;
|
||||
if (heightMap[internalPos] == y) {
|
||||
// we have this exact block, it's a surface block
|
||||
IBlockState state = ChunkPacker.stringToBlock(overview[internalPos]).getDefaultState();
|
||||
//System.out.println("Saying that " + x + "," + y + "," + z + " is " + state);
|
||||
return state;
|
||||
}
|
||||
PathingBlockType type = getType(x, y, z);
|
||||
return ChunkPacker.pathingTypeToBlock(type);
|
||||
}
|
||||
|
||||
private PathingBlockType getType(int x, int y, int z) {
|
||||
int index = getPositionIndex(x, y, z);
|
||||
return PathingBlockType.fromBits(data.get(index), data.get(index + 1));
|
||||
}
|
||||
|
||||
private void calculateHeightMap() {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
int index = z << 4 | x;
|
||||
heightMap[index] = 0;
|
||||
for (int y = 256; y >= 0; y--) {
|
||||
if (getType(x, y, z) != PathingBlockType.AIR) {
|
||||
heightMap[index] = y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final String[] getOverview() {
|
||||
return overview;
|
||||
}
|
||||
|
||||
public final Map<String, List<BlockPos>> getRelativeBlocks() {
|
||||
return specialBlockLocations;
|
||||
}
|
||||
|
||||
public final LinkedList<BlockPos> getAbsoluteBlocks(String blockType) {
|
||||
if (specialBlockLocations.get(blockType) == null) {
|
||||
return null;
|
||||
}
|
||||
LinkedList<BlockPos> res = new LinkedList<>();
|
||||
for (BlockPos pos : specialBlockLocations.get(blockType)) {
|
||||
res.add(new BlockPos(pos.getX() + x * 16, pos.getY(), pos.getZ() + z * 16));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the raw packed chunk data as a byte array
|
||||
*/
|
||||
public final byte[] toByteArray() {
|
||||
return this.data.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw bit index of the specified position
|
||||
*
|
||||
* @param x The x position
|
||||
* @param y The y position
|
||||
* @param z The z position
|
||||
* @return The bit index
|
||||
*/
|
||||
public static int getPositionIndex(int x, int y, int z) {
|
||||
return (x + (z << 4) + (y << 8)) * 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the size of an input {@link BitSet} containing the raw
|
||||
* packed chunk data. Sizes that exceed {@link CachedChunk#SIZE} are
|
||||
* considered invalid, and thus, an exception will be thrown.
|
||||
*
|
||||
* @param data The raw data
|
||||
* @throws IllegalArgumentException if the bitset size exceeds the maximum size
|
||||
*/
|
||||
private static void validateSize(BitSet data) {
|
||||
if (data.size() > SIZE)
|
||||
throw new IllegalArgumentException("BitSet of invalid length provided");
|
||||
}
|
||||
}
|
||||
@@ -1,289 +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 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.chunk;
|
||||
|
||||
import baritone.utils.pathing.IBlockTypeAccess;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.*;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/3/2018 9:35 PM
|
||||
*/
|
||||
public final class CachedRegion implements IBlockTypeAccess {
|
||||
private static final byte CHUNK_NOT_PRESENT = 0;
|
||||
private static final byte CHUNK_PRESENT = 1;
|
||||
|
||||
/**
|
||||
* Magic value to detect invalid cache files, or incompatible cache files saved in an old version of Baritone
|
||||
*/
|
||||
private static final int CACHED_REGION_MAGIC = 456022910;
|
||||
|
||||
/**
|
||||
* All of the chunks in this region: A 32x32 array of them.
|
||||
*/
|
||||
private final CachedChunk[][] chunks = new CachedChunk[32][32];
|
||||
|
||||
/**
|
||||
* The region x coordinate
|
||||
*/
|
||||
private final int x;
|
||||
|
||||
/**
|
||||
* The region z coordinate
|
||||
*/
|
||||
private final int z;
|
||||
|
||||
/**
|
||||
* Has this region been modified since its most recent load or save
|
||||
*/
|
||||
private boolean hasUnsavedChanges;
|
||||
|
||||
CachedRegion(int x, int z) {
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
this.hasUnsavedChanges = false;
|
||||
}
|
||||
|
||||
@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 null;
|
||||
}
|
||||
|
||||
public final LinkedList<BlockPos> getLocationsOf(String block) {
|
||||
LinkedList<BlockPos> res = new LinkedList<>();
|
||||
for (int chunkX = 0; chunkX < 32; chunkX++) {
|
||||
for (int chunkZ = 0; chunkZ < 32; chunkZ++) {
|
||||
if (chunks[chunkX][chunkZ] == null) {
|
||||
continue;
|
||||
}
|
||||
List<BlockPos> locs = chunks[chunkX][chunkZ].getAbsoluteBlocks(block);
|
||||
if (locs == null) {
|
||||
continue;
|
||||
}
|
||||
for (BlockPos pos : locs) {
|
||||
res.add(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
final synchronized void updateCachedChunk(int chunkX, int chunkZ, CachedChunk chunk) {
|
||||
this.chunks[chunkX][chunkZ] = chunk;
|
||||
hasUnsavedChanges = true;
|
||||
}
|
||||
|
||||
|
||||
public synchronized final void save(String directory) {
|
||||
if (!hasUnsavedChanges) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Path path = Paths.get(directory);
|
||||
if (!Files.exists(path))
|
||||
Files.createDirectories(path);
|
||||
|
||||
System.out.println("Saving region " + x + "," + z + " to disk " + path);
|
||||
Path regionFile = getRegionFile(path, this.x, this.z);
|
||||
if (!Files.exists(regionFile))
|
||||
Files.createFile(regionFile);
|
||||
try (
|
||||
FileOutputStream fileOut = new FileOutputStream(regionFile.toFile());
|
||||
GZIPOutputStream gzipOut = new GZIPOutputStream(fileOut);
|
||||
DataOutputStream out = new DataOutputStream(gzipOut);
|
||||
) {
|
||||
out.writeInt(CACHED_REGION_MAGIC);
|
||||
for (int z = 0; z < 32; z++) {
|
||||
for (int x = 0; x < 32; x++) {
|
||||
CachedChunk chunk = this.chunks[x][z];
|
||||
if (chunk == null) {
|
||||
out.write(CHUNK_NOT_PRESENT);
|
||||
} else {
|
||||
out.write(CHUNK_PRESENT);
|
||||
byte[] chunkBytes = chunk.toByteArray();
|
||||
out.write(chunkBytes);
|
||||
// Messy, but fills the empty 0s that should be trailing to fill up the space.
|
||||
out.write(new byte[CachedChunk.SIZE_IN_BYTES - chunkBytes.length]);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int z = 0; z < 32; z++) {
|
||||
for (int x = 0; x < 32; x++) {
|
||||
if (chunks[x][z] != null) {
|
||||
for (int i = 0; i < 256; i++) {
|
||||
out.writeUTF(chunks[x][z].getOverview()[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int z = 0; z < 32; z++) {
|
||||
for (int x = 0; x < 32; x++) {
|
||||
if (chunks[x][z] != null) {
|
||||
Map<String, List<BlockPos>> locs = chunks[x][z].getRelativeBlocks();
|
||||
out.writeShort(locs.entrySet().size());
|
||||
for (Map.Entry<String, List<BlockPos>> entry : locs.entrySet()) {
|
||||
out.writeUTF(entry.getKey());
|
||||
out.writeShort(entry.getValue().size());
|
||||
for (BlockPos pos : entry.getValue()) {
|
||||
out.writeByte((byte) (pos.getZ() << 4 | pos.getX()));
|
||||
out.writeByte((byte) (pos.getY()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
hasUnsavedChanges = false;
|
||||
System.out.println("Saved region successfully");
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void load(String directory) {
|
||||
try {
|
||||
Path path = Paths.get(directory);
|
||||
if (!Files.exists(path))
|
||||
Files.createDirectories(path);
|
||||
|
||||
Path regionFile = getRegionFile(path, this.x, this.z);
|
||||
if (!Files.exists(regionFile))
|
||||
return;
|
||||
|
||||
System.out.println("Loading region " + x + "," + z + " from disk " + path);
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
try (
|
||||
FileInputStream fileIn = new FileInputStream(regionFile.toFile());
|
||||
GZIPInputStream gzipIn = new GZIPInputStream(fileIn);
|
||||
DataInputStream in = new DataInputStream(gzipIn);
|
||||
) {
|
||||
int magic = in.readInt();
|
||||
if (magic != CACHED_REGION_MAGIC) {
|
||||
// in the future, if we change the format on disk
|
||||
// we can keep converters for the old format
|
||||
// by switching on the magic value, and either loading it normally, or loading through a converter.
|
||||
throw new IOException("Bad magic value " + magic);
|
||||
}
|
||||
CachedChunk[][] tmpCached = new CachedChunk[32][32];
|
||||
Map<String, List<BlockPos>>[][] location = new Map[32][32];
|
||||
for (int z = 0; z < 32; z++) {
|
||||
for (int x = 0; x < 32; x++) {
|
||||
int isChunkPresent = in.read();
|
||||
switch (isChunkPresent) {
|
||||
case CHUNK_PRESENT:
|
||||
byte[] bytes = new byte[CachedChunk.SIZE_IN_BYTES];
|
||||
in.readFully(bytes);
|
||||
location[x][z] = new HashMap<>();
|
||||
int regionX = this.x;
|
||||
int regionZ = this.z;
|
||||
int chunkX = x + 32 * regionX;
|
||||
int chunkZ = z + 32 * regionZ;
|
||||
tmpCached[x][z] = new CachedChunk(chunkX, chunkZ, BitSet.valueOf(bytes), new String[256], location[x][z]);
|
||||
break;
|
||||
case CHUNK_NOT_PRESENT:
|
||||
tmpCached[x][z] = null;
|
||||
break;
|
||||
default:
|
||||
throw new IOException("Malformed stream");
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int z = 0; z < 32; z++) {
|
||||
for (int x = 0; x < 32; x++) {
|
||||
if (tmpCached[x][z] != null) {
|
||||
for (int i = 0; i < 256; i++) {
|
||||
tmpCached[x][z].getOverview()[i] = in.readUTF();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int z = 0; z < 32; z++) {
|
||||
for (int x = 0; x < 32; x++) {
|
||||
if (tmpCached[x][z] != null) {
|
||||
// 16 * 16 * 256 = 65536 so a short is enough
|
||||
// ^ haha jokes on leijurv, java doesn't have unsigned types so that isn't correct
|
||||
// also why would you have more than 32767 special blocks in a chunk
|
||||
// haha double jokes on you now it works for 65535 not just 32767
|
||||
int numSpecialBlockTypes = in.readShort() & 0xffff;
|
||||
for (int i = 0; i < numSpecialBlockTypes; i++) {
|
||||
String blockName = in.readUTF();
|
||||
List<BlockPos> locs = new ArrayList<>();
|
||||
location[x][z].put(blockName, locs);
|
||||
int numLocations = in.readShort() & 0xffff;
|
||||
if (numLocations == 0) {
|
||||
// an entire chunk full of air can happen in the end
|
||||
numLocations = 65536;
|
||||
}
|
||||
for (int j = 0; j < numLocations; j++) {
|
||||
byte xz = in.readByte();
|
||||
int X = xz & 0x0f;
|
||||
int Z = (xz >>> 4) & 0x0f;
|
||||
int Y = in.readByte() & 0xff;
|
||||
locs.add(new BlockPos(X, Y, Z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// only if the entire file was uncorrupted do we actually set the chunks
|
||||
for (int x = 0; x < 32; x++) {
|
||||
for (int z = 0; z < 32; z++) {
|
||||
this.chunks[x][z] = tmpCached[x][z];
|
||||
}
|
||||
}
|
||||
}
|
||||
hasUnsavedChanges = false;
|
||||
long end = System.currentTimeMillis();
|
||||
System.out.println("Loaded region successfully in " + (end - start) + "ms");
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The region x coordinate
|
||||
*/
|
||||
public final int getX() {
|
||||
return this.x;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The region z coordinate
|
||||
*/
|
||||
public final int getZ() {
|
||||
return this.z;
|
||||
}
|
||||
|
||||
private static Path getRegionFile(Path cacheDir, int regionX, int regionZ) {
|
||||
return Paths.get(cacheDir.toString(), "r." + regionX + "." + regionZ + ".bcr");
|
||||
}
|
||||
}
|
||||
@@ -1,241 +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 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.chunk;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.utils.pathing.IBlockTypeAccess;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.LinkedList;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/4/2018 12:02 AM
|
||||
*/
|
||||
public final class CachedWorld implements IBlockTypeAccess {
|
||||
|
||||
/**
|
||||
* The maximum number of regions in any direction from (0,0)
|
||||
*/
|
||||
private static final int REGION_MAX = 58594;
|
||||
|
||||
/**
|
||||
* A map of all of the cached regions.
|
||||
*/
|
||||
private Long2ObjectMap<CachedRegion> cachedRegions = new Long2ObjectOpenHashMap<>();
|
||||
|
||||
/**
|
||||
* The directory that the cached region files are saved to
|
||||
*/
|
||||
private final String directory;
|
||||
|
||||
private final LinkedBlockingQueue<Chunk> toPack = new LinkedBlockingQueue<>();
|
||||
|
||||
CachedWorld(Path directory) {
|
||||
if (!Files.exists(directory)) {
|
||||
try {
|
||||
Files.createDirectories(directory);
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
this.directory = directory.toString();
|
||||
System.out.println("Cached world directory: " + directory);
|
||||
// Insert an invalid region element
|
||||
cachedRegions.put(0, null);
|
||||
new PackerThread().start();
|
||||
new Thread() {
|
||||
public void run() {
|
||||
try {
|
||||
while (true) {
|
||||
// since a region only saves if it's been modified since its last save
|
||||
// saving every 10 minutes means that once it's time to exit
|
||||
// we'll only have a couple regions to save
|
||||
save();
|
||||
Thread.sleep(600000);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
public final void queueForPacking(Chunk chunk) {
|
||||
try {
|
||||
toPack.put(chunk);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final IBlockState getBlock(int x, int y, int z) {
|
||||
// no point in doing getOrCreate region, if we don't have it we don't have it
|
||||
CachedRegion region = getRegion(x >> 9, z >> 9);
|
||||
if (region == null) {
|
||||
return null;
|
||||
}
|
||||
return region.getBlock(x & 511, y, z & 511);
|
||||
}
|
||||
|
||||
public final LinkedList<BlockPos> getLocationsOf(String block, int minimum, int maxRegionDistanceSq) {
|
||||
LinkedList<BlockPos> res = new LinkedList<>();
|
||||
int playerRegionX = playerFeet().getX() >> 9;
|
||||
int playerRegionZ = playerFeet().getZ() >> 9;
|
||||
|
||||
int searchRadius = 0;
|
||||
while (searchRadius <= maxRegionDistanceSq) {
|
||||
for (int xoff = -searchRadius; xoff <= searchRadius; xoff++) {
|
||||
for (int zoff = -searchRadius; zoff <= searchRadius; zoff++) {
|
||||
int distance = xoff * xoff + zoff * zoff;
|
||||
if (distance != searchRadius) {
|
||||
continue;
|
||||
}
|
||||
int regionX = xoff + playerRegionX;
|
||||
int regionZ = zoff + playerRegionZ;
|
||||
CachedRegion region = getOrCreateRegion(regionX, regionZ);
|
||||
if (region != null)
|
||||
for (BlockPos pos : region.getLocationsOf(block))
|
||||
res.add(pos);
|
||||
}
|
||||
}
|
||||
if (res.size() >= minimum) {
|
||||
return res;
|
||||
}
|
||||
searchRadius++;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private void updateCachedChunk(CachedChunk chunk) {
|
||||
CachedRegion region = getOrCreateRegion(chunk.x >> 5, chunk.z >> 5);
|
||||
region.updateCachedChunk(chunk.x & 31, chunk.z & 31, chunk);
|
||||
}
|
||||
|
||||
public final void save() {
|
||||
if (!Baritone.settings().chunkCaching.get()) {
|
||||
System.out.println("Not saving to disk; chunk caching is disabled.");
|
||||
return;
|
||||
}
|
||||
long start = System.currentTimeMillis();
|
||||
this.cachedRegions.values().forEach(region -> {
|
||||
if (region != null)
|
||||
region.save(this.directory);
|
||||
});
|
||||
long now = System.currentTimeMillis();
|
||||
System.out.println("World save took " + (now - start) + "ms");
|
||||
}
|
||||
|
||||
public final void reloadAllFromDisk() {
|
||||
long start = System.currentTimeMillis();
|
||||
this.cachedRegions.values().forEach(region -> {
|
||||
if (region != null)
|
||||
region.load(this.directory);
|
||||
});
|
||||
long now = System.currentTimeMillis();
|
||||
System.out.println("World load took " + (now - start) + "ms");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the region at the specified region coordinates
|
||||
*
|
||||
* @param regionX The region X coordinate
|
||||
* @param regionZ The region Z coordinate
|
||||
* @return The region located at the specified coordinates
|
||||
*/
|
||||
public final CachedRegion getRegion(int regionX, int regionZ) {
|
||||
return cachedRegions.get(getRegionID(regionX, regionZ));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the region at the specified region coordinates. If a
|
||||
* region is not found, then a new one is created.
|
||||
*
|
||||
* @param regionX The region X coordinate
|
||||
* @param regionZ The region Z coordinate
|
||||
* @return The region located at the specified coordinates
|
||||
*/
|
||||
private synchronized CachedRegion getOrCreateRegion(int regionX, int regionZ) {
|
||||
return cachedRegions.computeIfAbsent(getRegionID(regionX, regionZ), id -> {
|
||||
CachedRegion newRegion = new CachedRegion(regionX, regionZ);
|
||||
newRegion.load(this.directory);
|
||||
return newRegion;
|
||||
});
|
||||
}
|
||||
|
||||
public void forEachRegion(Consumer<CachedRegion> consumer) {
|
||||
this.cachedRegions.forEach((id, r) -> {
|
||||
if (r != null)
|
||||
consumer.accept(r);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the region ID based on the region coordinates. 0 will be
|
||||
* returned if the specified region coordinates are out of bounds.
|
||||
*
|
||||
* @param regionX The region X coordinate
|
||||
* @param regionZ The region Z coordinate
|
||||
* @return The region ID
|
||||
*/
|
||||
private long getRegionID(int regionX, int regionZ) {
|
||||
if (!isRegionInWorld(regionX, regionZ))
|
||||
return 0;
|
||||
|
||||
return (long) regionX & 0xFFFFFFFFL | ((long) regionZ & 0xFFFFFFFFL) << 32;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the specified region coordinates is within the world bounds.
|
||||
*
|
||||
* @param regionX The region X coordinate
|
||||
* @param regionZ The region Z coordinate
|
||||
* @return Whether or not the region is in world bounds
|
||||
*/
|
||||
private boolean isRegionInWorld(int regionX, int regionZ) {
|
||||
return regionX <= REGION_MAX && regionX >= -REGION_MAX && regionZ <= REGION_MAX && regionZ >= -REGION_MAX;
|
||||
}
|
||||
|
||||
private class PackerThread extends Thread {
|
||||
public void run() {
|
||||
while (true) {
|
||||
LinkedBlockingQueue<Chunk> queue = toPack;
|
||||
if (queue == null) {
|
||||
break;
|
||||
}
|
||||
try {
|
||||
Chunk chunk = queue.take();
|
||||
CachedChunk cached = ChunkPacker.pack(chunk);
|
||||
CachedWorld.this.updateCachedChunk(cached);
|
||||
//System.out.println("Processed chunk at " + chunk.x + "," + chunk.z);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,152 +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 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.chunk;
|
||||
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.pathing.PathingBlockType;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockAir;
|
||||
import net.minecraft.block.BlockDoublePlant;
|
||||
import net.minecraft.block.BlockTallGrass;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/3/2018 1:09 AM
|
||||
*/
|
||||
public final class ChunkPacker implements Helper {
|
||||
|
||||
private ChunkPacker() {}
|
||||
|
||||
public static CachedChunk pack(Chunk chunk) {
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
Map<String, List<BlockPos>> specialBlocks = new HashMap<>();
|
||||
BitSet bitSet = new BitSet(CachedChunk.SIZE);
|
||||
try {
|
||||
for (int y = 0; y < 256; y++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
int index = CachedChunk.getPositionIndex(x, y, z);
|
||||
Block block = chunk.getBlockState(x, y, z).getBlock();
|
||||
boolean[] bits = getPathingBlockType(block).getBits();
|
||||
bitSet.set(index, bits[0]);
|
||||
bitSet.set(index + 1, bits[1]);
|
||||
if (CachedChunk.BLOCKS_TO_KEEP_TRACK_OF.contains(block)) {
|
||||
String name = blockToString(block);
|
||||
specialBlocks.computeIfAbsent(name, b -> new ArrayList<>()).add(new BlockPos(x, y, z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
//System.out.println("Packed special blocks: " + specialBlocks);
|
||||
long end = System.currentTimeMillis();
|
||||
//System.out.println("Chunk packing took " + (end - start) + "ms for " + chunk.x + "," + chunk.z);
|
||||
String[] blockNames = new String[256];
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
int height = chunk.getHeightValue(x, z);
|
||||
IBlockState blockState = chunk.getBlockState(x, height, z);
|
||||
for (int y = height; y > 0; y--) {
|
||||
blockState = chunk.getBlockState(x, y, z);
|
||||
if (getPathingBlockType(blockState.getBlock()) != PathingBlockType.AIR) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
String name = blockToString(blockState.getBlock());
|
||||
blockNames[z << 4 | x] = name;
|
||||
}
|
||||
}
|
||||
CachedChunk cached = new CachedChunk(chunk.x, chunk.z, bitSet, blockNames, specialBlocks);
|
||||
return cached;
|
||||
}
|
||||
|
||||
public static String blockToString(Block block) {
|
||||
ResourceLocation loc = Block.REGISTRY.getNameForObject(block);
|
||||
String name = loc.getPath(); // normally, only write the part after the minecraft:
|
||||
if (!loc.getNamespace().equals("minecraft")) {
|
||||
// Baritone is running on top of forge with mods installed, perhaps?
|
||||
name = loc.toString(); // include the namespace with the colon
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
public static Block stringToBlock(String name) {
|
||||
if (!name.contains(":")) {
|
||||
name = "minecraft:" + name;
|
||||
}
|
||||
return Block.getBlockFromName(name);
|
||||
}
|
||||
|
||||
private static PathingBlockType getPathingBlockType(Block block) {
|
||||
if (BlockStateInterface.isWater(block)) {
|
||||
return PathingBlockType.WATER;
|
||||
}
|
||||
|
||||
if (MovementHelper.avoidWalkingInto(block)) {
|
||||
return PathingBlockType.AVOID;
|
||||
}
|
||||
// We used to do an AABB check here
|
||||
// however, this failed in the nether when you were near a nether fortress
|
||||
// because fences check their adjacent blocks in the world for their fence connection status to determine AABB shape
|
||||
// this caused a nullpointerexception when we saved chunks on unload, because they were unable to check their neighbors
|
||||
if (block instanceof BlockAir || block instanceof BlockTallGrass || block instanceof BlockDoublePlant) {
|
||||
return PathingBlockType.AIR;
|
||||
}
|
||||
|
||||
return PathingBlockType.SOLID;
|
||||
}
|
||||
|
||||
static IBlockState pathingTypeToBlock(PathingBlockType type) {
|
||||
if (type != null) {
|
||||
switch (type) {
|
||||
case AIR:
|
||||
return Blocks.AIR.getDefaultState();
|
||||
case WATER:
|
||||
return Blocks.WATER.getDefaultState();
|
||||
case AVOID:
|
||||
return Blocks.LAVA.getDefaultState();
|
||||
case SOLID:
|
||||
// Dimension solid types
|
||||
switch (mc.player.dimension) {
|
||||
case -1:
|
||||
return Blocks.NETHERRACK.getDefaultState();
|
||||
case 0:
|
||||
return Blocks.STONE.getDefaultState();
|
||||
case 1:
|
||||
return Blocks.END_STONE.getDefaultState();
|
||||
}
|
||||
|
||||
// The fallback solid type
|
||||
return Blocks.STONE.getDefaultState();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,90 +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 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.chunk;
|
||||
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A single waypoint
|
||||
*
|
||||
* @author leijurv
|
||||
*/
|
||||
public class Waypoint {
|
||||
public final String name;
|
||||
public final Tag tag;
|
||||
private final long creationTimestamp;
|
||||
public final BlockPos location;
|
||||
|
||||
public Waypoint(String name, Tag tag, BlockPos location) {
|
||||
this(name, tag, location, System.currentTimeMillis());
|
||||
}
|
||||
|
||||
Waypoint(String name, Tag tag, BlockPos location, long creationTimestamp) { // read from disk
|
||||
this.name = name;
|
||||
this.tag = tag;
|
||||
this.location = location;
|
||||
this.creationTimestamp = creationTimestamp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(o instanceof Waypoint)) {
|
||||
return false;
|
||||
}
|
||||
Waypoint w = (Waypoint) o;
|
||||
return name.equals(w.name) && tag == w.tag && location.equals(w.location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return name.hashCode() + tag.hashCode() + location.hashCode(); //lol
|
||||
}
|
||||
|
||||
public long creationTimestamp() {
|
||||
return creationTimestamp;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return name + " " + location.toString() + " " + new Date(creationTimestamp).toString();
|
||||
}
|
||||
|
||||
public enum Tag {
|
||||
HOME, DEATH, BED, USER;
|
||||
|
||||
}
|
||||
|
||||
public static final Map<String, Tag> TAG_MAP;
|
||||
|
||||
static {
|
||||
HashMap<String, Tag> map = new HashMap<>();
|
||||
map.put("home", Tag.HOME);
|
||||
map.put("base", Tag.HOME);
|
||||
map.put("bed", Tag.BED);
|
||||
map.put("spawn", Tag.BED);
|
||||
map.put("death", Tag.DEATH);
|
||||
TAG_MAP = Collections.unmodifiableMap(map);
|
||||
}
|
||||
}
|
||||
@@ -1,124 +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 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.chunk;
|
||||
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Waypoints for a world
|
||||
*
|
||||
* @author leijurv
|
||||
*/
|
||||
public class Waypoints {
|
||||
|
||||
/**
|
||||
* Magic value to detect invalid waypoint files
|
||||
*/
|
||||
private static final long WAYPOINT_MAGIC_VALUE = 121977993584L; // good value
|
||||
|
||||
private final Path directory;
|
||||
private final Map<Waypoint.Tag, Set<Waypoint>> waypoints;
|
||||
|
||||
Waypoints(Path directory) {
|
||||
this.directory = directory;
|
||||
if (!Files.exists(directory)) {
|
||||
try {
|
||||
Files.createDirectories(directory);
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
System.out.println("Would save waypoints to " + directory);
|
||||
this.waypoints = new HashMap<>();
|
||||
load();
|
||||
}
|
||||
|
||||
private void load() {
|
||||
for (Waypoint.Tag tag : Waypoint.Tag.values()) {
|
||||
load(tag);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void load(Waypoint.Tag tag) {
|
||||
waypoints.put(tag, new HashSet<>());
|
||||
|
||||
Path fileName = directory.resolve(tag.name().toLowerCase() + ".mp4");
|
||||
if (!Files.exists(fileName))
|
||||
return;
|
||||
|
||||
try (
|
||||
FileInputStream fileIn = new FileInputStream(fileName.toFile());
|
||||
BufferedInputStream bufIn = new BufferedInputStream(fileIn);
|
||||
DataInputStream in = new DataInputStream(bufIn)
|
||||
) {
|
||||
long magic = in.readLong();
|
||||
if (magic != WAYPOINT_MAGIC_VALUE) {
|
||||
throw new IOException("Bad magic value " + magic);
|
||||
}
|
||||
|
||||
long length = in.readLong(); // Yes I want 9,223,372,036,854,775,807 waypoints, do you not?
|
||||
while (length-- > 0) {
|
||||
String name = in.readUTF();
|
||||
long creationTimestamp = in.readLong();
|
||||
int x = in.readInt();
|
||||
int y = in.readInt();
|
||||
int z = in.readInt();
|
||||
waypoints.get(tag).add(new Waypoint(name, tag, new BlockPos(x, y, z), creationTimestamp));
|
||||
}
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
|
||||
private synchronized void save(Waypoint.Tag tag) {
|
||||
Path fileName = directory.resolve(tag.name().toLowerCase() + ".mp4");
|
||||
try (
|
||||
FileOutputStream fileOut = new FileOutputStream(fileName.toFile());
|
||||
BufferedOutputStream bufOut = new BufferedOutputStream(fileOut);
|
||||
DataOutputStream out = new DataOutputStream(bufOut)
|
||||
) {
|
||||
out.writeLong(WAYPOINT_MAGIC_VALUE);
|
||||
out.writeLong(waypoints.get(tag).size());
|
||||
for (Waypoint waypoint : waypoints.get(tag)) {
|
||||
out.writeUTF(waypoint.name);
|
||||
out.writeLong(waypoint.creationTimestamp());
|
||||
out.writeInt(waypoint.location.getX());
|
||||
out.writeInt(waypoint.location.getY());
|
||||
out.writeInt(waypoint.location.getZ());
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public Set<Waypoint> getByTag(Waypoint.Tag tag) {
|
||||
return Collections.unmodifiableSet(waypoints.get(tag));
|
||||
}
|
||||
|
||||
public Waypoint getMostRecentByTag(Waypoint.Tag tag) {
|
||||
// Find a waypoint of the given tag which has the greatest timestamp value, indicating the most recent
|
||||
return this.waypoints.get(tag).stream().min(Comparator.comparingLong(w -> -w.creationTimestamp())).orElse(null);
|
||||
}
|
||||
|
||||
public void addWaypoint(Waypoint waypoint) {
|
||||
// no need to check for duplicate, because it's a Set not a List
|
||||
waypoints.get(waypoint.tag).add(waypoint);
|
||||
save(waypoint.tag);
|
||||
}
|
||||
}
|
||||
@@ -1,51 +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 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.chunk;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
/**
|
||||
* Data about a world, from baritone's point of view. Includes cached chunks, waypoints, and map data.
|
||||
*
|
||||
* @author leijurv
|
||||
*/
|
||||
public class WorldData {
|
||||
public final CachedWorld cache;
|
||||
public final Waypoints waypoints;
|
||||
//public final MapData map;
|
||||
public final Path directory;
|
||||
|
||||
WorldData(Path directory) {
|
||||
this.directory = directory;
|
||||
this.cache = new CachedWorld(directory.resolve("cache"));
|
||||
this.waypoints = new Waypoints(directory.resolve("waypoints"));
|
||||
}
|
||||
|
||||
public Path getMapDirectory() {
|
||||
return directory.resolve("map");
|
||||
}
|
||||
|
||||
void onClose() {
|
||||
new Thread() {
|
||||
public void run() {
|
||||
System.out.println("Started saving the world in a new thread");
|
||||
cache.save();
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
}
|
||||
@@ -1,108 +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 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.chunk;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.launch.mixins.accessor.IAnvilChunkLoader;
|
||||
import baritone.launch.mixins.accessor.IChunkProviderServer;
|
||||
import baritone.utils.Helper;
|
||||
import net.minecraft.client.multiplayer.WorldClient;
|
||||
import net.minecraft.server.integrated.IntegratedServer;
|
||||
import net.minecraft.world.WorldServer;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/4/2018 11:06 AM
|
||||
*/
|
||||
public enum WorldProvider implements Helper {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
private final Map<Path, WorldData> worldCache = new HashMap<>();
|
||||
|
||||
private WorldData currentWorld;
|
||||
|
||||
public final WorldData getCurrentWorld() {
|
||||
return this.currentWorld;
|
||||
}
|
||||
|
||||
public final void initWorld(WorldClient world) {
|
||||
int dimensionID = world.provider.getDimensionType().getId();
|
||||
File directory;
|
||||
File readme;
|
||||
IntegratedServer integratedServer = mc.getIntegratedServer();
|
||||
if (integratedServer != null) {
|
||||
WorldServer localServerWorld = integratedServer.getWorld(dimensionID);
|
||||
IChunkProviderServer provider = (IChunkProviderServer) localServerWorld.getChunkProvider();
|
||||
IAnvilChunkLoader loader = (IAnvilChunkLoader) provider.getChunkLoader();
|
||||
directory = loader.getChunkSaveLocation();
|
||||
|
||||
// Gets the "depth" of this directory relative the the game's run directory, 2 is the location of the world
|
||||
if (directory.toPath().relativize(mc.gameDir.toPath()).getNameCount() != 2) {
|
||||
// subdirectory of the main save directory for this world
|
||||
directory = directory.getParentFile();
|
||||
}
|
||||
|
||||
directory = new File(directory, "baritone");
|
||||
readme = directory;
|
||||
|
||||
} else {
|
||||
//remote
|
||||
directory = new File(Baritone.INSTANCE.getDir(), mc.getCurrentServerData().serverIP);
|
||||
readme = Baritone.INSTANCE.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();
|
||||
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);
|
||||
}
|
||||
|
||||
public final void closeWorld() {
|
||||
WorldData world = this.currentWorld;
|
||||
this.currentWorld = null;
|
||||
if (world == null) {
|
||||
return;
|
||||
}
|
||||
world.onClose();
|
||||
}
|
||||
|
||||
public final void ifWorldLoaded(Consumer<WorldData> currentWorldConsumer) {
|
||||
if (this.currentWorld != null)
|
||||
currentWorldConsumer.accept(this.currentWorld);
|
||||
}
|
||||
}
|
||||
@@ -1,196 +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 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.event;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.chunk.WorldProvider;
|
||||
import baritone.event.events.*;
|
||||
import baritone.event.events.type.EventState;
|
||||
import baritone.event.listener.IGameEventListener;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.InputOverrideHandler;
|
||||
import baritone.utils.interfaces.Toggleable;
|
||||
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;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 7/31/2018 11:04 PM
|
||||
*/
|
||||
public final class GameEventHandler implements IGameEventListener, Helper {
|
||||
|
||||
private final List<IGameEventListener> listeners = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public final void onTick(TickEvent event) {
|
||||
dispatch(listener -> listener.onTick(event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onPlayerUpdate(PlayerUpdateEvent event) {
|
||||
dispatch(listener -> listener.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);
|
||||
}
|
||||
}
|
||||
|
||||
dispatch(IGameEventListener::onProcessKeyBinds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onSendChatMessage(ChatEvent event) {
|
||||
dispatch(listener -> listener.onSendChatMessage(event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onChunkEvent(ChunkEvent event) {
|
||||
EventState state = event.getState();
|
||||
ChunkEvent.Type type = event.getType();
|
||||
|
||||
boolean isPostPopulate = state == EventState.POST
|
||||
&& type == ChunkEvent.Type.POPULATE;
|
||||
|
||||
// Whenever the server sends us to another dimension, chunks are unloaded
|
||||
// technically after the new world has been loaded, so we perform a check
|
||||
// to make sure the chunk being unloaded is already loaded.
|
||||
boolean isPreUnload = state == EventState.PRE
|
||||
&& type == ChunkEvent.Type.UNLOAD
|
||||
&& mc.world.getChunkProvider().isChunkGeneratedAt(event.getX(), event.getZ());
|
||||
|
||||
if (isPostPopulate || isPreUnload) {
|
||||
WorldProvider.INSTANCE.ifWorldLoaded(world -> {
|
||||
Chunk chunk = mc.world.getChunk(event.getX(), event.getZ());
|
||||
world.cache.queueForPacking(chunk);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
dispatch(listener -> listener.onChunkEvent(event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onRenderPass(RenderEvent event) {
|
||||
/*
|
||||
WorldProvider.INSTANCE.ifWorldLoaded(world -> world.forEachRegion(region -> region.forEachChunk(chunk -> {
|
||||
drawChunkLine(region.getX() * 512 + chunk.getX() * 16, region.getZ() * 512 + chunk.getZ() * 16, event.getPartialTicks());
|
||||
})));
|
||||
*/
|
||||
|
||||
dispatch(listener -> listener.onRenderPass(event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onWorldEvent(WorldEvent event) {
|
||||
WorldProvider cache = WorldProvider.INSTANCE;
|
||||
|
||||
switch (event.getState()) {
|
||||
case PRE:
|
||||
cache.closeWorld();
|
||||
break;
|
||||
case POST:
|
||||
cache.closeWorld();
|
||||
if (event.getWorld() != null)
|
||||
cache.initWorld(event.getWorld());
|
||||
break;
|
||||
}
|
||||
|
||||
dispatch(listener -> listener.onWorldEvent(event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onSendPacket(PacketEvent event) {
|
||||
dispatch(listener -> listener.onSendPacket(event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onReceivePacket(PacketEvent event) {
|
||||
dispatch(listener -> listener.onReceivePacket(event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onQueryItemSlotForBlocks(ItemSlotEvent event) {
|
||||
dispatch(listener -> listener.onQueryItemSlotForBlocks(event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerRelativeMove(RelativeMoveEvent event) {
|
||||
dispatch(listener -> listener.onPlayerRelativeMove(event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockInteract(BlockInteractEvent event) {
|
||||
dispatch(listener -> listener.onBlockInteract(event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerDeath() {
|
||||
dispatch(IGameEventListener::onPlayerDeath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPathEvent(PathEvent event) {
|
||||
dispatch(listener -> listener.onPathEvent(event));
|
||||
}
|
||||
|
||||
public final void registerEventListener(IGameEventListener listener) {
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
private void dispatch(Consumer<IGameEventListener> dispatchFunction) {
|
||||
this.listeners.stream().filter(this::canDispatch).forEach(dispatchFunction);
|
||||
}
|
||||
|
||||
private boolean canDispatch(IGameEventListener listener) {
|
||||
return !(listener instanceof Toggleable) || ((Toggleable) listener).isEnabled();
|
||||
}
|
||||
}
|
||||
@@ -1,69 +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 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.event.events;
|
||||
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/22/2018
|
||||
*/
|
||||
public final class BlockInteractEvent {
|
||||
|
||||
/**
|
||||
* The position of the block interacted with
|
||||
*/
|
||||
private final BlockPos pos;
|
||||
|
||||
/**
|
||||
* The type of interaction that occurred
|
||||
*/
|
||||
private final Type type;
|
||||
|
||||
public BlockInteractEvent(BlockPos pos, Type type) {
|
||||
this.pos = pos;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The position of the block interacted with
|
||||
*/
|
||||
public final BlockPos getPos() {
|
||||
return this.pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The type of interaction with the target block
|
||||
*/
|
||||
public final Type getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public enum Type {
|
||||
|
||||
/**
|
||||
* We're breaking the target block.
|
||||
*/
|
||||
BREAK,
|
||||
|
||||
/**
|
||||
* We're right clicking on the target block. Either placing or interacting with.
|
||||
*/
|
||||
USE
|
||||
}
|
||||
}
|
||||
@@ -1,56 +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 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.event.events;
|
||||
|
||||
import baritone.event.listener.IGameEventListener;
|
||||
|
||||
/**
|
||||
* Called in some cases where a player's inventory has it's current slot queried.
|
||||
* <p>
|
||||
* @see IGameEventListener#onQueryItemSlotForBlocks()
|
||||
*
|
||||
* @author Brady
|
||||
* @since 8/20/2018
|
||||
*/
|
||||
public final class ItemSlotEvent {
|
||||
|
||||
/**
|
||||
* The current slot index
|
||||
*/
|
||||
private int slot;
|
||||
|
||||
public ItemSlotEvent(int slot) {
|
||||
this.slot = slot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the new slot index that will be used
|
||||
*
|
||||
* @param slot The slot index
|
||||
*/
|
||||
public final void setSlot(int slot) {
|
||||
this.slot = slot;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The current slot index
|
||||
*/
|
||||
public final int getSlot() {
|
||||
return this.slot;
|
||||
}
|
||||
}
|
||||
@@ -1,43 +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 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.event.events;
|
||||
|
||||
import baritone.event.events.type.EventState;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/21/2018
|
||||
*/
|
||||
public final class PlayerUpdateEvent {
|
||||
|
||||
/**
|
||||
* The state of the event
|
||||
*/
|
||||
private final EventState state;
|
||||
|
||||
public PlayerUpdateEvent(EventState state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The state of the event
|
||||
*/
|
||||
public final EventState getState() {
|
||||
return this.state;
|
||||
}
|
||||
}
|
||||
@@ -1,43 +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 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.event.events;
|
||||
|
||||
import baritone.event.events.type.EventState;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/21/2018
|
||||
*/
|
||||
public final class RelativeMoveEvent {
|
||||
|
||||
/**
|
||||
* The state of the event
|
||||
*/
|
||||
private final EventState state;
|
||||
|
||||
public RelativeMoveEvent(EventState state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The state of the event
|
||||
*/
|
||||
public final EventState getState() {
|
||||
return this.state;
|
||||
}
|
||||
}
|
||||
@@ -1,56 +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 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.event.events.RelativeMoveEvent;
|
||||
import baritone.event.events.type.EventState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.entity.Entity;
|
||||
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.callback.CallbackInfo;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/21/2018
|
||||
*/
|
||||
@Mixin(Entity.class)
|
||||
public class MixinEntity {
|
||||
|
||||
@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 (_this == Minecraft.getMinecraft().player)
|
||||
Baritone.INSTANCE.getGameEventHandler().onPlayerRelativeMove(new RelativeMoveEvent(EventState.PRE));
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "moveRelative",
|
||||
at = @At("RETURN")
|
||||
)
|
||||
private void postMoveRelative(float strafe, float up, float forward, float friction, CallbackInfo ci) {
|
||||
Entity _this = (Entity) (Object) this;
|
||||
if (_this == Minecraft.getMinecraft().player)
|
||||
Baritone.INSTANCE.getGameEventHandler().onPlayerRelativeMove(new RelativeMoveEvent(EventState.POST));
|
||||
}
|
||||
}
|
||||
@@ -17,10 +17,8 @@
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.event.events.ChatEvent;
|
||||
import baritone.event.events.PlayerUpdateEvent;
|
||||
import baritone.event.events.type.EventState;
|
||||
import baritone.bot.Baritone;
|
||||
import baritone.bot.event.events.ChatEvent;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
@@ -55,20 +53,7 @@ public class MixinEntityPlayerSP {
|
||||
by = -3
|
||||
)
|
||||
)
|
||||
private void onPreUpdate(CallbackInfo ci) {
|
||||
Baritone.INSTANCE.getGameEventHandler().onPlayerUpdate(new PlayerUpdateEvent(EventState.PRE));
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "onUpdate",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "net/minecraft/client/entity/EntityPlayerSP.onUpdateWalkingPlayer()V",
|
||||
shift = At.Shift.BY,
|
||||
by = 2
|
||||
)
|
||||
)
|
||||
private void onPostUpdate(CallbackInfo ci) {
|
||||
Baritone.INSTANCE.getGameEventHandler().onPlayerUpdate(new PlayerUpdateEvent(EventState.POST));
|
||||
private void onUpdate(CallbackInfo ci) {
|
||||
Baritone.INSTANCE.getGameEventHandler().onPlayerUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.event.events.RenderEvent;
|
||||
import baritone.bot.Baritone;
|
||||
import baritone.bot.event.events.RenderEvent;
|
||||
import net.minecraft.client.renderer.EntityRenderer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.bot.Baritone;
|
||||
import net.minecraft.client.settings.GameSettings;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
@@ -34,8 +34,7 @@ public class MixinGameSettings {
|
||||
method = "isKeyDown",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "org/lwjgl/input/Keyboard.isKeyDown(I)Z",
|
||||
remap = false
|
||||
target = "org/lwjgl/input/Keyboard.isKeyDown(I)Z"
|
||||
)
|
||||
)
|
||||
private static boolean isKeyDown(int keyCode) {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.bot.Baritone;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
@@ -37,8 +37,7 @@ public class MixinGuiContainer {
|
||||
},
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "org/lwjgl/input/Keyboard.isKeyDown(I)Z",
|
||||
remap = false
|
||||
target = "org/lwjgl/input/Keyboard.isKeyDown(I)Z"
|
||||
)
|
||||
)
|
||||
private boolean isKeyDown(int keyCode) {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.bot.Baritone;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
@@ -38,8 +38,7 @@ public class MixinGuiScreen {
|
||||
},
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "org/lwjgl/input/Keyboard.isKeyDown(I)Z",
|
||||
remap = false
|
||||
target = "org/lwjgl/input/Keyboard.isKeyDown(I)Z"
|
||||
)
|
||||
)
|
||||
private static boolean isKeyDown(int keyCode) {
|
||||
|
||||
@@ -1,62 +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 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.event.events.ItemSlotEvent;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
import org.spongepowered.asm.lib.Opcodes;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/20/2018
|
||||
*/
|
||||
@Mixin(InventoryPlayer.class)
|
||||
public class MixinInventoryPlayer {
|
||||
|
||||
@Redirect(
|
||||
method = "getDestroySpeed",
|
||||
at = @At(
|
||||
value = "FIELD",
|
||||
opcode = Opcodes.GETFIELD,
|
||||
target = "net/minecraft/entity/player/InventoryPlayer.currentItem:I"
|
||||
)
|
||||
)
|
||||
private int getDestroySpeed$getCurrentItem(InventoryPlayer inventory) {
|
||||
ItemSlotEvent event = new ItemSlotEvent(inventory.currentItem);
|
||||
Baritone.INSTANCE.getGameEventHandler().onQueryItemSlotForBlocks(event);
|
||||
return event.getSlot();
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "canHarvestBlock",
|
||||
at = @At(
|
||||
value = "FIELD",
|
||||
opcode = Opcodes.GETFIELD,
|
||||
target = "net/minecraft/entity/player/InventoryPlayer.currentItem:I"
|
||||
)
|
||||
)
|
||||
private int canHarvestBlock$getCurrentItem(InventoryPlayer inventory) {
|
||||
ItemSlotEvent event = new ItemSlotEvent(inventory.currentItem);
|
||||
Baritone.INSTANCE.getGameEventHandler().onQueryItemSlotForBlocks(event);
|
||||
return event.getSlot();
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.bot.Baritone;
|
||||
import net.minecraft.client.settings.KeyBinding;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
|
||||
83
src/main/java/baritone/launch/mixins/MixinBlockPos.java → src/main/java/baritone/launch/mixins/MixinMain.java
Normal file → Executable file
83
src/main/java/baritone/launch/mixins/MixinBlockPos.java → src/main/java/baritone/launch/mixins/MixinMain.java
Normal file → Executable file
@@ -1,43 +1,40 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3i;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/25/2018
|
||||
*/
|
||||
@Mixin(BlockPos.class)
|
||||
public abstract class MixinBlockPos extends Vec3i {
|
||||
|
||||
public MixinBlockPos(int xIn, int yIn, int zIn) {
|
||||
super(xIn, yIn, zIn);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public String toString() {
|
||||
return MoreObjects.toStringHelper("BlockPos").add("x", this.getX()).add("y", this.getY()).add("z", this.getZ()).toString();
|
||||
}
|
||||
}
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import net.minecraft.client.main.Main;
|
||||
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.callback.CallbackInfo;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 7/31/2018 10:18 PM
|
||||
*/
|
||||
@Mixin(Main.class)
|
||||
public class MixinMain {
|
||||
|
||||
@Inject(
|
||||
method = "main",
|
||||
at = @At("HEAD")
|
||||
)
|
||||
private static void main(String[] args, CallbackInfo ci) {
|
||||
System.setProperty("java.net.preferIPv4Stack", "true");
|
||||
}
|
||||
}
|
||||
@@ -17,21 +17,13 @@
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.behavior.impl.PathingBehavior;
|
||||
import baritone.event.events.BlockInteractEvent;
|
||||
import baritone.event.events.TickEvent;
|
||||
import baritone.event.events.WorldEvent;
|
||||
import baritone.event.events.type.EventState;
|
||||
import baritone.utils.ExampleBaritoneControl;
|
||||
import baritone.bot.Baritone;
|
||||
import baritone.bot.event.events.TickEvent;
|
||||
import baritone.bot.event.events.WorldEvent;
|
||||
import baritone.bot.event.events.type.EventState;
|
||||
import baritone.bot.utils.ExampleBaritoneControl;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.multiplayer.WorldClient;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumActionResult;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import org.spongepowered.asm.lib.Opcodes;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
@@ -39,7 +31,6 @@ 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 org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
@@ -49,7 +40,6 @@ import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
public class MixinMinecraft {
|
||||
|
||||
@Shadow private int leftClickCounter;
|
||||
@Shadow public EntityPlayerSP player;
|
||||
@Shadow public WorldClient world;
|
||||
|
||||
@Inject(
|
||||
@@ -86,8 +76,7 @@ public class MixinMinecraft {
|
||||
method = "runTickKeyboard",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "org/lwjgl/input/Keyboard.isKeyDown(I)Z",
|
||||
remap = false
|
||||
target = "org/lwjgl/input/Keyboard.isKeyDown(I)Z"
|
||||
)
|
||||
)
|
||||
private boolean Keyboard$isKeyDown(int keyCode) {
|
||||
@@ -102,6 +91,23 @@ public class MixinMinecraft {
|
||||
Baritone.INSTANCE.getGameEventHandler().onProcessKeyBinds();
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = {
|
||||
"setIngameFocus",
|
||||
"runTick"
|
||||
},
|
||||
at = @At(
|
||||
value = "FIELD",
|
||||
opcode = Opcodes.PUTFIELD,
|
||||
target = "net/minecraft/client/Minecraft.leftClickCounter:I",
|
||||
ordinal = 0
|
||||
)
|
||||
)
|
||||
private void setLeftClickCounter(Minecraft mc, int value) {
|
||||
if (!Baritone.INSTANCE.isInitialized() || !Baritone.INSTANCE.getInputOverrideHandler().isInputForcedDown(mc.gameSettings.keyBindAttack))
|
||||
this.leftClickCounter = value;
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "loadWorld(Lnet/minecraft/client/multiplayer/WorldClient;Ljava/lang/String;)V",
|
||||
at = @At("HEAD")
|
||||
@@ -135,40 +141,4 @@ public class MixinMinecraft {
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "runTick",
|
||||
at = @At(
|
||||
value = "FIELD",
|
||||
opcode = Opcodes.GETFIELD,
|
||||
target = "net/minecraft/client/gui/GuiScreen.allowUserInput:Z"
|
||||
)
|
||||
)
|
||||
private boolean isAllowUserInput(GuiScreen screen) {
|
||||
return (PathingBehavior.INSTANCE.getCurrent() != null && player != null) || screen.allowUserInput;
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "clickMouse",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "net/minecraft/client/multiplayer/PlayerControllerMP.clickBlock(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/EnumFacing;)Z"
|
||||
),
|
||||
locals = LocalCapture.CAPTURE_FAILHARD
|
||||
)
|
||||
private void onBlockBreak(CallbackInfo ci, BlockPos pos) {
|
||||
Baritone.INSTANCE.getGameEventHandler().onBlockInteract(new BlockInteractEvent(pos, BlockInteractEvent.Type.BREAK));
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "rightClickMouse",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "net/minecraft/client/entity/EntityPlayerSP.swingArm(Lnet/minecraft/util/EnumHand;)V"
|
||||
),
|
||||
locals = LocalCapture.CAPTURE_FAILHARD
|
||||
)
|
||||
private void onBlockUse(CallbackInfo ci, EnumHand var1[], int var2, int var3, EnumHand enumhand, ItemStack itemstack, BlockPos blockpos, int i, EnumActionResult enumactionresult) {
|
||||
Baritone.INSTANCE.getGameEventHandler().onBlockInteract(new BlockInteractEvent(blockpos, BlockInteractEvent.Type.USE));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,12 +17,11 @@
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.event.events.ChunkEvent;
|
||||
import baritone.event.events.type.EventState;
|
||||
import baritone.bot.Baritone;
|
||||
import baritone.bot.event.events.ChunkEvent;
|
||||
import baritone.bot.event.events.type.EventState;
|
||||
import net.minecraft.client.network.NetHandlerPlayClient;
|
||||
import net.minecraft.network.play.server.SPacketChunkData;
|
||||
import net.minecraft.network.play.server.SPacketCombatEvent;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
@@ -67,15 +66,4 @@ public class MixinNetHandlerPlayClient {
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "handleCombatEvent",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "net/minecraft/client/Minecraft.displayGuiScreen(Lnet/minecraft/client/gui/GuiScreen;)V"
|
||||
)
|
||||
)
|
||||
private void onPlayerDeath(SPacketCombatEvent packetIn, CallbackInfo ci) {
|
||||
Baritone.INSTANCE.getGameEventHandler().onPlayerDeath();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.event.events.PacketEvent;
|
||||
import baritone.event.events.type.EventState;
|
||||
import baritone.bot.Baritone;
|
||||
import baritone.bot.event.events.PacketEvent;
|
||||
import baritone.bot.event.events.type.EventState;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.util.concurrent.Future;
|
||||
@@ -64,7 +64,8 @@ public abstract class MixinNetworkManager {
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "net/minecraft/network/Packet.processPacket(Lnet/minecraft/network/INetHandler;)V"
|
||||
)
|
||||
),
|
||||
remap = false
|
||||
)
|
||||
private void preProcessPacket(ChannelHandlerContext context, Packet<?> packet, CallbackInfo ci) {
|
||||
Baritone.INSTANCE.getGameEventHandler().onReceivePacket(new PacketEvent(EventState.PRE, packet));
|
||||
@@ -72,7 +73,8 @@ public abstract class MixinNetworkManager {
|
||||
|
||||
@Inject(
|
||||
method = "channelRead0",
|
||||
at = @At("RETURN")
|
||||
at = @At("RETURN"),
|
||||
remap = false
|
||||
)
|
||||
private void postProcessPacket(ChannelHandlerContext context, Packet<?> packet, CallbackInfo ci) {
|
||||
if (this.channel.isOpen())
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.event.events.ChunkEvent;
|
||||
import baritone.event.events.type.EventState;
|
||||
import baritone.bot.Baritone;
|
||||
import baritone.bot.event.events.ChunkEvent;
|
||||
import baritone.bot.event.events.type.EventState;
|
||||
import net.minecraft.client.multiplayer.WorldClient;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
package baritone.map;
|
||||
|
||||
import baritone.behavior.Behavior;
|
||||
import baritone.chunk.WorldProvider;
|
||||
import baritone.event.events.ChunkEvent;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class Map extends Behavior {
|
||||
|
||||
public static final Map INSTANCE = new Map();
|
||||
|
||||
private BufferedImage fullImage = new BufferedImage(4080, 4080, BufferedImage.TYPE_INT_RGB);
|
||||
|
||||
private Map() {
|
||||
try {
|
||||
fullImage = ImageIO.read(getImagePath().toFile());
|
||||
} catch (IOException ignored) { }
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkEvent(ChunkEvent event) {
|
||||
if (event.getType() != ChunkEvent.Type.POPULATE)
|
||||
return;
|
||||
|
||||
MapChunk map = new MapChunk(world().getChunk(event.getX(), event.getZ()));
|
||||
stitchMapChunk(map);
|
||||
if (world().getChunkProvider().isChunkGeneratedAt(event.getX(), event.getZ() - 1)) {
|
||||
stitchMapChunk(new MapChunk(world().getChunk(event.getX(), event.getZ() - 1)));
|
||||
}
|
||||
}
|
||||
|
||||
private void stitchMapChunk(MapChunk map) {
|
||||
ChunkPos pos = map.getChunk().getPos();
|
||||
int startX = pos.x * 16 + (fullImage.getWidth() / 2) - 8;
|
||||
int startZ = pos.z * 16 + (fullImage.getHeight() / 2) - 8;
|
||||
Graphics graphics = fullImage.getGraphics();
|
||||
graphics.drawImage(map.generateOverview(), startX, startZ, null);
|
||||
}
|
||||
|
||||
public void writeImage() {
|
||||
Path image = getImagePath();
|
||||
if (!Files.exists(image.getParent())) {
|
||||
try {
|
||||
Files.createDirectory(image.getParent());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
try {
|
||||
ImageIO.write(fullImage, "PNG", image.toFile());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public Path getImagePath() {
|
||||
return WorldProvider.INSTANCE.getCurrentWorld().getMapDirectory().resolve("full-map.png");
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user