package minefantasy.entity;
import java.util.Iterator;
import java.util.List;
import com.google.common.io.ByteArrayDataInput;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.network.PacketDispatcher;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import minefantasy.MineFantasyBase;
import minefantasy.api.cooking.IHeatSource;
import minefantasy.api.hound.*;
import minefantasy.api.tactic.ISpecialSenses;
import minefantasy.block.special.BlockDogBowl;
import minefantasy.block.BlockListMF;
import minefantasy.block.tileentity.TileEntityDogBowl;
import minefantasy.entity.ai.hound.*;
import minefantasy.item.ItemArmourMFOld;
import minefantasy.item.ItemBandage;
import minefantasy.item.ItemListMF;
import minefantasy.item.ItemPetChange;
import minefantasy.item.MedievalArmourMaterial;
import minefantasy.system.cfg;
import minefantasy.system.data_minefantasy;
import minefantasy.system.network.PacketManagerMF;
import minefantasy.system.network.PacketUserMF;
import net.minecraft.block.Block;
import net.minecraft.block.BlockColored;
import net.minecraft.block.material.Material;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.enchantment.EnchantmentThorns;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityAgeable;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.EntityAIAttackOnCollide;
import net.minecraft.entity.ai.EntityAIFollowOwner;
import net.minecraft.entity.ai.EntityAIHurtByTarget;
import net.minecraft.entity.ai.EntityAILeapAtTarget;
import net.minecraft.entity.ai.EntityAILookIdle;
import net.minecraft.entity.ai.EntityAIMate;
import net.minecraft.entity.ai.EntityAIOwnerHurtByTarget;
import net.minecraft.entity.ai.EntityAIOwnerHurtTarget;
import net.minecraft.entity.ai.EntityAISwimming;
import net.minecraft.entity.ai.EntityAITargetNonTamed;
import net.minecraft.entity.ai.EntityAITempt;
import net.minecraft.entity.ai.EntityAIWander;
import net.minecraft.entity.ai.EntityAIWatchClosest;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.monster.IMob;
import net.minecraft.entity.passive.EntityAnimal;
import net.minecraft.entity.passive.EntitySheep;
import net.minecraft.entity.passive.EntityTameable;
import net.minecraft.entity.passive.EntityVillager;
import net.minecraft.entity.passive.EntityWolf;
import net.minecraft.entity.passive.IAnimals;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.projectile.EntityArrow;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.InventoryBasic;
import net.minecraft.item.EnumArmorMaterial;
import net.minecraft.item.Item;
import net.minecraft.item.ItemArmor;
import net.minecraft.item.ItemFood;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemSword;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.network.packet.Packet;
import net.minecraft.pathfinding.PathEntity;
import net.minecraft.potion.Potion;
import net.minecraft.potion.PotionEffect;
import net.minecraft.server.MinecraftServer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.DamageSource;
import net.minecraft.util.MathHelper;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;
/*
* Compared to Mobs...
* Drake: Level 15
* Minotaur: Level 20
* Knight: Level 20
* Basilisk:
* Dragon
*
* EntityWolf
*/
public class EntityHound extends EntityTameable
implements PacketUserMF, IInventory, INameableEntity, ISpecialSenses, ISyncedInventory
{
public int invertSpots = -1;
private float trust = 0.0F;
private int ID;
/**
* This is just used for the Gui Screen to remember if the command tab is open
* It resets on loading
*/
public boolean showCommands = false;
private float field_70926_e;
private float field_70924_f;
/** true is the wolf is wet else false */
private boolean isShaking;
private boolean field_70928_h;
/**
* This time increases while wolf is shaking and emitting water particles.
*/
private float timeWolfIsShaking;
private float prevTimeWolfIsShaking;
public int eatAnimation;
public float jawMove;
private int chewTimer;
private float saturationLevel;
private final int IdBase = 18;
private int timeUntilSit;
//OTHER OPTIONS//
public boolean attackMob;
public boolean attackAnimal;
public boolean attackPlayer;
public boolean attackDefense = true;
public boolean fightPvp = true;
public boolean leapAttack;
public boolean pickupItems;
public boolean boostStep;
public int strength;
public int stamina;
public int endurance;
public int xp;
public int xpMax = 80;
public int level = 1;
public int AtPoints;
/**
* The position the hound is told to stay at
*/
private double[] stayPos = new double[3];
/**
* The position the hound can teleport to
*/
private double[] homePos = new double[3];
/**
* Slot 0 = helmet, 1 = armour
*/
private ItemStack[] armour;
public InventoryHoundPack pack = new InventoryHoundPack("Pack Hound", true, 72);
private int lastEaten;
public EntityHound(World world)
{
super(world);
ID = rand.nextInt(100000000)+1;
setHome(world.getSpawnPoint().posX, world.getSpawnPoint().posY, world.getSpawnPoint().posZ);
setStats();
armour = new ItemStack[2];
this.setSize(0.6F, 0.8F);
getNavigator().setAvoidsWater(true);
this.tasks.addTask(1, new EntityAISwimming(this));
this.tasks.addTask(3, new EntityAILeapAtTargetHound(this, 0.4F));
this.tasks.addTask(4, new EntityAIAttackOnCollide(this, 1.0F, false));
this.tasks.addTask(5, new EntityAIFollowHound(this, 1.0F, 2.0F, 4.0F));
this.tasks.addTask(6, new EntityAIMate(this, 1.0F));
this.tasks.addTask(7, new EntityAIWanderHound(this, 1.0F));
this.tasks.addTask(8, new EntityAIBegHound(this, 8.0F));
this.tasks.addTask(9, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F));
this.tasks.addTask(9, new EntityAILookIdle(this));
this.tasks.addTask(3, new EntityAITemptHound(this, 0.75F, false));
//Defend Self
this.targetTasks.addTask(3, new EntityAIDefendHound(this, true));
//Defend Owner
this.targetTasks.addTask(1, new EntityAIDefendOwnerHound(this));
this.targetTasks.addTask(2, new EntityAIFightForHound(this));
//Attack Entities
this.targetTasks.addTask(2, new EntityAIHoundAttackMonster(this, IMob.class, 0, true));
this.targetTasks.addTask(2, new EntityAIHoundAttackAnimal(this, IAnimals.class, 0, true));
this.targetTasks.addTask(2, new EntityAIHoundAttackPlayer(this, EntityPlayer.class, 0, true));
this.targetTasks.addTask(4, new EntityAITargetPack(this, EntityAnimal.class, 200, true));
}
@Override
protected void applyEntityAttributes()
{
super.applyEntityAttributes();
this.getEntityAttribute(SharedMonsterAttributes.followRange).setAttribute(32.0D);
this.getEntityAttribute(SharedMonsterAttributes.movementSpeed).setAttribute(0.35D);
this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setAttribute(30.0F);
}
/**
* Returns true if the newer Entity AI code should be run
*/
public boolean isAIEnabled()
{
return true;
}
/**
* Sets the active target the Task system uses for tracking
*/
@Override
public void setAttackTarget(EntityLivingBase target)
{
if(isTamed() && getOwner() != null && getOwner() == target)
{
return;
}
if(isTamed() && target != null && target instanceof EntityPlayer)
{
if(!fightPvp && isTamed())
{
return;
}
}
super.setAttackTarget(target);
}
@Override
protected void entityInit()
{
super.entityInit();
this.dataWatcher.addObject(IdBase+1, new Byte((byte)0));//ENTITY STATE
this.dataWatcher.addObject(IdBase+2, new Byte((byte)BlockColored.getBlockFromDye(1)));//COLLAR
this.dataWatcher.addObject(IdBase+3, new Integer(-1));//BREED
this.dataWatcher.addObject(IdBase+4, "");//COMMAND
this.dataWatcher.addObject(IdBase+5, (byte)0);//STAND
this.dataWatcher.addObject(IdBase+6, new Float(20F));//Hunger
}
/**
* Plays step sound at given x, y, z for the entity
*/
@Override
@SideOnly(Side.CLIENT)
protected void playStepSound(int x, int y, int z, int id)
{
this.playSound("mob.wolf.step", 0.15F, 1.0F);
if(getArmourSpeedBuff() < 0)
{
playSound("mob.irongolem.throw", Math.min(2.5F, -getArmourSpeedBuff()), 1.0F);
}
}
/**
* (abstract) Protected helper method to write subclass entity data to NBT.
*/
public void writeEntityToNBT(NBTTagCompound nbt)
{
super.writeEntityToNBT(nbt);
nbt.setFloat("Domestic", trust);
nbt.setBoolean("Angry", this.isAngry());
nbt.setByte("CollarColour", (byte)this.getCollarColour());
nbt.setInteger("breed", getBreedInt());
nbt.setString("Command", getCommand());
nbt.setInteger("NoSit", timeUntilSit);
nbt.setInteger("LastEat", lastEaten);
nbt.setInteger("InvertSpots", invertSpots);
nbt.setInteger("houndID", ID);
nbt.setDouble("StayX", stayPos[0]);
nbt.setDouble("StayY", stayPos[1]);
nbt.setDouble("StayZ", stayPos[2]);
nbt.setDouble("HomeX", homePos[0]);
nbt.setDouble("HomeY", homePos[1]);
nbt.setDouble("HomeZ", homePos[2]);
nbt.setBoolean("Attack Mobs", attackMob);
nbt.setBoolean("Attack Animals", attackAnimal);
nbt.setBoolean("Attack Players", attackPlayer);
nbt.setBoolean("Defend Player", attackDefense);
nbt.setBoolean("Enable PvP", fightPvp);
nbt.setBoolean("LeapAttack", leapAttack);
nbt.setBoolean("ItemPickup", pickupItems);
nbt.setBoolean("Boost", boostStep);
nbt.setInteger("Strength", strength);
nbt.setInteger("Stamina", stamina);
nbt.setInteger("Endurance", endurance);
nbt.setFloat("Hunger", getHunger());
nbt.setInteger("XP", xp);
nbt.setInteger("XPMax", xpMax);
nbt.setInteger("Level", level);
nbt.setInteger("AttPoints", AtPoints);
NBTTagList list = new NBTTagList();
for (int c = 0; c < this.armour.length; ++c)
{
if (this.armour[c] != null)
{
NBTTagCompound var4 = new NBTTagCompound();
var4.setByte("Slot", (byte)c);
this.armour[c].writeToNBT(var4);
list.appendTag(var4);
}
}
nbt.setTag("Items", list);
NBTTagList list2 = new NBTTagList();
for (int c = 0; c < pack.getSizeInventory(); ++c)
{
if (pack.getStackInSlot(c) != null)
{
NBTTagCompound var4 = new NBTTagCompound();
var4.setByte("Slot", (byte)c);
pack.getStackInSlot(c).writeToNBT(var4);
list2.appendTag(var4);
}
}
nbt.setTag("Pack", list2);
}
/**
* (abstract) Protected helper method to read subclass entity data from NBT.
*/
public void readEntityFromNBT(NBTTagCompound nbt)
{
super.readEntityFromNBT(nbt);
trust = nbt.getFloat("Domestic");
this.setAngry(nbt.getBoolean("Angry"));
if(nbt.hasKey("houndID"))
ID = nbt.getInteger("houndID");
timeUntilSit = nbt.getInteger("NoSit");
lastEaten = nbt.getInteger("LastEat");
invertSpots = nbt.getInteger("InvertSpots");
stayPos[0] = nbt.getDouble("StayX");
stayPos[1] = nbt.getDouble("StayY");
stayPos[2] = nbt.getDouble("StayZ");
homePos[0] = nbt.getDouble("HomeX");
homePos[1] = nbt.getDouble("HomeY");
homePos[2] = nbt.getDouble("HomeZ");
if (nbt.hasKey("CollarColour"))
{
this.setCollarColour(nbt.getByte("CollarColour"));
}
setBreedInt(nbt.getInteger("breed"));
if (getBreedInt() <= -1) {
setRandomBreed();
}
setCommand(nbt.getString("Command"));
attackMob = nbt.getBoolean("Attack Mobs");
attackAnimal = nbt.getBoolean("Attack Animals");
attackPlayer = nbt.getBoolean("Attack Players");
attackDefense = nbt.getBoolean("Defend Player");
fightPvp = nbt.getBoolean("Enable PvP");
leapAttack = nbt.getBoolean("LeapAttack");
pickupItems = nbt.getBoolean("ItemPickup");
boostStep = nbt.getBoolean("Boost");
strength = nbt.getInteger("Strength");
stamina = nbt.getInteger("Stamina");
endurance = nbt.getInteger("Endurance");
setHunger(nbt.getFloat("Hunger"));
xp = nbt.getInteger("XP");
xpMax = nbt.getInteger("XPMax");
level = nbt.getInteger("Level");
AtPoints = nbt.getInteger("AttPoints");
NBTTagList var2 = nbt.getTagList("Items");
this.armour = new ItemStack[this.getSizeInventory()];
for (int var3 = 0; var3 < var2.tagCount(); ++var3)
{
NBTTagCompound var4 = (NBTTagCompound)var2.tagAt(var3);
byte var5 = var4.getByte("Slot");
if (var5 >= 0 && var5 < this.armour.length)
{
this.armour[var5] = ItemStack.loadItemStackFromNBT(var4);
}
}
NBTTagList var6 = nbt.getTagList("Pack");
for (int var3 = 0; var3 < var6.tagCount(); ++var3)
{
NBTTagCompound var4 = (NBTTagCompound)var6.tagAt(var3);
byte var5 = var4.getByte("Slot");
if (var5 >= 0 && var5 < pack.getSizeInventory())
{
pack.setInventorySlotContents(var5, ItemStack.loadItemStackFromNBT(var4));
}
}
}
public int getAvailableRows()
{
if(armour[1] != null)
{
if(armour[1].getItem() != null)
{
if(armour[1].getItem() instanceof ItemHoundPack)
{
return ((ItemHoundPack)armour[1].getItem()).getAvalibleRows();
}
}
}
return 0;
}
@Override
public void setDead()
{
super.setDead();
if(!worldObj.isRemote)
{
for(int a = 0; a < pack.getSizeInventory(); a ++)
{
if(pack.getStackInSlot(a) != null)
{
this.entityDropItem(pack.getStackInSlot(a), 1.0F);
pack.setInventorySlotContents(a, null);
}
}
for(int a = 0; a < armour.length; a ++)
{
if(armour[a] != null)
{
this.entityDropItem(armour[a], 1.0F);
armour[a] = null;
}
}
}
super.setDead();
}
/**
* Determines if an entity can be despawned, used on idle far away entities
*/
protected boolean canDespawn()
{
return false;
}
/**
* Returns the sound this mob makes while it's alive.
*/
protected String getLivingSound()
{
if(getHunger() < getLowHunger() || getHealth() < (isChild() ? 3 : 5))
{
return "mob.wolf.whine";
}
if(isAngry())
{
return "mob.wolf.growl";
}
if(rand.nextInt(3) == 0)
{
return "mob.wolf.panting";
}
return "mob.wolf.bark";
}
/**
* Returns the sound this mob makes when it is hurt.
*/
protected String getHurtSound()
{
return "mob.wolf.hurt";
}
/**
* Returns the sound this mob makes on death.
*/
protected String getDeathSound()
{
return "mob.wolf.death";
}
/**
* Returns the volume for the sounds this mob makes.
*/
protected float getSoundVolume()
{
return 0.4F;
}
/**
* Returns the item ID for the item the mob drops on death.
*/
@Override
protected void dropFewItems(boolean pKill, int looting)
{
for(int a = 0; a < 1 + rand.nextInt(1 + looting); a ++)
{
this.entityDropItem(ItemListMF.component(ItemListMF.hideHound), 1.0F);
}
}
/**
* Called frequently so the entity can update its state every tick as required. For example, zombies and skeletons
* use this to react to sunlight and start to burn.
*/
public void onLivingUpdate()
{
super.onLivingUpdate();
if(!worldObj.isRemote)
{
//BOOST
if(ticksExisted % 40 == 0)
{
stepHeight = shouldBoost() ? 1.0F : 0.5F;
}
float spd = this.getSpeedModifier();
motionX *= spd;
motionZ *= spd;
/**
* Healing
*/
if(canHeal() && ticksExisted % 100 == 0)
{
if(getHealth() < getMaxHealth())
{
heal(1);
}
}
/**
* Hungry
*/
if(getHunger() > 0 && ticksExisted % getHungerDecay() == 0 && cfg.hungryHound)
{
if(isTamed() && getOwner() != null && getHunger() > 0)
{
float exhaust = getExhaustion();
if(saturationLevel >= exhaust)
{
saturationLevel -= exhaust;
}
else
{
if(saturationLevel > 0)
{
exhaust -= saturationLevel;
}
saturationLevel = 0;
setHunger(getHunger()-exhaust);
}
}
}
if(ticksExisted % 20 == 0)
{
if(getHunger() <= 0 && getHealth() > getStarveLethality())
{
this.attackEntityFrom(DamageSource.starve, 1);
}
if(getHunger() < 0)
{
setHunger(0);
}
if(shouldPickupItems())
{
searchForItems(false);
}
}
if(ticksExisted % 600 == 0)
{
if(getAttackTarget() != null)
{
if(!this.canEntityBeSeen(getAttackTarget()))
{
setAttackTarget(null);
}
}
}
if(isTamed() && getHunger() < (getMaxHunger()-1F))
{
tryToEat();
}
if(lastEaten > 0)lastEaten --;
if(!isTamed() && ticksExisted % 200 == 0)
{
inPack = searchForPack();
}
if(isAngry() && getAttackTarget() == null && rand.nextInt(200) == 0)
{
setAngry(false);
}
if(!isTamed() && !inPack() && !isAngry() && ticksExisted % 20 == 0)
{
if(!cfg.easyTameHound && trust > 0F)
{
trust += getPlayerBonus();
trust += getVillaBonus();
}
}
}
updateAnimations();
if (!this.worldObj.isRemote && this.isShaking && !this.field_70928_h && !this.hasPath() && this.onGround)
{
this.field_70928_h = true;
this.timeWolfIsShaking = 0.0F;
this.prevTimeWolfIsShaking = 0.0F;
this.worldObj.setEntityState(this, (byte)8);
}
if (!this.dead && isTamed())
{
List list = this.worldObj.getEntitiesWithinAABB(EntityItem.class, this.boundingBox.expand(1.0D, 0.0D, 1.0D));
Iterator iterator = list.iterator();
while (iterator.hasNext())
{
this.pickupItem((EntityItem)iterator.next());
}
}
}
private float getStarveLethality()
{
return cfg.starveHound ? 0 : (isChild() ? 1 : 5);
}
private float getExhaustion()
{
if(this.isPotionActive(Potion.field_76443_y.id))
{
return 0.0F;
}
if(getOwner() == null)
{
return 0.0F;
}
float exhaust = 0.1F;
return exhaust;
}
private void updateAnimations()
{
if (jawMove > 0) {
jawMove--;
}
if (eatAnimation > 0) {
eatAnimation--;
}
if (chewTimer > 0) {
chewTimer--;
}
if (jawMove <= 0 && chewTimer > 0) {
jawMove = 3 + rand.nextInt(5);
playSound("random.eat", getSoundVolume(), getSoundPitch());
}
}
@Override
public void playLivingSound()
{
super.playLivingSound();
jawMove = 10;
}
public void addToHunger(float add)
{
setHunger(getHunger() + add);
}
private void tryToEat()
{
if(this.remainingFeedbag() > 0)
{
if (getHunger() < getMaxHunger())
{
addToHunger(1);
chew(20);
eatAnimation = 20;
worldObj.playAuxSFX(2001, (int)posX, (int)posY, (int)posZ,
Block.dirt.blockID);
this.eatBag(1);
}
}
else
{
if (ticksExisted % 20 == 0)
{
lookForFood();
}
if(ticksExisted % 5 == 0 && isTamed())
{
eatFromBowl();
}
}
}
private void eatFromBowl()
{
int search = 2;
double range = 1.5D;
for (int x = (int) posX - search; x <= (int) posX + search; x++)
{
for (int y = (int) posY - search; y <= (int) posY + search; y++)
{
for (int z = (int) posZ - search; z <= (int) posZ + search; z++)
{
if (this.getDistance(x+0.5D, y+0.5D, z+0.5D) < range && worldObj.getBlockId(x, y, z) == BlockListMF.dogbowl.blockID)
{
getNavigator().clearPathEntity();
TileEntityDogBowl tile = (TileEntityDogBowl) worldObj.getBlockTileEntity(x, y, z);
if (tile != null && tile.food > 0)
{
lastEaten = 20;
addToHunger(1);
if(this.saturationLevel < 10.0F)
{
saturationLevel = 10.0F;
}
tile.food--;
chew(20);
eatAnimation = 20;
worldObj.playAuxSFX(2001, x, y, z,Block.dirt.blockID);
facePoint(x, y, z);
return;
}
}
}
}
}
}
private void facePoint(double d0, double d1, double d2)
{
double d3 = (double)MathHelper.sqrt_double(d0 * d0 + d1 * d1);
float f2 = (float)(Math.atan2(d1, d0) * 180.0D / Math.PI) - 90.0F;
float f3 = (float)(-(Math.atan2(d2, d3) * 180.0D / Math.PI));
this.rotationPitch = this.updateRotation(this.rotationPitch, f3, 10F);
this.rotationYaw = this.updateRotation(this.rotationYaw, f2, getVerticalFaceSpeed());
}
private float updateRotation(float x, float y, float angle)
{
float f3 = MathHelper.wrapAngleTo180_float(y - x);
if (f3 > angle)
{
f3 = angle;
}
if (f3 < -angle)
{
f3 = -angle;
}
return x + f3;
}
private void lookForFood()
{
for (int x = (int) posX - 16; x < (int) posX + 16; x++)
{
for (int y = (int) posY - 16; y < (int) posY + 16; y++)
{
for (int z = (int) posZ - 16; z < (int) posZ + 16; z++)
{
if (worldObj.getBlockId(x, y, z) == BlockListMF.dogbowl.blockID)
{
TileEntityDogBowl tile = (TileEntityDogBowl) worldObj.getBlockTileEntity(x, y, z);
if (tile != null && tile.food > 0)
{
getNavigator().tryMoveToXYZ(x+0.5D, y+0.5D, z+0.5D, 1.0F);
return;
}
}
}
}
}
searchForItems(true);
}
private void searchForItems(boolean foodOnly)
{
List list = worldObj.getEntitiesWithinAABB(EntityItem.class,AxisAlignedBB.getAABBPool().getAABB(posX, posY, posZ, posX + 1.0D,posY + 1.0D, posZ + 1.0D).expand(16D, 4D, 16D));
if (!list.isEmpty())
{
EntityItem target = (EntityItem) list.get(worldObj.rand.nextInt(list.size()));
boolean pickup = false;
//IF IS FOOD
if(foodOnly)
{
if (target != null && target.getEntityItem().getItem() instanceof ItemFood)
{
ItemFood food = (ItemFood) (target.getEntityItem().getItem());
if (food != null && willEatFood(food))
{
pickup = true;
}
}
}
else
{
pickup = true;
}
if (pickup)
{
if (getNavigator().noPath())
{
this.setTarget(target);
this.getNavigator().tryMoveToXYZ(target.posX, target.posY, target.posZ, 1.0F);
return;
}
}
}
}
private void chew(int i)
{
jawMove = 5;
chewTimer = i;
playSound("random.eat", getSoundVolume(), getSoundPitch());
}
/**
* Called to update the entity's position/logic.
*/
public void onUpdate()
{
super.onUpdate();
this.field_70924_f = this.field_70926_e;
if (!worldObj.isRemote)
{
/**
* This will let the Hound return to the last point commanded
* If on stay, it will return after 2 blocks range, teleporting if it must
* If idle: the hound will try walk back after 16
*/
if(getCommand().equalsIgnoreCase("Stay") && getNavigator().noPath() && getAttackTarget() == null)
{
if(lastEaten <= 0 && this.getDistance(stayPos[0], stayPos[1], stayPos[2]) > 2)
{
if(!getNavigator().tryMoveToXYZ(stayPos[0], stayPos[1], stayPos[2], 1.0F))
{
int i = MathHelper.floor_double(stayPos[0]) - 2;
int j = MathHelper.floor_double(stayPos[2]) - 2;
int k = MathHelper.floor_double(stayPos[1]);
for (int l = 0; l <= 4; ++l)
{
for (int i1 = 0; i1 <= 4; ++i1)
{
if ((l < 1 || i1 < 1 || l > 3 || i1 > 3) && worldObj.doesBlockHaveSolidTopSurface(i + l, k - 1, j + i1) && !worldObj.isBlockNormalCube(i + l, k, j + i1) && !worldObj.isBlockNormalCube(i + l, k + 1, j + i1))
{
setLocationAndAngles((double)((float)(i + l) + 0.5F), (double)k, (double)((float)(j + i1) + 0.5F), rotationYaw, rotationPitch);
this.getNavigator().clearPathEntity();
return;
}
}
}
}
}
}
if(timeUntilSit > 0)
{
timeUntilSit --;
}
if(!getNavigator().noPath() && timeUntilSit < 10)
{
timeUntilSit = 10;
}
updateCommands();
if(xp >= xpMax)
{
levelup();
}
if(ticksExisted % 20 == 0)
{
updateArmours();
this.sendStatPackets();
}
this.sendQuickPackets();
boolean flag = getNavigator().noPath() && timeUntilSit <= 0;
this.setStill(flag);
int maxItems = this.getAvailableRows()*9;
for(int a = maxItems; a < pack.getSizeInventory(); a ++)
{
if(pack.getStackInSlot(a) != null)
{
this.entityDropItem(pack.getStackInSlot(a), 1.0F);
pack.setInventorySlotContents(a, null);
}
}
if(isChild())
{
if(getHealth() > getMaxHealth())
{
setHealth(getMaxHealth());
}
if(getHunger() > getMaxHunger())
{
setHunger(getMaxHunger());
}
if(this.getGrowingAge() == -1)
{
this.setGrowingAge(0);
setHunger(getMaxHunger());
refreshHealth();
}
}
if(invertSpots < 0)
{
invertSpots = rand.nextBoolean() ? 1 : 0;
}
if(ticksExisted % 20 == 0)
{
float maxHealth = this.getMaxHealth();
float properHealth = this.getMaxHealth(endurance);
if(maxHealth != properHealth)
{
this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setAttribute(properHealth);
}
}
}
if (this.isInterested())
{
this.field_70926_e += (1.0F - this.field_70926_e) * 0.4F;
}
else
{
this.field_70926_e += (0.0F - this.field_70926_e) * 0.4F;
}
if (this.isInterested())
{
this.numTicksToChaseTarget = 10;
}
if (this.isWet())
{
this.isShaking = true;
this.field_70928_h = false;
this.timeWolfIsShaking = 0.0F;
this.prevTimeWolfIsShaking = 0.0F;
}
else if ((this.isShaking || this.field_70928_h) && this.field_70928_h)
{
if (this.timeWolfIsShaking == 0.0F)
{
this.playSound("mob.wolf.shake", this.getSoundVolume(), (this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 1.0F);
}
this.prevTimeWolfIsShaking = this.timeWolfIsShaking;
this.timeWolfIsShaking += 0.05F;
if (this.prevTimeWolfIsShaking >= 2.0F)
{
this.isShaking = false;
this.field_70928_h = false;
this.prevTimeWolfIsShaking = 0.0F;
this.timeWolfIsShaking = 0.0F;
}
if (this.timeWolfIsShaking > 0.4F)
{
float f = (float)this.boundingBox.minY;
int i = (int)(MathHelper.sin((this.timeWolfIsShaking - 0.4F) * (float)Math.PI) * 7.0F);
for (int j = 0; j < i; ++j)
{
float f1 = (this.rand.nextFloat() * 2.0F - 1.0F) * this.width * 0.5F;
float f2 = (this.rand.nextFloat() * 2.0F - 1.0F) * this.width * 0.5F;
this.worldObj.spawnParticle("splash", this.posX + (double)f1, (double)(f + 0.8F), this.posZ + (double)f2, this.motionX, this.motionY, this.motionZ);
}
}
}
}
@SideOnly(Side.CLIENT)
public boolean getWolfShaking()
{
return this.isShaking;
}
@SideOnly(Side.CLIENT)
/**
* Used when calculating the amount of shading to apply while the wolf is shaking.
*/
public float getShadingWhileShaking(float shade)
{
return 0.75F + (this.prevTimeWolfIsShaking + (this.timeWolfIsShaking - this.prevTimeWolfIsShaking) * shade) / 2.0F * 0.25F;
}
@SideOnly(Side.CLIENT)
public float getShakeAngle(float f, float f1)
{
float f2 = (this.prevTimeWolfIsShaking + (this.timeWolfIsShaking - this.prevTimeWolfIsShaking) * f + f1) / 1.8F;
if (f2 < 0.0F)
{
f2 = 0.0F;
}
else if (f2 > 1.0F)
{
f2 = 1.0F;
}
return MathHelper.sin(f2 * (float)Math.PI) * MathHelper.sin(f2 * (float)Math.PI * 11.0F) * 0.15F * (float)Math.PI;
}
@SideOnly(Side.CLIENT)
public float getInterestedAngle(float angle)
{
return (this.field_70924_f + (this.field_70926_e - this.field_70924_f) * angle) * 0.15F * (float)Math.PI;
}
public float getEyeHeight()
{
return this.height * 0.8F;
}
/**
* The speed it takes to move the entityliving's rotationPitch through the faceEntity method. This is only currently
* use in wolves.
*/
public int getVerticalFaceSpeed()
{
return this.isSitting() ? 20 : super.getVerticalFaceSpeed();
}
/**
* Called when the entity is attacked.
*/
@Override
public boolean attackEntityFrom(DamageSource source, float damage)
{
if(source == DamageSource.inWall)
{
return false;
}
if (this.isEntityInvulnerable())
{
return false;
}
else
{
damage = applyResistance(source, damage);
if(source.isFireDamage())
{
if(isSuper() || (cfg.houndNoFire && getHealth() <= 1))
{
return false;
}
}
if(damage <= 0)
{
return false;
}
timeUntilSit = 100;
Entity entity = source.getEntity();
this.aiSit.setSitting(false);
if (entity != null && !(entity instanceof EntityPlayer) && !(entity instanceof EntityArrow))
{
damage = (damage + 1) / 2;
}
if (entity != null && entity instanceof EntityPlayer && !isTamed())
{
setAngry(true);
}
return super.attackEntityFrom(source, damage);
}
}
private float applyResistance(DamageSource source, float damage)
{
float resist = getEquippedArmour(source);
damage -= (damage*resist);
return (float)Math.max(damage, 0);
}
private boolean isSuper()
{
if(this.getBreed() != null)
{
return getBreed().tierOfBreed == 3;
}
return false;
}
@Override
public boolean attackEntityAsMob(Entity enemy)
{
timeUntilSit = 100;
jawMove = 10;
float i = getBiteDamage(enemy);
if(armour[0] != null)
{
if(armour[0].getItem() instanceof ItemHoundWeapon)
{
if(enemy instanceof EntityLiving)
((ItemHoundWeapon)armour[0].getItem()).hitEntity(armour[0], (EntityLiving)enemy, this);
}
if (enemy instanceof EntityLiving)
{
i += EnchantmentHelper.getEnchantmentModifierLiving(this, (EntityLiving)enemy);
}
}
if(enemy.attackEntityFrom(DamageSource.causeMobDamage(this), i))
{
xp += (int)i;
return true;
}
if (enemy instanceof EntityLiving)
{
EnchantmentThorns.func_92096_a(this, (EntityLiving)enemy, this.rand);
int l = EnchantmentHelper.getFireAspectModifier(this);
if (l > 0 && !enemy.isBurning())
{
enemy.setFire(l);
}
}
return false;
}
@Override
public int getTotalArmorValue()
{
return 0;
}
private float getEquippedArmour(DamageSource source)
{
float base = 0;
for (ItemStack slot : armour)
{
if (slot != null && slot.getItem() instanceof IHoundArmour)
{
base += ((IHoundArmour)slot.getItem()).getResistance(source);
}
}
return (float)Math.min(0.999F, base);
}
public float getACDisplayPercent()
{
float base = 0;
for (ItemStack slot : armour)
{
if (slot != null && slot.getItem() instanceof IHoundArmour)
{
base += ((IHoundArmour)slot.getItem()).getACDisplayPercent();
}
}
return (float)Math.min(0.99F, base);
}
@Override
protected float applyArmorCalculations(DamageSource source, float damage)
{
if (!source.isUnblockable())
{
int i = 25 - this.getTotalArmorValue();
float f1 = damage * (float)i;
this.damageArmour(source, damage);
damage = f1 / 25.0F;
}
return damage;
}
protected void damageArmour(DamageSource source, float damage)
{
damage /= 2;
if (damage < 1)
{
damage = 1;
}
for (int var2 = 0; var2 < this.armour.length; ++var2)
{
if (this.armour[var2] != null && this.armour[var2].getItem().isDamageable())
{
if(shouldDamage(armour[var2], source))
{
this.armour[var2].damageItem((int)damage, this);
if (this.armour[var2].stackSize <= 0)
{
this.armour[var2] = null;
updateArmours();
}
}
}
}
}
private boolean shouldDamage(ItemStack stack, DamageSource source)
{
if(stack == null)
{
return false;
}
if(stack.getItem() instanceof IHoundArmour)
{
return ((IHoundArmour)stack.getItem()).shouldDamage(source);
}
return true;
}
@Override
public void onKillEntity(EntityLivingBase enemy)
{
//this.getAIMoveSpeed()
int reward = 0;
if(enemy instanceof EntityLiving)
{
reward = (int)((EntityLiving)enemy).experienceValue;
}
if(enemy instanceof EntityPlayer)
{
reward = 100;
}
xp += reward;
}
/**
* Called when a player interacts with a mob. e.g. gets milk from a cow, gets into the saddle on a pig.
*/
public boolean interact(EntityPlayer player)
{
ItemStack itemstack = player.inventory.getCurrentItem();
if (this.isTamed())
{
if (itemstack != null)
{
if(player.isSneaking() && itemstack.getItem() instanceof ItemBandage)
{
return false;
}
if(MineFantasyBase.isDebug())
{
if(applyDebugItems(player, itemstack)) return true;
}
if (Item.itemsList[itemstack.itemID] instanceof ItemFood)
{
ItemFood itemfood = (ItemFood)Item.itemsList[itemstack.itemID];
if (willEatFood(itemfood))
{
boolean consume = false;
if(canEatFood(itemfood))
{
consume = true;
eatFood(itemfood);
}
else
{
if(this.fillBag(itemfood.getHealAmount()))
{
consume = true;
}
}
if (consume && !player.capabilities.isCreativeMode)
{
--itemstack.stackSize;
}
if (itemstack.stackSize <= 0)
{
player.inventory.setInventorySlotContents(player.inventory.currentItem, (ItemStack)null);
}
if(consume)
return true;
}
}
else if (itemstack.itemID == Item.dyePowder.itemID)
{
int i = BlockColored.getBlockFromDye(itemstack.getItemDamage());
if (i != this.getCollarColour())
{
this.setCollarColour(i);
if (!player.capabilities.isCreativeMode && --itemstack.stackSize <= 0)
{
player.inventory.setInventorySlotContents(player.inventory.currentItem, (ItemStack)null);
}
return true;
}
}
else if(itemstack.getItem() instanceof ItemPetChange)
{
if(onUseTrade(player, itemstack))
{
return true;
}
}
}
if (!this.worldObj.isRemote && !this.isBreedingItem(itemstack))
{
player.openGui(MineFantasyBase.instance, 2, worldObj, entityId,
0, 0);
return true;
}
}
else if (tryToTame(player, itemstack))
{
this.setHunger(this.getMaxHunger());
return true;
}
return super.interact(player);
}
/**
* Tries to tame the hound.
* @param player the taming player
* @param itemstack the item being used
*/
private boolean tryToTame(EntityPlayer player, ItemStack itemstack)
{
if(itemstack != null && itemstack.itemID == Item.bone.itemID && (!inPack() && canBeTamed(player) || player.capabilities.isCreativeMode))
{
if(player.capabilities.isCreativeMode)
{
tame(player, true);
return true;
}
if(!cfg.easyTameHound && trust > 25F && trust < 100F)
{
return false;
}
if(isAngry())
{
playSound("mob.wolf.bark", 1.2F, 1.0F);
player.attackEntityFrom(DamageSource.causeMobDamage(this), 1);
return true;
}
chew(20);
//Start
if(!cfg.easyTameHound && trust < 25F)
{
trust += rand.nextFloat()*5F;
}
if (!player.capabilities.isCreativeMode)
{
--itemstack.stackSize;
}
if (itemstack.stackSize <= 0)
{
player.inventory.setInventorySlotContents(player.inventory.currentItem, (ItemStack)null);
}
//Tame
if((cfg.easyTameHound || trust >= 100F) && rand.nextInt(5) == 0)
{
tame(player, true);
return true;
}
else
{
tame(player, false);
}
}
return false;
}
/**
* Called when taming has succeeded
* @param player the player taming the creature
*/
private void tame(EntityPlayer player, boolean success)
{
if (this.worldObj.isRemote)
{
return;
}
if (success)
{
this.setTamed(true); //Dog Will Tame
this.setPathToEntity((PathEntity)null); //Dog Will Stop Moving
this.setAttackTarget((EntityLiving)null); //Dog Will Cease Combat
this.setOwner(player.username); //Sets The Owner
this.playTameEffect(true); //Create Hearts
this.worldObj.setEntityState(this, (byte)7); //Set Tame
command("Follow");
refreshHealth();
}
else
{
this.playTameEffect(false); //Fail look
this.worldObj.setEntityState(this, (byte)6); //Set Fail
}
}
private void refreshHealth()
{
this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setAttribute(getMaxHealth(endurance));
this.setHealth(getMaxHealth());
}
/**
* Determines if a dog can be tamed
* @param player the player trying to tame
* @return if it is possible(False if the hound is in combat)
*/
private boolean canBeTamed(EntityPlayer player)
{
return getAttackTarget() == null;
}
public int remainingFeedbag()
{
if(armour[0] != null)
{
if(armour[0].getItem() instanceof ItemHoundFeedbag)
{
ItemHoundFeedbag bag = (ItemHoundFeedbag)armour[0].getItem();
return bag.getMaxDamage() - armour[0].getItemDamage();
}
}
return 0;
}
public boolean fillBag(int food)
{
if(armour[0] != null)
{
if(armour[0].getItem() instanceof ItemHoundFeedbag)
{
int f = armour[0].getItemDamage();
if(f <= 1)return false;
if(!worldObj.isRemote)
{
armour[0].setItemDamage(f-food);
if(armour[0].getItemDamage() < 1)armour[0].setItemDamage(1);
}
return true;
}
}
return false;
}
public boolean eatBag(int food)
{
if(armour[0] != null)
{
if(armour[0].getItem() instanceof ItemHoundFeedbag)
{
int f = armour[0].getItemDamage();
if(f >= armour[0].getMaxDamage())return false;
if(!worldObj.isRemote)
{
armour[0].setItemDamage(f+food);
if(armour[0].getItemDamage() < 1)armour[0].setItemDamage(1);
}
return true;
}
}
return false;
}
private boolean canEatFood(ItemFood itemfood)
{
return getHunger() < getMaxHunger();
}
@Override
public boolean canAttackClass(Class entity)
{
if(!cfg.houndKillMan && entity == EntityVillager.class)
return false;
return true;
}
/**
* Applies a command from the player
* @param string the command sent("Idle", "Stay", "Follow")
*/
public void command(String string)
{
this.detachHome();
setCommand(string);
if(string.equalsIgnoreCase("Stay"))
{
setStayPos();
}
if(string.equalsIgnoreCase("Idle"))
{
setHome();
}
}
private void setHome()
{
setHomeArea((int)posX, (int)posY, (int)posZ, 15);
}
@SideOnly(Side.CLIENT)
public void handleHealthUpdate(byte par1)
{
if (par1 == 8)
{
this.field_70928_h = true;
this.timeWolfIsShaking = 0.0F;
this.prevTimeWolfIsShaking = 0.0F;
}
else
{
super.handleHealthUpdate(par1);
}
}
@SideOnly(Side.CLIENT)
public float getTailRotation()
{
float tail = (float)Math.toRadians(90);
float hp = (20F / getMaxHealth()) * getHealth();
if(cfg.easyTameHound)
{
tail = (float)Math.PI / 5F;
}
else if(trust > 0F)
{
tail = (tail / 100F) * trust;
}
return this.isAngry() ? 1.5393804F : (this.isTamed() ? (0.55F - (float)(20 - hp) * 0.02F) * (float)Math.PI : (tail));
}
/**
* Checks if the parameter is an item which this animal can be fed to breed it (wheat, carrots or seeds depending on
* the animal type)
*/
public boolean isBreedingItem(ItemStack item)
{
return item == null ? false : (!(Item.itemsList[item.itemID] instanceof ItemFood) ? false : ((ItemFood)Item.itemsList[item.itemID]).isWolfsFavoriteMeat());
}
/**
* Will return how many at most can spawn in a chunk at once.
*/
public int getMaxSpawnedInChunk()
{
return 8;
}
/**
* Determines whether this wolf is angry or not.
*/
public boolean isAngry()
{
return (this.dataWatcher.getWatchableObjectByte(16) & 2) != 0;
}
/**
* Sets whether this wolf is angry or not.
*/
public void setAngry(boolean flag)
{
if(isTamed() && flag)return;
byte b0 = this.dataWatcher.getWatchableObjectByte(16);
if (flag)
{
this.dataWatcher.updateObject(16, Byte.valueOf((byte)(b0 | 2)));
}
else
{
this.dataWatcher.updateObject(16, Byte.valueOf((byte)(b0 & -3)));
}
}
/**
* Return this wolf's collar color.
*/
public int getCollarColour()
{
return this.dataWatcher.getWatchableObjectByte(20) & 15;
}
/**
* Set this wolf's collar color.
*/
public void setCollarColour(int par1)
{
this.dataWatcher.updateObject(20, Byte.valueOf((byte)(par1 & 15)));
}
/**
* This function is used when two same-species animals in 'love mode' breed to generate the new baby animal.
*/
public EntityHound spawnBabyAnimal(EntityAgeable parent)
{
//TODO: Breeding
EntityHound hound2 = null;
if(parent instanceof EntityHound)
{
hound2 = (EntityHound)parent;
}
EntityHound dog = new EntityHound(this.worldObj);
String s = this.getOwnerName();
if (s != null && s.trim().length() > 0)
{
dog.setOwner(s);
dog.setTamed(true);
}
if(hound2 != null)
{
if(getBreed() != null && hound2.getBreed() != null)
{
dog.setBreedInt(getBreedFor(getBreedInt(), hound2.getBreedInt()));
}
}
dog.command("Stay");
return dog;
}
private int getBreedFor(int breed, int breed2)
{
EnumHoundBreed special = EnumHoundBreed.getBreedFor(breed, breed2);
if(special != null)
{
double chance = getChanceFor(special.chanceToCreate, cfg.HoundBreed);
if(MineFantasyBase.isDebug())
{
System.out.println("Chance: "+chance + " (" + (chance*100F) + ")% cfg= " + cfg.HoundBreed);
}
if(MineFantasyBase.isDebug() || rand.nextDouble() <= chance)
{
return special.ordinal();
}
}
return (rand.nextBoolean() ? breed : breed2);
}
private double getChanceFor(double chance, int a)
{
double multiplier = 1.0F / ((float)a);
return chance*multiplier;
}
public void func_70918_i(boolean flag)
{
byte b0 = this.dataWatcher.getWatchableObjectByte(IdBase+1);
if (flag)
{
this.dataWatcher.updateObject(IdBase+1, Byte.valueOf((byte)1));
}
else
{
this.dataWatcher.updateObject(IdBase+1, Byte.valueOf((byte)0));
}
}
/**
* Returns true if the mob is currently able to mate with the specified mob.
*/
public boolean canMateWith(EntityAnimal animal)
{
if (animal == this)
{
return false;
}
else if (!this.isTamed())
{
return false;
}
else if (!(animal instanceof EntityHound))
{
return false;
}
else
{
EntityHound entitywolf = (EntityHound)animal;
return !entitywolf.isTamed() ? false : (entitywolf.isSitting() ? false : this.isInLove() && entitywolf.isInLove());
}
}
private void setStats()
{
if (getBreedInt() <= -1)
{
setRandomBreed();
}
}
public boolean isInterested()
{
return this.dataWatcher.getWatchableObjectByte(IdBase+1) == 1 && !inPack();
}
public EntityAgeable createChild(EntityAgeable parent2)
{
return this.spawnBabyAnimal(parent2);
}
public ItemStack getStackInSlot(int i)
{
return armour[i];
}
public boolean isAlpha()
{
return false;
}
public String getName()
{
return getEntityName();
}
public String getTexture()
{
if(getBreed() != null)
{
if(invertSpots == 1)
{
if(getSpots() != null)
{
return data_minefantasy.image("/mob/Hound/hound" + getSpots() + ".png");
}
}
}
return data_minefantasy.image("/mob/Hound/hound" + getFurTex() + ".png");
}
public String getFurTex() {
if(getBreed() != null)
{
return getBreed().texture;
}
return "Brown";
}
public boolean isFollowing()
{
return getCommand().equalsIgnoreCase("Follow");
}
public String getCommand()
{
String str = dataWatcher.getWatchableObjectString(IdBase+4);
if(str == null)
{
str = "";
}
return str;
}
public void setCommand(String s)
{
dataWatcher.updateObject(IdBase+4, s);
}
@Override
public boolean isSitting()
{
if(!isStill())
{
return false;
}
if(getCommand().equalsIgnoreCase("Stay"))
{
return true;
}
return false;
}
private boolean isStill()
{
return dataWatcher.getWatchableObjectByte(IdBase+5) == 1;
}
private void setStill(boolean flag)
{
byte b = (byte)(flag ? 1 : 0);
dataWatcher.updateObject(IdBase+5, b);
}
private void updateCommands()
{
if(getCommand().length() == 0)
{
setCommand("Idle");
}
if(getCommand().equalsIgnoreCase("Follow"))
{
if(getOwner() == null)
{
/*
if(false && this.hasUnlockedTeleport())//TODO: Later on; add some sort of teleport when offline option
{
teleport(homePos);
stayPos[0] = homePos[0];
stayPos[1] = homePos[1];
stayPos[2] = homePos[2];
setCommand("Stay");
}
else
*/
{
setStayPos();
setCommand("Stay");
}
}
}
}
public boolean shouldWander()
{
if(isFollowing() || isSitting())
{
return false;
}
return true;
}
@Override
public void recievePacket(ByteArrayDataInput data)
{
try
{
int id = data.readInt();
if(id == 0)//STATS
{
strength = data.readInt();
stamina = data.readInt();
endurance = data.readInt();
xp = data.readInt();
xpMax = data.readInt();
level = data.readInt();
AtPoints = data.readInt();
}
if(id == 1)//BOOLEANS
{
attackMob = data.readInt() == 1;
attackAnimal = data.readInt() == 1;
attackPlayer = data.readInt() == 1;
attackDefense = data.readInt() == 1;
fightPvp = data.readInt() == 1;
leapAttack = data.readInt() == 1;
pickupItems = data.readInt() == 1;
boostStep = data.readInt() == 1;
inPack = data.readInt() == 1;
trust = data.readInt();
invertSpots = data.readInt();
}
if(id == 2)//COMMAND
{
int i = data.readInt();
if(i < commandList.length)
{
command(commandList[i]);
}
}
if(id == 3)//TOGGLE
{
int p = data.readInt();
activatePower(p);
}
if(id == 4)//Level
{
int i = data.readInt();
if(i == 0)//STR
{
if(strength < 100)
this.strength = tryLevelSkill(strength);
}
if(i == 1)//STA
{
if(stamina < 100)
this.stamina = tryLevelSkill(stamina);
}
if(i == 2)//END
{
if(endurance < 100)
{
float max = getMaxHealthFor();
this.endurance = tryLevelSkill(endurance);
syncAttributes();
heal(getMaxHealth() - max);
}
}
}
if(id == 5)
{
int a1 = data.readInt();
int s1 = data.readInt();
int d1 = data.readInt();
int a2 = data.readInt();
int s2 = data.readInt();
int d2 = data.readInt();
if(a1 > 0)
{
armour[0] = new ItemStack(a1, s1, d1);
}
if(a2 > 0)
{
armour[1] = new ItemStack(a2, s2, d2);
}
}
}catch(Exception e)
{
System.err.println("MineFantasy: Issues found in hound packet data");
}
}
/**
* Activates from the power bar
* @param p the powerbar slot
*/
private void activatePower(int p)
{
switch(p)
{
case 0:
attackMob = !attackMob;
break;
case 1:
attackAnimal = !attackAnimal;
break;
case 2:
attackPlayer = !attackPlayer;
if(attackPlayer)
{
fightPvp = true;
}
break;
case 3:
attackDefense = !attackDefense;
break;
case 4:
fightPvp = !fightPvp;
break;
case 5://LEAP
leapAttack = !leapAttack;
break;
case 6://PICKUP
pickupItems = !pickupItems;
break;
case 7://BOOST
boostStep = !boostStep;
stepHeight = boostStep ? 1.0F : 0.5F;
break;
case 8://TELEPORT
if(hasUnlockedTeleport())
{
teleport(homePos);
stayPos[0] = homePos[0];
stayPos[1] = homePos[1];
stayPos[2] = homePos[2];
setCommand("Stay");
}
break;
case 9://SETPOS
if(hasUnlockedTeleport())
{
setHome(posX, posY, posZ);
trySendPlayerMessage("Your Hound " + getNameString() + "Has set home: "
+ posX + "x "+ posY + "y "+ posZ + "z ");
}
break;
case 10: //Disengage
{
if(getAttackTarget() != null)
{
this.setAttackTarget(null);
getNavigator().clearPathEntity();
}
}
}
}
private void trySendPlayerMessage(String message)
{
if(!worldObj.isRemote)
if(getOwner() != null && getOwner() instanceof EntityPlayer)
{
((EntityPlayer)getOwner()).addChatMessage(message);
}
}
private void setHome(double x, double y, double z)
{
homePos[0] = x;
homePos[1] = y;
homePos[2] = z;
}
private void sendQuickPackets()
{
try {
Packet packet = PacketManagerMF.getEntityPacketIntegerArray(this, new int[]{1, attackMob ? 1 : 0, attackAnimal ? 1 : 0, attackPlayer ? 1 : 0, attackDefense ? 1 : 0 ,fightPvp ? 1 : 0 , leapAttack ? 1 : 0 , pickupItems ? 1 : 0 , boostStep ? 1 : 0, inPack ? 1 : 0, (int)trust, invertSpots});
FMLCommonHandler.instance().getMinecraftServerInstance()
.getConfigurationManager()
.sendPacketToAllPlayers(packet);
} catch (NullPointerException e) {
;
}
}
private void sendStatPackets()
{
try {
Packet packet = PacketManagerMF.getEntityPacketIntegerArray(this, new int[]{0, strength, stamina, endurance, xp, xpMax, level, AtPoints});
FMLCommonHandler.instance().getMinecraftServerInstance()
.getConfigurationManager()
.sendPacketToAllPlayers(packet);
} catch (NullPointerException e) {
;
}
}
@SideOnly(Side.CLIENT)
public void commandFromClient(int id)
{
try {
Packet packet = PacketManagerMF.getEntityPacketIntegerArray(this, new int[]{2, id});
PacketDispatcher.sendPacketToServer(packet);
FMLCommonHandler.instance().getMinecraftServerInstance()
.getConfigurationManager()
.sendPacketToAllPlayers(packet);
} catch (NullPointerException e) {
;
}
}
@SideOnly(Side.CLIENT)
public void levelFromClient(int id)
{
try {
Packet packet = PacketManagerMF.getEntityPacketIntegerArray(this, new int[]{4, id});
PacketDispatcher.sendPacketToServer(packet);
FMLCommonHandler.instance().getMinecraftServerInstance()
.getConfigurationManager()
.sendPacketToAllPlayers(packet);
} catch (NullPointerException e) {
;
}
}
private void setStayPos()
{
stayPos[0] = posX;
stayPos[1] = posY;
stayPos[2] = posZ;
}
private String[] commandList = new String[]{"Idle", "Stay", "Follow"};
private float levelupMulti = 1.05F;
private int maxLevel = 100;
private boolean inPack;
private int tryLevelSkill(int skill)
{
if(skill < 100 && AtPoints > 0)
{
AtPoints --;
skill ++;
}
return skill;
}
@Override
public int getSizeInventory()
{
return armour.length;
}
@Override
public ItemStack decrStackSize(int i, int j) {
if (armour[i] != null)
{
if (armour[i].stackSize <= j)
{
ItemStack itemstack = armour[i];
armour[i] = null;
return itemstack;
}
ItemStack itemstack1 = armour[i].splitStack(j);
if (armour[i].stackSize == 0)
{
armour[i] = null;
}
return itemstack1;
}
else
{
return null;
}
}
@Override
public ItemStack getStackInSlotOnClosing(int i)
{
return null;
}
@Override
public void setInventorySlotContents(int i, ItemStack itemstack)
{
armour[i] = itemstack;
}
@Override
public String getInvName()
{
return getEntityName();
}
@Override
public boolean isInvNameLocalized()
{
return true;
}
@Override
public int getInventoryStackLimit()
{
return 64;
}
@Override
public boolean isUseableByPlayer(EntityPlayer var1)
{
return this.getDistanceToEntity(var1) < 16 && !isDead;
}
@Override
public void openChest() {}
@Override
public void closeChest() {}
@Override
public boolean isItemValidForSlot(int i, ItemStack itemstack)
{
return false;
}
@SideOnly(Side.CLIENT)
public void usePower(int id)
{
try {
Packet packet = PacketManagerMF.getEntityPacketIntegerArray(this, new int[]{3, id});
PacketDispatcher.sendPacketToServer(packet);
FMLCommonHandler.instance().getMinecraftServerInstance()
.getConfigurationManager()
.sendPacketToAllPlayers(packet);
} catch (NullPointerException e) {
;
}
}
public float getMaxHealthFor()
{
return isChild() ? 5 : getMaxHealth(endurance);
}
public float getMaxHealth(int lvl)
{
if(isChild())return 5;
float hp = getHealthOnBreed();
if(isTamed())
{
double buff = 1.0D / 100D * (double)lvl;
hp += (float)((double)hp * buff);
}
return hp;
}
public float getHealthOnBreed()
{
float bonus = 1;
if(getBreed() != null)
{
bonus = getBreed().defense;
}
return 10 * bonus;
}
public float getBiteDamage(Entity tar)
{
float damage = getBaseDamage(strength);
if(armour[0] != null)
{
if(armour[0].getItem() instanceof IHoundWeapon)
{
damage += ((IHoundWeapon)armour[0].getItem()).getDamage(tar);
}
}
if (this.isPotionActive(Potion.damageBoost))
{
damage += 3 << this.getActivePotionEffect(Potion.damageBoost).getAmplifier();
}
if (this.isPotionActive(Potion.weakness))
{
damage -= 2 << this.getActivePotionEffect(Potion.weakness).getAmplifier();
}
return damage;
}
public float getBaseDamage(int level)
{
float damage = 1;
if(getBreed() != null)
{
damage += (getBreed().attack/2);
}
float str = getDamageMod(level);
return damage * str;
}
public float getDamageMod(int level)
{
return 1.0F + (1.0F / 100F * (float)level);
}
public int getHungerDecay()
{
int d = getHungerDecay(stamina);
if(shouldBoost())
{
d = (int)((double)d * 0.9F);
}
if(isChild())
{
d *= 4;
}
return d;
}
/**
* Gets the time span between hunger loss
* @return every 30 seconds(level 1). special breeds lose every 90 seconds
* 5x longer at lvl 100
*
* Total time:
* Lvl1: 10mins (30mins special)
* lvl50: 30mins (90mins special)
* lvl100: 1hour (3hours special)
*/
public int getHungerDecay(int lvl)
{
int decay = getDecayOnBreed() / 10; // 3 Seconds
double bonus = 5.0D / 100D * (double)lvl;
decay += (int)((double)decay * bonus);
return decay;
}
public int getDecayOnBreed()
{
int bonus = 1;
if(getBreed() != null)
{
bonus = getBreed().stamina;
}
return 1200 + (300 * bonus);
}
/**
* Hounds can't heal below 85% hunger
*/
private boolean canHeal()
{
return getHunger() >= (getMaxHunger()*0.85F);
}
private void levelup()
{
levelup(true);
}
private void levelup(boolean legit)
{
boolean leap = hasUnlockedLeap();
boolean pickup = hasUnlockedPickup();
boolean boost = hasUnlockedBoost();
boolean teleport = hasUnlockedTeleport();
if(legit)
{
xp -= xpMax;
worldObj.playSoundAtEntity(this, "random.levelup", 1.0F, 1.0F);
}
experienceValue *= this.levelupMulti;
level ++;
xpMax *= levelupMulti;
AtPoints += 2;
if(level % 5 == 0)
{
AtPoints += 3;
}
if(strength >= 100 && stamina >= 100 && endurance >= 100)
{
AtPoints = 0;
}
if(leap != hasUnlockedLeap())
{
trySendPlayerMessage("Your Hound " + getNameString() + "Has Learned 'Leap Attack'");
}
if(pickup != hasUnlockedPickup())
{
trySendPlayerMessage("Your Hound " + getNameString() + "Has Learned 'Collect Items'");
}
if(boost != hasUnlockedBoost())
{
trySendPlayerMessage("Your Hound " + getNameString() + "Has Learned 'Step Boost'");
}
if(teleport != hasUnlockedTeleport())
{
trySendPlayerMessage("Your Hound " + getNameString() + "Has Learned 'Teleport Home'");
}
syncAttributes();
}
private void syncAttributes()
{
this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setAttribute(this.getMaxHealthFor());
}
public float getMaxHunger()
{
return isChild() ? 5 : getMaxHungerOnBreed();
}
private float getMaxHungerOnBreed()
{
float bonus = 1;
if(getBreed() != null)
{
bonus = getBreed().stamina;
}
return (5 * bonus) + 5;
}
@SideOnly(Side.CLIENT)
public float getDisplayHealth()
{
return getHealth();
}
@Override
public int getEntityID()
{
return entityId;
}
@Override
public void sendNewName(String name)
{
setCustomNameTag(name);
}
public void setHunger(float h)
{
dataWatcher.updateObject(IdBase+6, h);
}
public float getHunger()
{
return dataWatcher.getWatchableObjectFloat(IdBase+6);
}
@Override
public int getViewingArc()
{
return 360;
}
@Override
public int getHearing()
{
return -5;
}
@Override
public int getSight()
{
return 10;
}
public void eatFood(ItemFood food)
{
chew(100);
this.saturationLevel = food.getSaturationModifier()*food.getHealAmount();
this.setHunger(Math.min(getMaxHunger(), getHunger() + food.getHealAmount()));
}
@Override
public void onInventoryChanged() {}
public boolean canEquip(IHoundEquipment equipment)
{
/*
if(strength < equipment.getRequiredStr() || stamina < equipment.getRequiredSta() || endurance < equipment.getRequiredEnd())
{
return false;
}
*/
return true;
}
private void syncItems()
{
if(!worldObj.isRemote)
{
for(int a = 0; a < armour.length; a ++)
{
Packet packet = PacketManagerMF.getPacketItemStackArray(this, a, armour[a]);
try
{
FMLCommonHandler.instance().getMinecraftServerInstance().getConfigurationManager().sendPacketToAllPlayers(packet);
} catch(NullPointerException e)
{
System.out.println("MineFantasy: Client connection lost");
return;
}
}
}
}
private void updateArmours()
{
syncItems();
}
public void unused()
{
int a1 = -1;
int a2 = -1;
int s1 = 1;
int s2 = 1;
int d1 = 0;
int d2 = 0;
if(armour[0] != null)
{
a1 = armour[0].itemID;
s1 = armour[0].stackSize;
d1 = armour[0].getItemDamage();
}
if(armour[1] != null)
{
a2 = armour[1].itemID;
s2 = armour[1].stackSize;
d2 = armour[1].getItemDamage();
}
try {
Packet packet = PacketManagerMF.getEntityPacketIntegerArray(this, new int[]{5, a1, s1, d1, a2, s2, d2});
FMLCommonHandler.instance().getMinecraftServerInstance()
.getConfigurationManager()
.sendPacketToAllPlayers(packet);
} catch (NullPointerException e) {
;
}
}
protected int applyPotionDamageCalculations(DamageSource source, int damage)
{
//TODO Potion Calc
int j;
int k;
int l;
if (this.isPotionActive(Potion.resistance))
{
damage /= 2;
}
if (damage <= 0)
{
return 0;
}
else
{
j = EnchantmentHelper.getEnchantmentModifierDamage(this.getLastActiveItems(), source);
if (j > 20)
{
j = 20;
}
return damage;
}
}
@Override
public ItemStack[] getLastActiveItems()
{
return this.armour;
}
@Override
public ItemStack getHeldItem()
{
return armour[0];
}
/**
* Used to determine what hounds gang up
* @param theDog: The dog requesting assistance
* @return If both are untamed: they will fight together.
* If both are tamed by the same person: they will fight too
*/
public boolean willFightFor(EntityHound theDog)
{
if(!isTamed())
{
return !theDog.isTamed();
}
else
{
if(getOwnerName() != null && theDog.getOwnerName() != null)
{
return getOwnerName().equals(theDog.getOwnerName());
}
}
return false;
}
/**
* A list of items that are used for testing
* @return if an item has been used
*/
private boolean applyDebugItems(EntityPlayer user, ItemStack itemstack)
{
if(itemstack.itemID == Item.book.itemID)
{
levelup(false);
return true;
}
if(itemstack.itemID == Item.slimeBall.itemID)
{
setHunger(getHunger()-1);
return true;
}
if(itemstack.itemID == Item.appleGold.itemID)
{
if(isChild())
{
setGrowingAge(-2);
return true;
}
else
{
setGrowingAge(0);
return true;
}
}
if(isTamed() && itemstack.itemID == Item.bone.itemID)
{
this.setOwner(user.username);
return true;
}
if(itemstack.itemID == Item.wheat.itemID)
{
if(getBreedInt() < EnumHoundBreed.getMaxBreeds())
setBreedInt(getBreedInt() + 1);
return true;
}
if(itemstack.itemID == Item.carrot.itemID)
{
if(getBreedInt() > 0)
setBreedInt(getBreedInt() - 1);
return true;
}
return false;
}
/**
* Tries to eat food off the ground
* @param target the food on the ground
* @return true if it was eaten
*/
private boolean tryEatItemFood(EntityItem target)
{
if (target != null && target.getEntityItem().getItem() instanceof ItemFood)
{
ItemFood food = (ItemFood) (target.getEntityItem().getItem());
if (food != null && willEatFood(food))
{
addToHunger(food.getHealAmount());
if(eatAnimation <= 0)
{
chew(food.getHealAmount() * 10);
eatAnimation = 20;
}
if(!worldObj.isRemote)
{
target.getEntityItem().stackSize--;
if (target.getEntityItem().stackSize <= 0)
{
target.setDead();
}
}
return true;
}
}
return false;
}
/**
* If the hound will eat a food, normally: this is only meat, but if the hound is half hunger
* it will eat any food
*/
private boolean willEatFood(ItemFood food)
{
return food.isWolfsFavoriteMeat() || getHunger() < getLowHunger();
}
public boolean isTempting(ItemStack item)
{
if(item != null)
{
if(item.itemID == Item.bone.itemID)
{
return true;
}
if(item.getItem() instanceof ItemFood)
{
if(((ItemFood)item.getItem()).isWolfsFavoriteMeat())
{
return true;
}
}
}
return false;
}
private int getLowHunger()
{
return isChild() ? 3 : 10;
}
/**
* Called when the hound walks over an item
*/
private void pickupItem(EntityItem item)
{
if(item == null || item.getEntityItem() == null)return;
if(getHunger() < getMaxHunger())
{
if(tryEatItemFood(item))
{
return;
}
}
ItemStack itemstack = item.getEntityItem();
if(!worldObj.isRemote && shouldPickupItems() && item.delayBeforeCanPickup <= 0 && pack.addItemStackToInventory(itemstack))
{
worldObj.playSoundAtEntity(this, "random.pop",0.2F, ((this.rand.nextFloat() - this.rand.nextFloat()) * 0.7F + 1.0F) * 2.0F);//EntityPlayer
item.getEntityItem().stackSize--;
if (item.getEntityItem().stackSize <= 0)
{
item.setDead();
}
}
}
/**
* Determines if the hound should collect items
*/
private boolean shouldPickupItems()
{
return getAvailableRows() > 0 && pickupItems && hasUnlockedPickup();
}
/**
* Determines if the hound will leap attack
*/
public boolean shouldLeapAttack()
{
return leapAttack && hasUnlockedLeap();
}
/**
* Determines if the hound will draw attention from the owner
*/
public boolean shouldBoost()
{
return boostStep && hasUnlockedBoost();
}
public boolean hasUnlockedLeap()
{
return level >= 5;
}
public boolean hasUnlockedBoost()
{
return level >= 25;
}
public boolean hasUnlockedPickup()
{
return level >= 40;
}
public boolean hasUnlockedTeleport()
{
return level >= 80;
}
/**
* Teleports the dog to coords
* @param coords the x,y,z array(must be 3 doubles)
* @return true if a teleport is successful
*/
private boolean teleport(double[] coords)
{
if(coords.length >= 3)
{
return teleport(coords[0], coords[1], coords[2]);
}
return false;
}
/**
* Teleports the dog to x, y, and z
*/
private boolean teleport(double x, double y, double z)
{
int i = MathHelper.floor_double(x);
int j = MathHelper.floor_double(z);
int k = MathHelper.floor_double(y);
if (worldObj.doesBlockHaveSolidTopSurface(i, k - 1, j) && !worldObj.isBlockNormalCube(i, k, j) && !worldObj.isBlockNormalCube(i, k + 1, j))
{
setLocationAndAngles((double)((float)(i) + 0.5F), (double)k, (double)((float)(j) + 0.5F), rotationYaw, rotationPitch);
this.getNavigator().clearPathEntity();
return true;
}
i = MathHelper.floor_double(x) - 2;
j = MathHelper.floor_double(z) - 2;
k = MathHelper.floor_double(y);
for (int l = 0; l <= 4; ++l)
{
for (int i1 = 0; i1 <= 4; ++i1)
{
if ((l < 1 || i1 < 1 || l > 3 || i1 > 3)&& worldObj.doesBlockHaveSolidTopSurface(i + l, k - 1, j + i1) && !worldObj.isBlockNormalCube(i + l, k, j + i1) && !worldObj.isBlockNormalCube(i + l, k + 1, j + i1))
{
setLocationAndAngles((double)((float)(i + l) + 0.5F), (double)k, (double)((float)(j + i1) + 0.5F), rotationYaw, rotationPitch);
this.getNavigator().clearPathEntity();
return true;
}
}
}
trySendPlayerMessage("Your Hound " + getNameString() + "Failed to find a spot to teleport");
return false;
}
public float getSpeedModifier()
{
float speed = 1.0F; //TODO rewrite speed because of FUCKING ATTRIBUTES!
if(!(cfg.disableWeight && getArmourSpeedBuff() < 0))
{
speed += getArmourSpeedBuff();
}
if(isChild())
{
speed *= 0.75F;
}
return speed;
}
/**
* Gets the amount armour effects the hound
* @return -1 for slow +1 for fast 0 for no effect
*/
private float getArmourSpeedBuff()
{
float speed = 0.0F;
ItemStack[] var2 = this.armour;
int var3 = var2.length;
for (int var4 = 0; var4 < var3; ++var4)
{
ItemStack var5 = var2[var4];
if (var5 != null && var5.getItem() instanceof IHoundArmour)
{
float var6 = ((IHoundArmour)var5.getItem()).getMobilityModifier();
speed += var6;
}
}
return speed;
}
/**
* Gets the name used in messages
* @return The custom name or nothing
*/
private String getNameString()
{
return this.hasCustomNameTag() ? ("'" + this.getCustomNameTag() + "' ") : "";
}
public boolean inPack()
{
return inPack;
}
/**
* Attepts to see if there is a large enough pack to fight in
* @return if the pack size is more than 4
*/
public boolean searchForPack()
{
int packSize = 0;
AxisAlignedBB search = this.boundingBox.expand(16D, 8D, 16D);
List<EntityHound>dogs = worldObj.getEntitiesWithinAABB(EntityHound.class, search);
Iterator dogList = dogs.iterator();
while(dogList.hasNext())
{
EntityHound dog = (EntityHound)dogList.next();
if(!dog.isTamed())
{
packSize ++;
}
}
return packSize > 4;
}
/**
* Gets the bonus to trust on how many players are in the area
*/
public float getPlayerBonus()
{
AxisAlignedBB search = this.boundingBox.expand(16D, 8D, 16D);
List<EntityHound>players = worldObj.getEntitiesWithinAABB(EntityPlayer.class, search);
int mins = 10;
return (100F / (60F * mins)) * (float)players.size();
}
public float getVillaBonus()
{
AxisAlignedBB search = this.boundingBox.expand(16D, 8D, 16D);
List<EntityHound>players = worldObj.getEntitiesWithinAABB(EntityVillager.class, search);
int mins = 10;
return (100F / (60F * mins)) * (float)players.size();
}
public boolean canTempt()
{
return !isTamed() && !inPack() && !isAngry() && trust > 25F;
}
private EnumHoundBreed getBreed()
{
return EnumHoundBreed.getBreed(getBreedInt());
}
private int getBreedInt()
{
return dataWatcher.getWatchableObjectInt(IdBase+3);
}
private void setBreedInt(int value)
{
dataWatcher.updateObject(IdBase+3, value);
}
/**
* Sets a random breed
*/
private void setRandomBreed()
{
setBreedInt(rand.nextInt(6));
refreshHealth();
}
@SideOnly(Side.CLIENT)
public String getSpots()
{
if(getBreed() != null)
{
return getBreed().spots;
}
return null;
}
private NBTTagCompound getNBT(ItemStack itemstack)
{
if(!itemstack.hasTagCompound())
{
itemstack.setTagCompound(new NBTTagCompound());
}
return itemstack.getTagCompound();
}
private boolean onUseTrade(EntityPlayer user, ItemStack item)
{
if(item.hasTagCompound() && item.getTagCompound().hasKey("TradedHound"))
{
if(!(getOwnerName() != null && user.username == getOwnerName()) && item.getTagCompound().getInteger("TradedHound") == ID)
{
setOwner(user.username);
user.inventory.setInventorySlotContents(user.inventory.currentItem, (ItemStack)null);
user.addChatMessage("This hound " + getNameString() + "is now yours!");
return true;
}
}
if(getOwner() != null && getOwner() == user) // IF CAN TRADE
{
getNBT(item).setInteger("TradedHound", ID);
String name = (this.getNameString().length() > 0) ? this.getNameString() : "(Unnamed)";
item.setItemName("Hound Trade: " + name);
return true;
}
return false;
}
public boolean canSeeName(EntityPlayer observer)
{
Vec3 vec3 = observer.getLook(1.0F).normalize();
Vec3 vec31 = this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX - observer.posX, this.boundingBox.minY + (double)(this.height / 2.0F) - (observer.posY + (double)observer.getEyeHeight()), this.posZ - observer.posZ);
double d0 = vec31.lengthVector();
vec31 = vec31.normalize();
double d1 = vec3.dotProduct(vec31);
return d1 > 1.0D - 0.025D / d0 ? observer.canEntityBeSeen(this) : false;
}
public boolean shouldDefendOwner(EntityLivingBase tar)
{
return attackDefense;
}
@Override
public boolean allowLeashing()
{
if(!isTamed())
{
return canTempt();
}
return super.allowLeashing();
}
@Override
public float getBlockPathWeight(int x, int y, int z)
{
if(worldObj.getBlockMaterial(x, y, z) == Material.fire || worldObj.getBlockMaterial(x, y, z) == Material.lava)
{
return 0F;
}
if(worldObj.getBlockMaterial(x, y, z) == Material.water && isBurning())
{
return 20F;
}
TileEntity block = worldObj.getBlockTileEntity(x, y, z);
if(block != null && block instanceof IHeatSource)
{
IHeatSource src = (IHeatSource)block;
if(src.getHeat() > 0)
{
return 0F;
}
}
return super.getBlockPathWeight(x, y, z);
}
@Override
public void setItem(ItemStack item, int slot)
{
armour[slot] = item;
}
@Override
public Entity getOwner() {
MinecraftServer server = MinecraftServer.getServer();
Entity entity = server.getConfigurationManager().getPlayerForUsername(this.getOwnerName());
return entity;
}
}