Compare commits

..

1 Commits

Author SHA1 Message Date
Leijurv
21b0f74a76 spaghetti to export list of canWalkThrough and canWalkOn 2018-08-17 14:12:35 -07:00
138 changed files with 6691 additions and 4343 deletions

View File

@@ -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.

View File

@@ -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'
}

View File

@@ -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() { }
}

View File

@@ -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()));
}
}

View File

@@ -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--;
}
}
}

View File

@@ -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;
}
}

View 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() { }
}

View File

@@ -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;
}

View 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--;
}
}
}

View File

@@ -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 {

View File

@@ -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

View File

@@ -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();

View 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");
}
}

View 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");
}
}

View 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;
}
}

View 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);
}
}

View 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;
}
}

View File

@@ -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);
}

View 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();
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -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;
/**

View File

@@ -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

View File

@@ -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 {

View File

@@ -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;
/**

View File

@@ -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

View File

@@ -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

View File

@@ -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) {}
}

View File

@@ -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);
}

View File

@@ -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();

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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

View File

@@ -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];
}
}
}

View File

@@ -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

View File

@@ -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.

View File

@@ -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;
/**

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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 {

View File

@@ -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();

View File

@@ -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;
}
}

View File

@@ -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<>();
}

View File

@@ -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 {

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}

View File

@@ -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) {

View File

@@ -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]);

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;
}
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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();
}

View 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;
}
}
}
}

View 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();
}
}

View File

@@ -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()));
}
}
}

View File

@@ -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);
}

View File

@@ -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();

View File

@@ -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;

View File

@@ -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;
}
}
}

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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());
}
}

View File

@@ -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

View File

@@ -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");
}
}

View File

@@ -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");
}
}

View File

@@ -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;
}
}
}
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}

View File

@@ -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();
}
}

View File

@@ -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
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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));
}
}

View File

@@ -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();
}
}

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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();
}
}

View File

@@ -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;

View 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");
}
}

View File

@@ -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));
}
}

View File

@@ -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();
}
}

View File

@@ -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())

View File

@@ -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;

View File

@@ -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