001/*
002 * This file is part of Baritone.
003 *
004 * Baritone is free software: you can redistribute it and/or modify
005 * it under the terms of the GNU Lesser General Public License as published by
006 * the Free Software Foundation, either version 3 of the License, or
007 * (at your option) any later version.
008 *
009 * Baritone is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012 * GNU Lesser General Public License for more details.
013 *
014 * You should have received a copy of the GNU Lesser General Public License
015 * along with Baritone.  If not, see <https://www.gnu.org/licenses/>.
016 */
017
018package baritone.api.pathing.goals;
019
020import baritone.api.utils.BetterBlockPos;
021import baritone.api.utils.SettingsUtil;
022import baritone.api.utils.interfaces.IGoalRenderPos;
023import net.minecraft.core.BlockPos;
024
025/**
026 * A specific BlockPos goal
027 *
028 * @author leijurv
029 */
030public class GoalBlock implements Goal, IGoalRenderPos {
031
032    /**
033     * The X block position of this goal
034     */
035    public final int x;
036
037    /**
038     * The Y block position of this goal
039     */
040    public final int y;
041
042    /**
043     * The Z block position of this goal
044     */
045    public final int z;
046
047    public GoalBlock(BlockPos pos) {
048        this(pos.getX(), pos.getY(), pos.getZ());
049    }
050
051    public GoalBlock(int x, int y, int z) {
052        this.x = x;
053        this.y = y;
054        this.z = z;
055    }
056
057    @Override
058    public boolean isInGoal(int x, int y, int z) {
059        return x == this.x && y == this.y && z == this.z;
060    }
061
062    @Override
063    public double heuristic(int x, int y, int z) {
064        int xDiff = x - this.x;
065        int yDiff = y - this.y;
066        int zDiff = z - this.z;
067        return calculate(xDiff, yDiff, zDiff);
068    }
069
070    @Override
071    public boolean equals(Object o) {
072        if (this == o) {
073            return true;
074        }
075        if (o == null || getClass() != o.getClass()) {
076            return false;
077        }
078
079        GoalBlock goal = (GoalBlock) o;
080        return x == goal.x
081                && y == goal.y
082                && z == goal.z;
083    }
084
085    @Override
086    public int hashCode() {
087        return (int) BetterBlockPos.longHash(x, y, z) * 905165533;
088    }
089
090    @Override
091    public String toString() {
092        return String.format(
093                "GoalBlock{x=%s,y=%s,z=%s}",
094                SettingsUtil.maybeCensor(x),
095                SettingsUtil.maybeCensor(y),
096                SettingsUtil.maybeCensor(z)
097        );
098    }
099
100    /**
101     * @return The position of this goal as a {@link BlockPos}
102     */
103    @Override
104    public BlockPos getGoalPos() {
105        return new BlockPos(x, y, z);
106    }
107
108    public static double calculate(double xDiff, int yDiff, double zDiff) {
109        double heuristic = 0;
110
111        // if yDiff is 1 that means that currentY-goalY==1 which means that we're 1 block above where we should be
112        // therefore going from 0,yDiff,0 to a GoalYLevel of 0 is accurate
113        heuristic += GoalYLevel.calculate(0, yDiff);
114
115        //use the pythagorean and manhattan mixture from GoalXZ
116        heuristic += GoalXZ.calculate(xDiff, zDiff);
117        return heuristic;
118    }
119}