/**
* 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 @ [Jul 31, 2014, 12:59:16 AM (GMT)]
*/
package vazkii.botania.common.item.equipment.bauble;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import baubles.api.BaubleType;
import baubles.api.BaublesApi;
import gnu.trove.list.array.TIntArrayList;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.passive.EntityVillager;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.nbt.NBTTagLong;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.village.MerchantRecipe;
import net.minecraftforge.common.util.Constants;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.wrapper.InvWrapper;
import vazkii.botania.api.BotaniaAPI;
import vazkii.botania.api.item.IBaubleRender;
import vazkii.botania.client.core.handler.MiscellaneousIcons;
import vazkii.botania.client.core.helper.IconHelper;
import vazkii.botania.common.Botania;
import vazkii.botania.common.core.helper.ItemNBTHelper;
import vazkii.botania.common.lib.LibItemNames;
public class ItemItemFinder extends ItemBauble implements IBaubleRender {
private static final String TAG_ENTITY_POSITIONS = "highlightPositionsEnt";
private static final String TAG_BLOCK_POSITIONS = "highlightPositionsBlock1";
public ItemItemFinder() {
super(LibItemNames.ITEM_FINDER);
}
@Override
public void onWornTick(ItemStack stack, EntityLivingBase player) {
super.onWornTick(stack, player);
if(!(player instanceof EntityPlayer))
return;
if(player.world.isRemote)
tickClient(stack, (EntityPlayer) player);
else tickServer(stack, (EntityPlayer) player);
}
protected void tickClient(ItemStack stack, EntityPlayer player) {
if(!Botania.proxy.isTheClientPlayer(player))
return;
NBTTagList blocks = ItemNBTHelper.getList(stack, TAG_BLOCK_POSITIONS, Constants.NBT.TAG_LONG, false);
Botania.proxy.setWispFXDepthTest(false);
for(int i = 0; i < blocks.tagCount(); i++) {
BlockPos pos = BlockPos.fromLong(((NBTTagLong) blocks.get(i)).getLong());
float m = 0.02F;
Botania.proxy.wispFX(pos.getX() + (float) Math.random(), pos.getY() + (float) Math.random(), pos.getZ() + (float) Math.random(), (float) Math.random(), (float) Math.random(), (float) Math.random(), 0.15F + 0.05F * (float) Math.random(), m * (float) (Math.random() - 0.5), m * (float) (Math.random() - 0.5), m * (float) (Math.random() - 0.5));
}
int[] entities = ItemNBTHelper.getIntArray(stack, TAG_ENTITY_POSITIONS);
for(int i : entities) {
Entity e = player.world.getEntityByID(i);
if(e != null && Math.random() < 0.6) {
Botania.proxy.setWispFXDepthTest(Math.random() < 0.6);
Botania.proxy.wispFX(e.posX + (float) (Math.random() * 0.5 - 0.25) * 0.45F, e.posY + e.height, e.posZ + (float) (Math.random() * 0.5 - 0.25) * 0.45F, (float) Math.random(), (float) Math.random(), (float) Math.random(), 0.15F + 0.05F * (float) Math.random(), -0.05F - 0.03F * (float) Math.random());
}
}
Botania.proxy.setWispFXDepthTest(true);
}
protected void tickServer(ItemStack stack, EntityPlayer player) {
TIntArrayList entPosBuilder = new TIntArrayList();
NBTTagList blockPosBuilder = new NBTTagList();
scanForStack(player.getHeldItemMainhand(), player, entPosBuilder, blockPosBuilder);
scanForStack(player.getHeldItemOffhand(), player, entPosBuilder, blockPosBuilder);
int[] currentEnts = entPosBuilder.toArray();
boolean entsEqual = Arrays.equals(currentEnts, ItemNBTHelper.getIntArray(stack, TAG_ENTITY_POSITIONS));
boolean blocksEqual = blockPosBuilder.equals(ItemNBTHelper.getList(stack, TAG_BLOCK_POSITIONS, Constants.NBT.TAG_LONG, false));
if(!entsEqual)
ItemNBTHelper.setIntArray(stack, TAG_ENTITY_POSITIONS, currentEnts);
if(!blocksEqual)
ItemNBTHelper.setList(stack, TAG_BLOCK_POSITIONS, blockPosBuilder);
if(!entsEqual || !blocksEqual)
BotaniaAPI.internalHandler.sendBaubleUpdatePacket(player, 4);
}
private void scanForStack(ItemStack pstack, EntityPlayer player, TIntArrayList entIdBuilder, NBTTagList blockPosBuilder) {
if(!pstack.isEmpty() || player.isSneaking()) {
int range = 24;
List<Entity> entities = player.world.getEntitiesWithinAABB(Entity.class, new AxisAlignedBB(player.posX - range, player.posY - range, player.posZ - range, player.posX + range, player.posY + range, player.posZ + range));
for(Entity e : entities) {
if(e == player)
continue;
if(e.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null) && !(e instanceof EntityPlayer)) {
if(scanInventory(e.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null), pstack))
entIdBuilder.add(e.getEntityId());
} else if(e instanceof EntityItem) {
EntityItem item = (EntityItem) e;
ItemStack istack = item.getEntityItem();
if(player.isSneaking() || istack.isItemEqual(pstack) && ItemStack.areItemStackTagsEqual(istack, pstack))
entIdBuilder.add(item.getEntityId());
} else if(e instanceof IInventory) {
IInventory inv = (IInventory) e;
if(scanInventory(new InvWrapper(inv), pstack))
entIdBuilder.add(e.getEntityId());
} else if(e instanceof EntityPlayer) {
EntityPlayer player_ = (EntityPlayer) e;
IItemHandler playerInv = player.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null);
IItemHandler binv = BaublesApi.getBaublesHandler(player);
if(scanInventory(binv, pstack) || scanInventory(playerInv, pstack))
entIdBuilder.add(player_.getEntityId());
} else if(e instanceof EntityVillager) {
EntityVillager villager = (EntityVillager) e;
ArrayList<MerchantRecipe> recipes = villager.getRecipes(player);
if(!pstack.isEmpty() && recipes != null)
for(MerchantRecipe recipe : recipes)
if(recipe != null && !recipe.isRecipeDisabled() && (equalStacks(pstack, recipe.getItemToBuy()) || equalStacks(pstack, recipe.getItemToSell()))) {
entIdBuilder.add(villager.getEntityId());
break;
}
}
}
if(!pstack.isEmpty()) {
range = 12;
BlockPos pos = new BlockPos(player);
for(BlockPos pos_ : BlockPos.getAllInBoxMutable(pos.add(-range, -range, -range), pos.add(range + 1, range + 1, range + 1))) {
TileEntity tile = player.world.getTileEntity(pos_);
if(tile != null) {
boolean foundCap = false;
for(EnumFacing e : EnumFacing.VALUES) {
if(tile.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, e)
&& scanInventory(tile.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, e), pstack)) {
blockPosBuilder.appendTag(new NBTTagLong(pos_.toLong()));
foundCap = true;
break;
}
}
if(!foundCap && tile instanceof IInventory) {
IInventory inv = (IInventory) tile;
if(scanInventory(new InvWrapper(inv), pstack))
blockPosBuilder.appendTag(new NBTTagLong(pos_.toLong()));
}
}
}
}
}
}
private boolean equalStacks(ItemStack stack1, ItemStack stack2) {
return stack1.isItemEqual(stack2) && ItemStack.areItemStackTagsEqual(stack1, stack2);
}
private boolean scanInventory(IItemHandler inv, ItemStack pstack) {
if(pstack.isEmpty())
return false;
for(int l = 0; l < inv.getSlots(); l++) {
ItemStack istack = inv.getStackInSlot(l);
if(!istack.isEmpty() && equalStacks(istack, pstack))
return true;
}
return false;
}
@Override
public BaubleType getBaubleType(ItemStack arg0) {
return BaubleType.HEAD;
}
@Override
@SideOnly(Side.CLIENT)
public void onPlayerBaubleRender(ItemStack stack, EntityPlayer player, RenderType type, float partialTicks) {
TextureAtlasSprite gemIcon = MiscellaneousIcons.INSTANCE.itemFinderGem;
if(type == RenderType.HEAD) {
float f = gemIcon.getMinU();
float f1 = gemIcon.getMaxU();
float f2 = gemIcon.getMinV();
float f3 = gemIcon.getMaxV();
boolean armor = !player.getItemStackFromSlot(EntityEquipmentSlot.HEAD).isEmpty();
Helper.translateToHeadLevel(player);
Minecraft.getMinecraft().renderEngine.bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE);
GlStateManager.rotate(90F, 0F, 1F, 0F);
GlStateManager.rotate(180F, 1F, 0F, 0F);
GlStateManager.translate(-0.4F, -1.4F, armor ? -0.3F : -0.25F);
GlStateManager.scale(0.75F, 0.75F, 0.75F);
IconHelper.renderIconIn3D(Tessellator.getInstance(), f1, f2, f, f3, gemIcon.getIconWidth(), gemIcon.getIconHeight(), 1F / 16F);
}
}
}