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.BaritoneAPI; 021import baritone.api.utils.BetterBlockPos; 022import baritone.api.utils.SettingsUtil; 023import net.minecraft.util.Mth; 024import net.minecraft.world.phys.Vec3; 025 026/** 027 * Useful for long-range goals that don't have a specific Y level. 028 * 029 * @author leijurv 030 */ 031public class GoalXZ implements Goal { 032 033 private static final double SQRT_2 = Math.sqrt(2); 034 035 /** 036 * The X block position of this goal 037 */ 038 private final int x; 039 040 /** 041 * The Z block position of this goal 042 */ 043 private final int z; 044 045 public GoalXZ(int x, int z) { 046 this.x = x; 047 this.z = z; 048 } 049 050 public GoalXZ(BetterBlockPos pos) { 051 this.x = pos.x; 052 this.z = pos.z; 053 } 054 055 @Override 056 public boolean isInGoal(int x, int y, int z) { 057 return x == this.x && z == this.z; 058 } 059 060 @Override 061 public double heuristic(int x, int y, int z) {//mostly copied from GoalBlock 062 int xDiff = x - this.x; 063 int zDiff = z - this.z; 064 return calculate(xDiff, zDiff); 065 } 066 067 @Override 068 public boolean equals(Object o) { 069 if (this == o) { 070 return true; 071 } 072 if (o == null || getClass() != o.getClass()) { 073 return false; 074 } 075 076 GoalXZ goal = (GoalXZ) o; 077 return x == goal.x && z == goal.z; 078 } 079 080 @Override 081 public int hashCode() { 082 int hash = 1791873246; 083 hash = hash * 222601791 + x; 084 hash = hash * -1331679453 + z; 085 return hash; 086 } 087 088 @Override 089 public String toString() { 090 return String.format( 091 "GoalXZ{x=%s,z=%s}", 092 SettingsUtil.maybeCensor(x), 093 SettingsUtil.maybeCensor(z) 094 ); 095 } 096 097 public static double calculate(double xDiff, double zDiff) { 098 //This is a combination of pythagorean and manhattan distance 099 //It takes into account the fact that pathing can either walk diagonally or forwards 100 101 //It's not possible to walk forward 1 and right 2 in sqrt(5) time 102 //It's really 1+sqrt(2) because it'll walk forward 1 then diagonally 1 103 double x = Math.abs(xDiff); 104 double z = Math.abs(zDiff); 105 double straight; 106 double diagonal; 107 if (x < z) { 108 straight = z - x; 109 diagonal = x; 110 } else { 111 straight = x - z; 112 diagonal = z; 113 } 114 diagonal *= SQRT_2; 115 return (diagonal + straight) * BaritoneAPI.getSettings().costHeuristic.value; // big TODO tune 116 } 117 118 public static GoalXZ fromDirection(Vec3 origin, float yaw, double distance) { 119 float theta = (float) Math.toRadians(yaw); 120 double x = origin.x - Mth.sin(theta) * distance; 121 double z = origin.z + Mth.cos(theta) * distance; 122 return new GoalXZ(Mth.floor(x), Mth.floor(z)); 123 } 124 125 public int getX() { 126 return x; 127 } 128 129 public int getZ() { 130 return z; 131 } 132}