package eiteam.esteemedinnovation.metalcasting.crucible;
import eiteam.esteemedinnovation.api.crucible.CrucibleLiquid;
import eiteam.esteemedinnovation.api.crucible.CrucibleRegistry;
import eiteam.esteemedinnovation.api.wrench.Wrenchable;
import eiteam.esteemedinnovation.commons.EsteemedInnovation;
import eiteam.esteemedinnovation.commons.util.WorldHelper;
import eiteam.esteemedinnovation.heater.BlockSteamHeater;
import eiteam.esteemedinnovation.heater.TileEntitySteamHeater;
import net.minecraft.block.Block;
import net.minecraft.block.BlockHorizontal;
import net.minecraft.block.material.Material;
import net.minecraft.block.properties.PropertyDirection;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.*;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import org.apache.commons.lang3.tuple.ImmutableTriple;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.tuple.Triple;
import static eiteam.esteemedinnovation.metalcasting.MetalcastingModule.HELL_CRUCIBLE;
public class BlockCrucible extends Block implements Wrenchable {
public static final PropertyDirection FACING = BlockHorizontal.FACING;
private static final float PX = (1.0F / 16.0F);
public static final AxisAlignedBB CRUCIBLE_AABB = new AxisAlignedBB(PX, PX, PX, 1F - PX, 1F - PX, 1F - PX);
public static final ResourceLocation LIQUID_ICON_RL = new ResourceLocation(EsteemedInnovation.MOD_ID, "blocks/crucible_liquid");
public BlockCrucible() {
super(Material.ROCK);
setHardness(3.5F);
setDefaultState(blockState.getBaseState().withProperty(FACING, EnumFacing.NORTH));
}
@Override
public EnumBlockRenderType getRenderType(IBlockState state) {
return EnumBlockRenderType.ENTITYBLOCK_ANIMATED;
}
@Override
public boolean isOpaqueCube(IBlockState state) {
return false;
}
@Override
public BlockStateContainer createBlockState() {
return new BlockStateContainer(this, FACING);
}
@Override
public int getMetaFromState(IBlockState state) {
return state.getValue(FACING).getIndex();
}
@Override
public IBlockState getStateFromMeta(int meta) {
EnumFacing dir = EnumFacing.getFront(meta);
if (dir.getAxis() == EnumFacing.Axis.Y) {
dir = EnumFacing.NORTH;
}
return getDefaultState().withProperty(FACING, dir);
}
@Override
public IBlockState withRotation(IBlockState state, Rotation rot) {
return state.withProperty(FACING, rot.rotate(state.getValue(FACING)));
}
@Override
public IBlockState withMirror(IBlockState state, Mirror mirrorIn) {
return state.withRotation(mirrorIn.toRotation(state.getValue(FACING)));
}
@Override
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess world, BlockPos pos) {
return CRUCIBLE_AABB;
}
@Override
public boolean isFullCube(IBlockState state) {
return false;
}
@Override
public boolean hasComparatorInputOverride(IBlockState state) {
return true;
}
@Override
public int getComparatorInputOverride(IBlockState state, World world, BlockPos pos) {
TileEntity te = world.getTileEntity(pos);
if (te != null && te instanceof TileEntityCrucible) {
TileEntityCrucible crucible = (TileEntityCrucible) te;
return crucible.getComparatorOutput();
}
return 0;
}
public boolean isCrucibleHeated(World world, BlockPos pos) {
BlockPos underCruciblePosition = new BlockPos(pos.getX(), pos.getY() - 1, pos.getZ());
IBlockState stateUnderCrucible = world.getBlockState(underCruciblePosition);
TileEntity tileUnderCrucible = world.getTileEntity(underCruciblePosition);
if (this == HELL_CRUCIBLE || stateUnderCrucible.getMaterial() == Material.FIRE ||
stateUnderCrucible.getMaterial() == Material.LAVA) {
return true;
}
if (tileUnderCrucible instanceof TileEntitySteamHeater) {
TileEntitySteamHeater steamHeater = (TileEntitySteamHeater) tileUnderCrucible;
if (world.getBlockState(steamHeater.getPos()).getValue(BlockSteamHeater.FACING) == EnumFacing.UP &&
steamHeater.getSteam() >= TileEntitySteamHeater.CONSUMPTION) {
steamHeater.decrSteam(TileEntitySteamHeater.CONSUMPTION);
return true;
}
}
return false;
}
@Override
public void onEntityCollidedWithBlock(World world, BlockPos pos, IBlockState state, Entity entity) {
if (entity instanceof EntityItem) {
EntityItem item = (EntityItem) entity;
if (isCrucibleHeated(world, pos)) {
Pair<CrucibleLiquid, Integer> output;
if (CrucibleRegistry.liquidRecipes.containsKey(Pair.of(item.getEntityItem().getItem(), item.getEntityItem().getItemDamage()))) {
output = CrucibleRegistry.liquidRecipes.get(Pair.of(item.getEntityItem().getItem(), item.getEntityItem().getItemDamage()));
} else if (CrucibleRegistry.liquidRecipes.containsKey(Pair.of(item.getEntityItem().getItem(), -1))) {
output = CrucibleRegistry.liquidRecipes.get(Pair.of(item.getEntityItem().getItem(), -1));
} else {
return;
}
TileEntityCrucible crucible = (TileEntityCrucible) world.getTileEntity(pos);
int amount = output.getRight();
if (crucible != null) {
// TODO: Waiting for response to MinecraftForge#3092. If it is not accepted, we will have to do
// reflection to get the delayBeforeCanPickup value.
// if (item.delayBeforeCanPickup > 2){
// item.delayBeforeCanPickup = 2;
// } else if (item.delayBeforeCanPickup <= 1) {
ItemStack stack = item.getEntityItem();
ItemStack out = crucible.fillWith(stack, amount, output);
if (crucible.getFill() + amount <= 90) {
// item.delayBeforeCanPickup = 2;
}
if (out.stackSize <= 0) {
entity.setDead();
} else {
item.setEntityItemStack(out);
}
crucible.needsUpdate = true;
// }
}
}
}
}
@Override
public void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack) {
world.setBlockState(pos, state.withProperty(FACING, placer.getHorizontalFacing().getOpposite()));
}
@Override
public boolean hasTileEntity(IBlockState state) {
return true;
}
@Override
public TileEntity createTileEntity(World world, IBlockState state) {
return new TileEntityCrucible();
}
@Override
public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, ItemStack heldItem, EnumFacing side, float hitX, float hitY, float hitZ) {
TileEntityCrucible tile = (TileEntityCrucible) world.getTileEntity(pos);
if (tile == null) {
return false;
}
if (!player.isSneaking() && heldItem == null) {
if (!tile.isTipping()) {
tile.setTipping();
tile.needsUpdate = true;
}
} else if (heldItem != null) {
for (CrucibleLiquid liquid : tile.contents) {
Triple<Item, Integer, CrucibleLiquid> triple = new ImmutableTriple<>(heldItem.getItem(), heldItem.getItemDamage(), liquid);
boolean valid;
if (!CrucibleRegistry.dunkRecipes.containsKey(triple)) {
triple = new ImmutableTriple<>(heldItem.getItem(), -1, liquid);
valid = CrucibleRegistry.dunkRecipes.containsKey(triple);
} else {
valid = true;
}
if (valid) {
Pair<Integer, ItemStack> pair = CrucibleRegistry.dunkRecipes.get(triple);
int needed = pair.getLeft();
ItemStack result = pair.getRight().copy();
if (tile.number.get(liquid) >= needed) {
player.inventory.decrStackSize(player.inventory.currentItem, 1);
int currNum = tile.number.get(liquid);
currNum -= needed;
if (currNum == 0) {
tile.contents.remove(liquid);
}
tile.number.remove(liquid);
tile.number.put(liquid, currNum);
if (!player.inventory.addItemStackToInventory(result)) {
if (!player.worldObj.isRemote) {
player.entityDropItem(result, 0.0F);
}
}
tile.needsUpdate = true;
break;
}
}
}
}
return true;
}
@Override
public boolean onWrench(ItemStack stack, EntityPlayer player, World world, BlockPos pos, EnumHand hand, EnumFacing facing, IBlockState state, float hitX, float hitY, float hitZ) {
if (facing != EnumFacing.DOWN && facing != EnumFacing.UP) {
WorldHelper.rotateProperly(FACING, world, state, pos, facing);
return true;
}
return false;
}
}