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 it.unimi.dsi.fastutil.doubles.DoubleIterator; 024import it.unimi.dsi.fastutil.doubles.DoubleOpenHashSet; 025import net.minecraft.core.BlockPos; 026 027public class GoalNear implements Goal, IGoalRenderPos { 028 029 private final int x; 030 private final int y; 031 private final int z; 032 private final int rangeSq; 033 034 public GoalNear(BlockPos pos, int range) { 035 this.x = pos.getX(); 036 this.y = pos.getY(); 037 this.z = pos.getZ(); 038 this.rangeSq = range * range; 039 } 040 041 @Override 042 public boolean isInGoal(int x, int y, int z) { 043 int xDiff = x - this.x; 044 int yDiff = y - this.y; 045 int zDiff = z - this.z; 046 return xDiff * xDiff + yDiff * yDiff + zDiff * zDiff <= rangeSq; 047 } 048 049 @Override 050 public double heuristic(int x, int y, int z) { 051 int xDiff = x - this.x; 052 int yDiff = y - this.y; 053 int zDiff = z - this.z; 054 return GoalBlock.calculate(xDiff, yDiff, zDiff); 055 } 056 057 @Override 058 public double heuristic() {// TODO less hacky solution 059 int range = (int) Math.ceil(Math.sqrt(rangeSq)); 060 DoubleOpenHashSet maybeAlwaysInside = new DoubleOpenHashSet(); // see pull request #1978 061 double minOutside = Double.POSITIVE_INFINITY; 062 for (int dx = -range; dx <= range; dx++) { 063 for (int dy = -range; dy <= range; dy++) { 064 for (int dz = -range; dz <= range; dz++) { 065 double h = heuristic(x + dx, y + dy, z + dz); 066 if (h < minOutside && isInGoal(x + dx, y + dy, z + dz)) { 067 maybeAlwaysInside.add(h); 068 } else { 069 minOutside = Math.min(minOutside, h); 070 } 071 } 072 } 073 } 074 double maxInside = Double.NEGATIVE_INFINITY; 075 DoubleIterator it = maybeAlwaysInside.iterator(); 076 while (it.hasNext()) { 077 double inside = it.nextDouble(); 078 if (inside < minOutside) { 079 maxInside = Math.max(maxInside, inside); 080 } 081 } 082 return maxInside; 083 } 084 085 @Override 086 public BlockPos getGoalPos() { 087 return new BlockPos(x, y, z); 088 } 089 090 @Override 091 public boolean equals(Object o) { 092 if (this == o) { 093 return true; 094 } 095 if (o == null || getClass() != o.getClass()) { 096 return false; 097 } 098 099 GoalNear goal = (GoalNear) o; 100 return x == goal.x 101 && y == goal.y 102 && z == goal.z 103 && rangeSq == goal.rangeSq; 104 } 105 106 @Override 107 public int hashCode() { 108 return (int) BetterBlockPos.longHash(x, y, z) + rangeSq; 109 } 110 111 @Override 112 public String toString() { 113 return String.format( 114 "GoalNear{x=%s, y=%s, z=%s, rangeSq=%d}", 115 SettingsUtil.maybeCensor(x), 116 SettingsUtil.maybeCensor(y), 117 SettingsUtil.maybeCensor(z), 118 rangeSq 119 ); 120 } 121}