baritone/pathfinding/actions/ActionPlaceOrBreak.java
2018-08-01 11:34:35 -04:00

222 lines
9.6 KiB
Java

/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package baritone.pathfinding.actions;
import java.util.ArrayList;
import baritone.util.ToolSet;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import baritone.ui.LookManager;
import baritone.Baritone;
import baritone.movement.MovementManager;
import baritone.util.Out;
import baritone.inventory.SmeltingTask;
import net.minecraft.block.Block;
import net.minecraft.block.BlockFalling;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
/**
*
* @author leijurv
*/
public abstract class ActionPlaceOrBreak extends Action {
public final BlockPos[] positionsToBreak;//the positions that need to be broken before this action can ensue
public final BlockPos[] positionsToPlace;//the positions where we need to place a block before this aciton can ensue
public final Block[] blocksToBreak;//the blocks at those positions
public final Block[] blocksToPlace;
public ActionPlaceOrBreak(BlockPos start, BlockPos end, BlockPos[] toBreak, BlockPos[] toPlace) {
super(start, end);
this.positionsToBreak = toBreak;
this.positionsToPlace = toPlace;
blocksToBreak = new Block[positionsToBreak.length];
blocksToPlace = new Block[positionsToPlace.length];
for (int i = 0; i < blocksToBreak.length; i++) {
blocksToBreak[i] = Minecraft.getMinecraft().world.getBlockState(positionsToBreak[i]).getBlock();
}
for (int i = 0; i < blocksToPlace.length; i++) {
blocksToPlace[i] = Minecraft.getMinecraft().world.getBlockState(positionsToPlace[i]).getBlock();
}
}
public double getTotalHardnessOfBlocksToBreak() {//of all the blocks we need to break before starting this action, what's the sum of how hard they are (phrasing)
ToolSet ts = new ToolSet();
return this.getTotalHardnessOfBlocksToBreak(ts);
}
public double getTotalHardnessOfBlocksToBreak(ToolSet ts) {
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();
}
}
for (BlockPos pos : toBreak) {
sum += getHardness(ts, Minecraft.getMinecraft().world.getBlockState(pos).getBlock(), pos);
if (sum >= COST_INF) {
return COST_INF;
}
}
if (!Baritone.allowBreakOrPlace || !Baritone.hasThrowaway) {
for (int i = 0; i < blocksToPlace.length; i++) {
if (!canWalkOn(positionsToPlace[i])) {
return COST_INF;
}
}
}
return sum;
}
public static boolean canFall(BlockPos pos) {
return Minecraft.getMinecraft().world.getBlockState(pos).getBlock() instanceof BlockFalling;
}
public static double getHardness(ToolSet ts, Block block, BlockPos position) {
if (!block.equals(Block.getBlockById(0)) && !canWalkThrough(position)) {
if (avoidBreaking(position)) {
return COST_INF;
}
if (!Baritone.allowBreakOrPlace) {
return COST_INF;
}
if (SmeltingTask.avoidBreaking(position)) {
return COST_INF;
}
double m = Block.getBlockFromName("minecraft:crafting_table").equals(block) ? 10 : 1;
return m / ts.getStrVsBlock(block, position) + BREAK_ONE_BLOCK_ADD;
}
return 0;
}
@Override
public String toString() {
return this.getClass() + " place " + Arrays.asList(blocksToPlace) + " break " + Arrays.asList(blocksToBreak) + " cost " + cost(null) + " break cost " + getTotalHardnessOfBlocksToBreak();
}
@Override
public boolean tick() {
//breaking first
for (int i = 0; i < positionsToBreak.length; i++) {
if (!canWalkThrough(positionsToBreak[i])) {
if (!Baritone.allowBreakOrPlace) {
Out.gui("BB I can't break this =(((", Out.Mode.Standard);
return false;
}
//Out.log("Breaking " + blocksToBreak[i] + " at " + positionsToBreak[i]);
boolean lookingInCorrectDirection = LookManager.lookAtBlock(positionsToBreak[i], true);
//TODO decide if when actuallyLookingAtTheBlock==true then should it still keep moving the look direction to the exact center of the block
boolean actuallyLookingAtTheBlock = positionsToBreak[i].equals(Baritone.whatAreYouLookingAt());
if (!(lookingInCorrectDirection || actuallyLookingAtTheBlock)) {
return false;
}
/*if (!positionsToBreak[i].equals(Baritone.whatAreYouLookingAt())) {//hmmm, our crosshairs are looking at the wrong block
//TODO add a timer here, and if we are stuck looking at the wrong block for more than 1 second, do something
//(it cant take longer than twenty ticks, because the Baritone.MAX_YAW_CHANGE_PER_TICK=18, and 18*20 = 360°
Out.log("Wrong");
return false;
}*/
if (Baritone.whatAreYouLookingAt() != null) {
Baritone.switchtotool(Minecraft.getMinecraft().world.getBlockState(Baritone.whatAreYouLookingAt()).getBlock());
}
MovementManager.isLeftClick = true;//hold down left click
if (canWalkThrough(positionsToBreak[i])) {
MovementManager.letGoOfLeftClick();
Out.log("Done breaking " + blocksToBreak[i] + " at " + positionsToBreak[i]);
}
return false;
}
}
MovementManager.letGoOfLeftClick();//sometimes it keeps on left clicking so we need this here (yes it scares me too)
for (BlockPos positionsToPlace1 : positionsToPlace) {
if (!canWalkOn(positionsToPlace1)) {
if (!Baritone.allowBreakOrPlace) {
Out.gui("BB I can't place this =(((", Out.Mode.Standard);
return false;
}
//Baritone.lookAtBlock(positionsToPlace[i], true);
//Out.log("CANT DO IT. CANT WALK ON " + blocksToPlace[i] + " AT " + positionsToPlace[i]);
//one of the blocks that needs to be there isn't there
//so basically someone mined out our path from under us
//
//this doesn't really do anything, because all the cases for positionToPlace are handled in their respective action tick0s (e.g. pillar and bridge)
}
}
return tick0();
}
//I dont want to make this static, because then it might be executed before Item gets initialized
private static List<Item> ACCEPTABLE_THROWAWAY_ITEMS = null;
private static void set() {
if (ACCEPTABLE_THROWAWAY_ITEMS != null) {
return;
}
ACCEPTABLE_THROWAWAY_ITEMS = Arrays.asList(new Item[]{Item.getByNameOrId("minecraft:dirt"), Item.getByNameOrId("minecraft:cobblestone")});
}
public static boolean switchtothrowaway(boolean message) {
set();
EntityPlayerSP p = Minecraft.getMinecraft().player;
ItemStack[] inv = p.inventory.mainInventory;
for (byte i = 0; i < 9; i++) {
ItemStack item = inv[i];
if (inv[i] == null) {
item = new ItemStack(Item.getByNameOrId("minecraft:apple"));
}
if (ACCEPTABLE_THROWAWAY_ITEMS.contains(item.getItem())) {
p.inventory.currentItem = i;
return true;
}
}
if (message) {
Out.gui("bb pls get me some blocks. dirt or cobble", Out.Mode.Minimal);
}
return false;
}
public static boolean hasthrowaway() {
set();
EntityPlayerSP p = Minecraft.getMinecraft().player;
ItemStack[] inv = p.inventory.mainInventory;
for (byte i = 0; i < 9; i++) {
ItemStack item = inv[i];
if (inv[i] == null) {
item = new ItemStack(Item.getByNameOrId("minecraft:apple"));
}
if (ACCEPTABLE_THROWAWAY_ITEMS.contains(item.getItem())) {
return true;
}
}
return false;
}
/**
* Do the actual tick. This function can assume that all blocks in
* positionsToBreak are now walk-through-able.
*
* @return
*/
protected abstract boolean tick0();
public ArrayList<BlockPos> toMine() {
ArrayList<BlockPos> result = new ArrayList<>();
for (BlockPos positionsToBreak1 : positionsToBreak) {
if (!canWalkThrough(positionsToBreak1)) {
result.add(positionsToBreak1);
}
}
return result;
}
public ArrayList<BlockPos> toPlace() {
ArrayList<BlockPos> result = new ArrayList<>();
for (BlockPos positionsToPlace1 : positionsToPlace) {
if (!canWalkOn(positionsToPlace1)) {
result.add(positionsToPlace1);
}
}
return result;
}
}