2018-08-01 11:34:35 -04:00

212 lines
7.7 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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();
}