package mods.battlegear2.api.core;
import java.io.Closeable;
import java.io.IOException;
import java.util.Collection;
import mods.battlegear2.api.IAllowItem;
import mods.battlegear2.api.IOffhandDual;
import mods.battlegear2.api.shield.IShield;
import mods.battlegear2.api.weapons.IBattlegearWeapon;
import mods.battlegear2.api.weapons.WeaponRegistry;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.enchantment.EnchantmentThorns;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.IEntityMultiPart;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.attributes.AttributeModifier;
import net.minecraft.entity.boss.EntityDragonPart;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.item.EnumAction;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemBow;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemSword;
import net.minecraft.item.ItemTool;
import net.minecraft.nbt.CompressedStreamTools;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.potion.Potion;
import net.minecraft.stats.AchievementList;
import net.minecraft.stats.StatList;
import net.minecraft.util.DamageSource;
import net.minecraft.util.MathHelper;
import net.minecraft.world.World;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.EventBus;
import net.minecraftforge.event.entity.player.AttackEntityEvent;
import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteArrayDataOutput;
public class BattlegearUtils {
/**
* Event bus to which {@link mods.battlegear2.api.RenderPlayerEventChild} events are post to
*/
public static final EventBus RENDER_BUS = new EventBus();
private static String[] itemBlackListMethodNames;
private static Class[][] itemBlackListMethodParams;
static {
if (World.class.getName().equals("net.minecraft.world.World")) {
itemBlackListMethodNames = new String[]{
"onItemUse",
"onItemRightClick"
};
} else {
itemBlackListMethodNames = new String[]{
BattlegearTranslator.getMapedMethodName("Item", "func_77648_a", "onItemUse"),
BattlegearTranslator.getMapedMethodName("Item", "func_77659_a", "onItemRightClick")
};
}
itemBlackListMethodParams = new Class[][]{
new Class[]{ItemStack.class, EntityPlayer.class, World.class, int.class, int.class, int.class, int.class, float.class, float.class, float.class},
new Class[]{ItemStack.class, World.class, EntityPlayer.class}
};
}
private static boolean[] weapons;
private static boolean[] mainHandDualWeapons;
private static boolean[] offhandDualWeapons;
public static boolean isBlockingWithShield(EntityPlayer player){
//TODO: Use this ?
if(!player.isSneaking()){
return false;
}
ItemStack offhand = ((InventoryPlayerBattle)player.inventory).getCurrentOffhandWeapon();
return offhand != null && offhand.getItem() instanceof IShield;
}
public static boolean isPlayerInBattlemode(EntityPlayer player) {
return ((InventoryPlayerBattle) player.inventory).isBattlemode();
}
public static void setPlayerCurrentItem(EntityPlayer player, ItemStack stack, int offset) {
((InventoryPlayerBattle) (player.inventory)).setInventorySlotContents(player.inventory.currentItem + offset, stack, false);
}
public static void setPlayerCurrentItem(EntityPlayer player, ItemStack stack) {
setPlayerCurrentItem(player, stack, 0);
}
public static boolean isWeapon(ItemStack main) {
if (main.getItem() instanceof IBattlegearWeapon)
return true;
else
return weapons[main.itemID] || WeaponRegistry.isWeapon(main);
}
public static boolean isMainHand(ItemStack main, ItemStack off) {
if(main.getItem() instanceof IAllowItem)
return ((IAllowItem) main.getItem()).allowOffhand(main, off);
else
return mainHandDualWeapons[main.itemID] || WeaponRegistry.isMainHand(main);
}
public static boolean isOffHand(ItemStack off) {
if(off.getItem() instanceof IOffhandDual)
return ((IOffhandDual) off.getItem()).isOffhandHandDual(off);
else if(off.getItem() instanceof IShield || off.getItem() instanceof ItemBlock)
return true;
else
return offhandDualWeapons[off.itemID] || WeaponRegistry.isOffHand(off);
}
public static void scanAndProcessItems() {
weapons = new boolean[Item.itemsList.length];
mainHandDualWeapons = new boolean[Item.itemsList.length];
offhandDualWeapons = new boolean[Item.itemsList.length];
for (int i = 0; i < Item.itemsList.length; i++) {
Item item = Item.itemsList[i];
weapons[i] = false;
mainHandDualWeapons[i] = false;
offhandDualWeapons[i] = false;
if (item != null) {
boolean valid = item.getItemStackLimit() == 1 && item.isDamageable();
if (valid) {
weapons[i] = item instanceof ItemSword ||
item instanceof ItemBow ||
item instanceof ItemTool;
if (weapons[i]) {
//make sure there are no special functions for offhand/mainhand weapons
boolean rightClickFunction = checkForRightClickFunction(item, null);
//only weapons can be placed in offhand
offhandDualWeapons[i] = !(item instanceof ItemTool || item instanceof ItemBow) && !rightClickFunction;
mainHandDualWeapons[i] = !(item instanceof ItemBow) && !rightClickFunction;
}
}
}
}
}
@SuppressWarnings("unchecked")
public static boolean checkForRightClickFunction(Item item, ItemStack stack) {
try {
if (item.getItemUseAction(stack) == EnumAction.block || item.getItemUseAction(stack) == EnumAction.none) {
Class c = item.getClass();
while (!(c.equals(Item.class) || c.equals(ItemTool.class) || c.equals(ItemSword.class))) {
try {
try {
c.getDeclaredMethod(itemBlackListMethodNames[0], itemBlackListMethodParams[0]);
return true;
} catch (NoSuchMethodException ignored) {
}
try {
c.getDeclaredMethod(itemBlackListMethodNames[1], itemBlackListMethodParams[1]);
return true;
} catch (NoSuchMethodException ignored) {
}
} catch (NoClassDefFoundError ignored) {
}
c = c.getSuperclass();
}
return false;
} else {
return true;
}
} catch (NullPointerException e) {
return true;
}
}
public static ItemStack readItemStack(ByteArrayDataInput par0DataInputStream) throws IOException {
ItemStack itemstack = null;
short short1 = par0DataInputStream.readShort();
if (short1 >= 0) {
byte b0 = par0DataInputStream.readByte();
short short2 = par0DataInputStream.readShort();
itemstack = new ItemStack(short1, b0, short2);
itemstack.stackTagCompound = readNBTTagCompound(par0DataInputStream);
}
return itemstack;
}
/**
* Reads a compressed NBTTagCompound from the InputStream
*/
public static NBTTagCompound readNBTTagCompound(ByteArrayDataInput par0DataInputStream) throws IOException {
short short1 = par0DataInputStream.readShort();
if (short1 < 0) {
return null;
} else {
byte[] abyte = new byte[short1];
par0DataInputStream.readFully(abyte);
return CompressedStreamTools.decompress(abyte);
}
}
public static void writeItemStack(ByteArrayDataOutput par1DataOutputStream, ItemStack par0ItemStack) throws IOException {
if (par0ItemStack == null) {
par1DataOutputStream.writeShort(-1);
} else {
par1DataOutputStream.writeShort(par0ItemStack.itemID);
par1DataOutputStream.writeByte(par0ItemStack.stackSize);
par1DataOutputStream.writeShort(par0ItemStack.getItemDamage());
NBTTagCompound nbttagcompound = null;
if (par0ItemStack.getItem().isDamageable() || par0ItemStack.getItem().getShareTag()) {
nbttagcompound = par0ItemStack.stackTagCompound;
}
writeNBTTagCompound(nbttagcompound, par1DataOutputStream);
}
}
protected static void writeNBTTagCompound(NBTTagCompound par0NBTTagCompound, ByteArrayDataOutput par1DataOutputStream) throws IOException {
if (par0NBTTagCompound == null) {
par1DataOutputStream.writeShort(-1);
} else {
byte[] abyte = CompressedStreamTools.compress(par0NBTTagCompound);
par1DataOutputStream.writeShort((short) abyte.length);
par1DataOutputStream.write(abyte);
}
}
public static InventoryPlayer replaceInventory(EntityPlayer entityPlayer) {
return new InventoryPlayerBattle(entityPlayer);
}
public static void attackTargetEntityWithCurrentOffItem(EntityPlayer player, Entity par1Entity)
{
player.inventory.currentItem += InventoryPlayerBattle.WEAPON_SETS;
if (MinecraftForge.EVENT_BUS.post(new AttackEntityEvent(player, par1Entity)))
{
player.inventory.currentItem -= InventoryPlayerBattle.WEAPON_SETS;
return;
}
ItemStack stack = player.getCurrentEquippedItem();
if (stack != null && stack.getItem().onLeftClickEntity(stack, player, par1Entity))
{
player.inventory.currentItem -= InventoryPlayerBattle.WEAPON_SETS;
return;
}
if (par1Entity.canAttackWithItem())
{
if (!par1Entity.hitByEntity(player))
{
float f = 1;
if(stack != null){
Collection map = stack.getAttributeModifiers().get(SharedMonsterAttributes.attackDamage.getAttributeUnlocalizedName());
for(Object ob : map){
if(ob instanceof AttributeModifier){
AttributeModifier am = (AttributeModifier)ob;
if(am.getName().equals("Weapon modifier")){
f += am.getAmount();
}
}
}
}
int i = 0;
float f1 = 0.0F;
if (par1Entity instanceof EntityLivingBase)
{
f1 = EnchantmentHelper.getEnchantmentModifierLiving(player, (EntityLivingBase) par1Entity);
i += EnchantmentHelper.getKnockbackModifier(player, (EntityLivingBase)par1Entity);
}
if (player.isSprinting())
{
++i;
}
if (f > 0.0F || f1 > 0.0F)
{
boolean flag = player.fallDistance > 0.0F && !player.onGround && !player.isOnLadder() && !player.isInWater() && !player.isPotionActive(Potion.blindness) && player.ridingEntity == null && par1Entity instanceof EntityLivingBase;
if (flag && f > 0.0F)
{
f *= 1.5F;
}
f += f1;
boolean flag1 = false;
int j = EnchantmentHelper.getFireAspectModifier(player);
if (par1Entity instanceof EntityLivingBase && j > 0 && !par1Entity.isBurning())
{
flag1 = true;
par1Entity.setFire(1);
}
boolean flag2 = par1Entity.attackEntityFrom(DamageSource.causePlayerDamage(player), f);
if (flag2)
{
if (i > 0)
{
par1Entity.addVelocity((double)(-MathHelper.sin(player.rotationYaw * (float) Math.PI / 180.0F) * (float)i * 0.5F), 0.1D, (double)(MathHelper.cos(player.rotationYaw * (float)Math.PI / 180.0F) * (float)i * 0.5F));
player.motionX *= 0.6D;
player.motionZ *= 0.6D;
player.setSprinting(false);
}
if (flag)
{
player.onCriticalHit(par1Entity);
}
if (f1 > 0.0F)
{
player.onEnchantmentCritical(par1Entity);
}
if (f >= 18.0F)
{
player.triggerAchievement(AchievementList.overkill);
}
player.setLastAttacker(par1Entity);
if (par1Entity instanceof EntityLivingBase)
{
EnchantmentThorns.func_92096_a(player, (EntityLivingBase) par1Entity, player.getRNG());
}
}
ItemStack itemstack = player.getCurrentEquippedItem();
Object object = par1Entity;
if (par1Entity instanceof EntityDragonPart)
{
IEntityMultiPart ientitymultipart = ((EntityDragonPart)par1Entity).entityDragonObj;
if (ientitymultipart != null && ientitymultipart instanceof EntityLivingBase)
{
object = ientitymultipart;
}
}
if (itemstack != null && object instanceof EntityLivingBase)
{
itemstack.hitEntity((EntityLivingBase)object, player);
if (itemstack.stackSize <= 0)
{
player.destroyCurrentEquippedItem();
}
}
if (par1Entity instanceof EntityLivingBase)
{
player.addStat(StatList.damageDealtStat, Math.round(f * 10.0F));
if (j > 0 && flag2)
{
par1Entity.setFire(j * 4);
}
else if (flag1)
{
par1Entity.extinguish();
}
}
player.addExhaustion(0.3F);
}
}
}
player.inventory.currentItem -= InventoryPlayerBattle.WEAPON_SETS;
}
public static void closeStream(Closeable c){
try{
if(c != null){
c.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}