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.SettingsUtil; 021import it.unimi.dsi.fastutil.doubles.DoubleOpenHashSet; 022import it.unimi.dsi.fastutil.doubles.DoubleIterator; 023import net.minecraft.util.math.BlockPos; 024 025import java.util.Arrays; 026 027/** 028 * Useful for automated combat (retreating specifically) 029 * 030 * @author leijurv 031 */ 032public class GoalRunAway implements Goal { 033 034 private final BlockPos[] from; 035 036 private final int distanceSq; 037 038 private final Integer maintainY; 039 040 public GoalRunAway(double distance, BlockPos... from) { 041 this(distance, null, from); 042 } 043 044 public GoalRunAway(double distance, Integer maintainY, BlockPos... from) { 045 if (from.length == 0) { 046 throw new IllegalArgumentException(); 047 } 048 this.from = from; 049 this.distanceSq = (int) (distance * distance); 050 this.maintainY = maintainY; 051 } 052 053 @Override 054 public boolean isInGoal(int x, int y, int z) { 055 if (maintainY != null && maintainY != y) { 056 return false; 057 } 058 for (BlockPos p : from) { 059 int diffX = x - p.getX(); 060 int diffZ = z - p.getZ(); 061 int distSq = diffX * diffX + diffZ * diffZ; 062 if (distSq < distanceSq) { 063 return false; 064 } 065 } 066 return true; 067 } 068 069 @Override 070 public double heuristic(int x, int y, int z) {// mostly copied from GoalBlock 071 double min = Double.MAX_VALUE; 072 for (BlockPos p : from) { 073 double h = GoalXZ.calculate(p.getX() - x, p.getZ() - z); 074 if (h < min) { 075 min = h; 076 } 077 } 078 min = -min; 079 if (maintainY != null) { 080 min = min * 0.6 + GoalYLevel.calculate(maintainY, y) * 1.5; 081 } 082 return min; 083 } 084 085 @Override 086 public double heuristic() {// TODO less hacky solution 087 int distance = (int) Math.ceil(Math.sqrt(distanceSq)); 088 int minX = Integer.MAX_VALUE; 089 int minY = Integer.MAX_VALUE; 090 int minZ = Integer.MAX_VALUE; 091 int maxX = Integer.MIN_VALUE; 092 int maxY = Integer.MIN_VALUE; 093 int maxZ = Integer.MIN_VALUE; 094 for (BlockPos p : from) { 095 minX = Math.min(minX, p.getX() - distance); 096 minY = Math.min(minY, p.getY() - distance); 097 minZ = Math.min(minZ, p.getZ() - distance); 098 maxX = Math.max(minX, p.getX() + distance); 099 maxY = Math.max(minY, p.getY() + distance); 100 maxZ = Math.max(minZ, p.getZ() + distance); 101 } 102 DoubleOpenHashSet maybeAlwaysInside = new DoubleOpenHashSet(); // see pull request #1978 103 double minOutside = Double.POSITIVE_INFINITY; 104 for (int x = minX; x <= maxX; x++) { 105 for (int y = minY; y <= maxY; y++) { 106 for (int z = minZ; z <= maxZ; z++) { 107 double h = heuristic(x, y, z); 108 if (h < minOutside && isInGoal(x, y, z)) { 109 maybeAlwaysInside.add(h); 110 } else { 111 minOutside = Math.min(minOutside, h); 112 } 113 } 114 } 115 } 116 double maxInside = Double.NEGATIVE_INFINITY; 117 DoubleIterator it = maybeAlwaysInside.iterator(); 118 while (it.hasNext()) { 119 double inside = it.nextDouble(); 120 if (inside < minOutside) { 121 maxInside = Math.max(maxInside, inside); 122 } 123 } 124 return maxInside; 125 } 126 127 @Override 128 public String toString() { 129 if (maintainY != null) { 130 return String.format( 131 "GoalRunAwayFromMaintainY y=%s, %s", 132 SettingsUtil.maybeCensor(maintainY), 133 Arrays.asList(from) 134 ); 135 } else { 136 return "GoalRunAwayFrom" + Arrays.asList(from); 137 } 138 } 139}