/**
* This class was created by <Vazkii>. It's distributed as
* part of the Botania Mod. Get the Source Code in github:
* https://github.com/Vazkii/Botania
*
* Botania is Open Source and distributed under the
* Botania License: http://botaniamod.net/license.php
*
* File Created @ [26/10/2016, 18:23:11 (GMT)]
*/
package vazkii.botania.common.item;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.resources.I18n;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.init.SoundEvents;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResult;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.EnumFacing.Axis;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import vazkii.botania.api.item.IBlockProvider;
import vazkii.botania.api.mana.ManaItemHandler;
import vazkii.botania.client.core.handler.ItemsRemainingRenderHandler;
import vazkii.botania.common.core.helper.ItemNBTHelper;
import vazkii.botania.common.item.equipment.tool.ToolCommons;
import vazkii.botania.common.item.rod.ItemExchangeRod;
import vazkii.botania.common.lib.LibItemNames;
import javax.annotation.Nonnull;
public class ItemAstrolabe extends ItemMod {
private static final String TAG_BLOCK_NAME = "blockName";
private static final String TAG_BLOCK_META = "blockMeta";
private static final String TAG_SIZE = "size";
public ItemAstrolabe() {
super(LibItemNames.ASTROLABE);
setMaxStackSize(1);
}
@Nonnull
@Override
public EnumActionResult onItemUse(EntityPlayer playerIn, World worldIn, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) {
ItemStack stack = playerIn.getHeldItem(hand);
IBlockState state = worldIn.getBlockState(pos);
Block block = state.getBlock();
int meta = block.getMetaFromState(state);
if(playerIn.isSneaking()) {
if(setBlock(stack, block, meta)) {
displayRemainderCounter(playerIn, stack);
return EnumActionResult.SUCCESS;
}
} else {
boolean did = placeAllBlocks(stack, playerIn);
if(did) {
displayRemainderCounter(playerIn, stack);
if(!worldIn.isRemote)
playerIn.swingArm(hand);
}
return did ? EnumActionResult.SUCCESS : EnumActionResult.FAIL;
}
return EnumActionResult.PASS;
}
@Nonnull
@Override
public ActionResult<ItemStack> onItemRightClick(World worldIn, EntityPlayer playerIn, @Nonnull EnumHand hand) {
ItemStack stack = playerIn.getHeldItem(hand);
if(playerIn.isSneaking()) {
int size = getSize(stack);
int newSize = size == 11 ? 3 : size + 2;
setSize(stack, newSize);
ItemsRemainingRenderHandler.set(stack, newSize + "x" + newSize);
worldIn.playSound(playerIn, playerIn.getPosition(), SoundEvents.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.PLAYERS, 0.5F, 1F);
return ActionResult.newResult(EnumActionResult.SUCCESS, stack);
}
return ActionResult.newResult(EnumActionResult.PASS, stack);
}
public boolean placeAllBlocks(ItemStack stack, EntityPlayer player) {
BlockPos[] blocksToPlace = getBlocksToPlace(stack, player);
if(!hasBlocks(stack, player, blocksToPlace))
return false;
int size = getSize(stack);
int cost = size * 320;
if(!ManaItemHandler.requestManaExact(stack, player, cost, false))
return false;
ItemStack stackToPlace = new ItemStack(getBlock(stack), 1, getBlockMeta(stack));
for(BlockPos coords : blocksToPlace)
placeBlockAndConsume(player, stack, stackToPlace, coords);
ManaItemHandler.requestManaExact(stack, player, cost, true);
return true;
}
private void placeBlockAndConsume(EntityPlayer player, ItemStack requestor, ItemStack blockToPlace, BlockPos coords) {
if(blockToPlace.getItem() == null)
return;
Block block = Block.getBlockFromItem(blockToPlace.getItem());
int meta = blockToPlace.getItemDamage();
IBlockState state = block.getStateFromMeta(meta);
player.world.setBlockState(coords, state, 1 | 2);
player.world.playEvent(2001, coords, Block.getStateId(state));
if(player.capabilities.isCreativeMode)
return;
List<ItemStack> stacksToCheck = new ArrayList<>();
for(int i = 0; i < player.inventory.getSizeInventory(); i++) {
ItemStack stackInSlot = player.inventory.getStackInSlot(i);
if(!stackInSlot.isEmpty() && stackInSlot.getItem() == blockToPlace.getItem() && stackInSlot.getItemDamage() == blockToPlace.getItemDamage()) {
stackInSlot.shrink(1);
return;
}
if (!stackInSlot.isEmpty() && stackInSlot.getItem() instanceof IBlockProvider)
stacksToCheck.add(stackInSlot);
}
for(ItemStack providerStack : stacksToCheck) {
IBlockProvider prov = (IBlockProvider) providerStack.getItem();
if(prov.provideBlock(player, requestor, providerStack, block, meta, false)) {
prov.provideBlock(player, requestor, providerStack, block, meta, true);
return;
}
}
}
public static boolean hasBlocks(ItemStack stack, EntityPlayer player, BlockPos[] blocks) {
if (player.capabilities.isCreativeMode)
return true;
Block block = getBlock(stack);
int meta = getBlockMeta(stack);
ItemStack reqStack = new ItemStack(block, 1, meta);
int required = blocks.length;
int current = 0;
List<ItemStack> stacksToCheck = new ArrayList<>();
for (int i = 0; i < player.inventory.getSizeInventory(); i++) {
ItemStack stackInSlot = player.inventory.getStackInSlot(i);
if (!stackInSlot.isEmpty() && stackInSlot.getItem() == reqStack.getItem() && stackInSlot.getItemDamage() == reqStack.getItemDamage()) {
current += stackInSlot.getCount();
if (current >= required)
return true;
}
if(!stackInSlot.isEmpty() && stackInSlot.getItem() instanceof IBlockProvider)
stacksToCheck.add(stackInSlot);
}
for(ItemStack providerStack : stacksToCheck) {
IBlockProvider prov = (IBlockProvider) providerStack.getItem();
int count = prov.getBlockCount(player, stack, providerStack, block, meta);
if(count == -1)
return true;
current += count;
if(current >= required)
return true;
}
return false;
}
public static BlockPos[] getBlocksToPlace(ItemStack stack, EntityPlayer player) {
List<BlockPos> coords = new ArrayList<>();
RayTraceResult pos = ToolCommons.raytraceFromEntity(player.world, player, true, 5);
if(pos != null) {
BlockPos bpos = pos.getBlockPos();
IBlockState state = player.world.getBlockState(bpos);
Block block = state.getBlock();
if(block != null && block.isReplaceable(player.world, bpos))
bpos = bpos.down();;
int rotation = MathHelper.floor(player.rotationYaw * 4F / 360F + 0.5D) & 3;
int range = (getSize(stack) ^ 1) / 2;
EnumFacing dir = pos.sideHit;
EnumFacing rotationDir = EnumFacing.fromAngle(player.rotationYaw);
boolean pitchedVertically = player.rotationPitch > 70 || player.rotationPitch < -70;
boolean axisX = rotationDir.getAxis() == Axis.X;
boolean axisZ = rotationDir.getAxis() == Axis.Z;
int xOff, yOff, zOff;
xOff = axisZ || pitchedVertically ? range : 0;
yOff = pitchedVertically ? 0 : range;
zOff = axisX || pitchedVertically ? range : 0;
for(int x = -xOff; x < xOff + 1; x++)
for(int y = 0; y < yOff * 2 + 1; y++) {
for(int z = -zOff; z < zOff + 1; z++) {
int xp = bpos.getX() + x + dir.getFrontOffsetX();
int yp = bpos.getY() + y + dir.getFrontOffsetY();
int zp = bpos.getZ() + z + dir.getFrontOffsetZ();
BlockPos newPos = new BlockPos(xp, yp, zp);
IBlockState state1 = player.world.getBlockState(newPos);
Block block1 = state1.getBlock();
if(block1 == null || block1.isAir(state1, player.world, newPos) || block1.isReplaceable(player.world, newPos))
coords.add(new BlockPos(xp, yp, zp));
}
}
}
return coords.toArray(new BlockPos[coords.size()]);
}
public void displayRemainderCounter(EntityPlayer player, ItemStack stack) {
Block block = getBlock(stack);
int meta = getBlockMeta(stack);
int count = ItemExchangeRod.getInventoryItemCount(player, stack, block, meta);
if(!player.world.isRemote)
ItemsRemainingRenderHandler.set(new ItemStack(block, 1, meta), count);
}
private boolean setBlock(ItemStack stack, Block block, int meta) {
if(Item.getItemFromBlock(block) != Items.AIR) {
ItemNBTHelper.setString(stack, TAG_BLOCK_NAME, Block.REGISTRY.getNameForObject(block).toString());
ItemNBTHelper.setInt(stack, TAG_BLOCK_META, meta);
return true;
}
return false;
}
private static void setSize(ItemStack stack, int size) {
ItemNBTHelper.setInt(stack, TAG_SIZE, size | 1);
}
public static int getSize(ItemStack stack) {
return ItemNBTHelper.getInt(stack, TAG_SIZE, 3) | 1;
}
public static Block getBlock(ItemStack stack) {
Block block = Block.getBlockFromName(getBlockName(stack));
if(block == null)
return Blocks.AIR;
return block;
}
public static String getBlockName(ItemStack stack) {
return ItemNBTHelper.getString(stack, TAG_BLOCK_NAME, "");
}
public static int getBlockMeta(ItemStack stack) {
return ItemNBTHelper.getInt(stack, TAG_BLOCK_META, 0);
}
@Override
@SideOnly(Side.CLIENT)
public void addInformation(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, List par3List, boolean par4) {
Block block = getBlock(par1ItemStack);
int size = getSize(par1ItemStack);
par3List.add(size + " x " + size);
if (block != null && block != Blocks.AIR)
par3List.add(new ItemStack(block, 1, getBlockMeta(par1ItemStack)).getDisplayName());
}
}