212 lines
7.7 KiB
Java
Raw Normal View History

2018-08-01 11:34:35 -04:00
/*
* 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 baritone.util.Out;
import baritone.util.ToolSet;
import net.minecraft.block.Block;
import net.minecraft.block.BlockCactus;
import net.minecraft.block.BlockFire;
import net.minecraft.block.BlockLadder;
import net.minecraft.block.BlockLilyPad;
import net.minecraft.block.BlockLiquid;
import net.minecraft.block.BlockVine;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.util.math.BlockPos;
/**
*
* @author leijurv
*/
public abstract class Action {
//These costs are measured roughly in ticks btw
public static final double WALK_ONE_BLOCK_COST = 20 / 4.317;
public static final double WALK_ONE_IN_WATER_COST = 20 / 2.2;
public static final double JUMP_ONE_BLOCK_COST = 5.72854;//see below calculation for fall. 1.25 blocks
public static final double LADDER_UP_ONE_COST = 20 / 2.35;
public static final double LADDER_DOWN_ONE_COST = 20 / 3;
public static final double SNEAK_ONE_BLOCK_COST = 20 / 1.3;
public static final double SPRINT_ONE_BLOCK_COST = 20 / 5.612;
/**
* Doesn't include walking forwards, just the falling
*
* Based on a sketchy formula from minecraftwiki
*
* d(t) = 3.92 × (99 - 49.50×(0.98^t+1) - t)
*
* Solved in mathematica
*/
public static final double FALL_ONE_BLOCK_COST = 5.11354;
public static final double FALL_TWO_BLOCK_COST = 7.28283;
public static final double FALL_THREE_BLOCK_COST = 8.96862;
/**
* It doesn't actually take ten ticks to place a block, this cost is so high
* because we want to generally conserve blocks which might be limited
*/
public static final double PLACE_ONE_BLOCK_COST = 20;
/**
* Add this to the cost of breaking any block. The cost of breaking any
* block is calculated as the number of ticks that block takes to break with
* the tools you have. You add this because there's always a little overhead
* (e.g. looking at the block)
*/
public static final double BREAK_ONE_BLOCK_ADD = 4;
public static final double COST_INF = 1000000;
public final BlockPos from;
public final BlockPos to;
private Double cost;
public boolean finished = false;
protected Action(BlockPos from, BlockPos to) {
this.from = from;
this.to = to;
this.cost = null;
}
/**
* Get the cost. It's cached
*
* @param ts
* @return
*/
public double cost(ToolSet ts) {
if (cost == null) {
cost = calculateCost0(ts == null ? new ToolSet() : ts);
}
if (cost < 1) {
Out.log("Bad cost " + this + " " + cost);
}
return cost;
}
public double calculateCost0(ToolSet ts) {
if (!(this instanceof ActionPillar) && !(this instanceof ActionBridge) && !(this instanceof ActionFall)) {
Block fromDown = Minecraft.getMinecraft().world.getBlockState(from.down()).getBlock();
if (fromDown instanceof BlockLadder || fromDown instanceof BlockVine) {
return COST_INF;
}
}
return calculateCost(ts);
}
protected abstract double calculateCost(ToolSet ts);
static Block waterFlowing = Block.getBlockById(8);
static Block waterStill = Block.getBlockById(9);
static Block lavaFlowing = Block.getBlockById(10);
static Block lavaStill = Block.getBlockById(11);
/**
* Is this block water? Includes both still and flowing
*
* @param b
* @return
*/
public static boolean isWater(Block b) {
return waterFlowing.equals(b) || waterStill.equals(b);
}
public static boolean isWater(BlockPos bp) {
return isWater(Minecraft.getMinecraft().world.getBlockState(bp).getBlock());
}
public static boolean isLiquid(Block b) {
return b instanceof BlockLiquid;
//return b != null && (waterFlowing.equals(b) || waterStill.equals(b) || lavaFlowing.equals(b) || lavaStill.equals(b));
}
public static boolean isFlowing(BlockPos pos, IBlockState state) {
Block b = state.getBlock();
Material m = b.getMaterial(state);
if (b instanceof BlockLiquid) {
throw new UnsupportedOperationException("TODO");
//return BlockLiquid.getFlow(Minecraft.getMinecraft().world, pos, state) != -1000.0D;
}
return false;
}
public static boolean isLava(Block b) {
return lavaFlowing.equals(b) || lavaStill.equals(b);
}
public static boolean isLiquid(BlockPos p) {
return isLiquid(Minecraft.getMinecraft().world.getBlockState(p).getBlock());
}
public static boolean avoidBreaking(BlockPos pos) {
Block b = Minecraft.getMinecraft().world.getBlockState(pos).getBlock();
Block below = Minecraft.getMinecraft().world.getBlockState(new BlockPos(pos.getX(), pos.getY() - 1, pos.getZ())).getBlock();
return Block.getBlockFromName("minecraft:ice").equals(b)//ice becomes water, and water can mess up the path
|| isLiquid(new BlockPos(pos.getX(), pos.getY() + 1, pos.getZ()))//don't break anything touching liquid on any side
|| isLiquid(new BlockPos(pos.getX() + 1, pos.getY(), pos.getZ()))
|| isLiquid(new BlockPos(pos.getX() - 1, pos.getY(), pos.getZ()))
|| isLiquid(new BlockPos(pos.getX(), pos.getY(), pos.getZ() + 1))
|| isLiquid(new BlockPos(pos.getX(), pos.getY(), pos.getZ() - 1))
|| (!(b instanceof BlockLilyPad && isWater(below)) && isLiquid(below));//if it's a lilypad above water, it's ok to break, otherwise don't break if its liquid
}
/**
* Can I walk through this block? e.g. air, saplings, torches, etc
*
* @param pos
* @return
*/
public static boolean canWalkThrough(BlockPos pos) {
IBlockState state = Minecraft.getMinecraft().world.getBlockState(pos);
Block block = state.getBlock();
if (block instanceof BlockLilyPad || block instanceof BlockFire) {//you can't actually walk through a lilypad from the side, and you shouldn't walk through fire
return false;
}
if (isFlowing(pos, state)) {
return false;//don't walk through flowing liquids
}
if (isLiquid(pos.up())) {
return false;//you could drown
}
return block.isPassable(Minecraft.getMinecraft().world, pos);
}
public static boolean avoidWalkingInto(BlockPos pos) {
Block block = Minecraft.getMinecraft().world.getBlockState(pos).getBlock();
if (isLava(block)) {
return true;
}
if (block instanceof BlockCactus) {
return true;
}
return block instanceof BlockFire;
}
/**
* Can I walk on this block without anything weird happening like me falling
* through? Includes water because we know that we automatically jump on
* lava
*
* @param pos
* @return
*/
public static boolean canWalkOn(BlockPos pos) {
IBlockState state = Minecraft.getMinecraft().world.getBlockState(pos);
Block block = state.getBlock();
if (block instanceof BlockLadder || block instanceof BlockVine) {
return true;
}
if (isWater(block)) {
return isWater(pos.up());//you can only walk on water if there is water above it
}
return block.isBlockNormalCube(state) && !isLava(block);
}
/**
* Tick this action
*
* @return is it done
*/
public abstract boolean tick();
}