package joshie.harvest.asm.transformers;
import joshie.harvest.fishing.FishingHelper;
import joshie.harvest.fishing.item.ItemFish;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.EntityBoat;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.item.EntityXPOrb;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.projectile.EntityFishHook;
import net.minecraft.init.Enchantments;
import net.minecraft.init.Items;
import net.minecraft.init.SoundEvents;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.stats.StatList;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.math.*;
import net.minecraft.world.World;
import net.minecraft.world.biome.Biome;
import net.minecraftforge.fml.common.registry.IThrowableEntity;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import java.util.List;
public class EntityCustomFishHook extends EntityFishHook implements IThrowableEntity {
public int shake;
public EntityPlayer angler;
public Entity bobber;
private int xTile;
private int yTile;
private int zTile;
private Block inTile;
private boolean inGround;
private int ticksInGround;
private int ticksInAir;
private int baseCatchTime = 300;
private int ticksCatchable;
private int fishPosRotationIncrements;
private double fishX;
private double fishY;
private double fishZ;
private double fishYaw;
private double fishPitch;
@SideOnly(Side.CLIENT)
private double velocityX;
@SideOnly(Side.CLIENT)
private double velocityY;
@SideOnly(Side.CLIENT)
private double velocityZ;
private boolean isAdmin = false;
@SideOnly(Side.CLIENT)
public EntityCustomFishHook(World par1World, double par2, double par4, double par6, EntityPlayer par8EntityPlayer) {
super(par1World, par2, par4, par6, par8EntityPlayer);
this.setPosition(par2, par4, par6);
this.ignoreFrustumCheck = true;
this.angler = par8EntityPlayer;
par8EntityPlayer.fishEntity = this;
this.xTile = -1;
this.yTile = -1;
this.zTile = -1;
this.inGround = false;
this.shake = 0;
this.ticksInAir = 0;
this.ticksCatchable = 0;
this.bobber = null;
this.setSize(0.25F, 0.25F);
this.ignoreFrustumCheck = true;
}
public EntityCustomFishHook(World par1World, EntityPlayer par2EntityPlayer) {
super(par1World, par2EntityPlayer);
this.xTile = -1;
this.yTile = -1;
this.zTile = -1;
this.inGround = false;
this.shake = 0;
this.ticksInAir = 0;
this.ticksCatchable = 0;
this.bobber = null;
this.ignoreFrustumCheck = true;
this.angler = par2EntityPlayer;
this.angler.fishEntity = this;
this.setSize(0.25F, 0.25F);
this.setLocationAndAngles(par2EntityPlayer.posX, par2EntityPlayer.posY + par2EntityPlayer.getEyeHeight(), par2EntityPlayer.posZ, par2EntityPlayer.rotationYaw, par2EntityPlayer.rotationPitch);
this.posX -= MathHelper.cos(this.rotationYaw / 180.0F * (float) Math.PI) * 0.16F;
this.posY -= 0.10000000149011612D;
this.posZ -= MathHelper.sin(this.rotationYaw / 180.0F * (float) Math.PI) * 0.16F;
this.setPosition(this.posX, this.posY, this.posZ);
float f = 0.4F;
this.motionX = -MathHelper.sin(this.rotationYaw / 180.0F * (float) Math.PI) * MathHelper.cos(this.rotationPitch / 180.0F * (float) Math.PI) * f;
this.motionZ = MathHelper.cos(this.rotationYaw / 180.0F * (float) Math.PI) * MathHelper.cos(this.rotationPitch / 180.0F * (float) Math.PI) * f;
this.motionY = -MathHelper.sin(this.rotationPitch / 180.0F * (float) Math.PI) * f;
int shortCast = 0;
int longCast = 1;
float velocity = 1.5F;
if (shortCast > 0) {
velocity *= (0.1F * shortCast);
}
if (longCast > 0) {
velocity += velocity * (0.2F * longCast);
}
this.calculateVelocity(this.motionX, this.motionY, this.motionZ, velocity, 1.0F);
}
public EntityCustomFishHook(World world, EntityPlayer entityplayer, boolean b) {
this(world, entityplayer);
isAdmin = b;
}
public EntityCustomFishHook(World world) {
this(world, null);
// TODO: change when forge fixes entity entry.
}
public void setBaseCatchTime(int amount) {
this.baseCatchTime = amount;
}
@Override
protected void entityInit() {
}
public void calculateVelocity(double par1, double par3, double par5, float par7, float par8) {
float f2 = 1;
par1 /= f2;
par3 /= f2;
par5 /= f2;
par1 += this.rand.nextGaussian() * 0.007499999832361937D * par8;
par3 += this.rand.nextGaussian() * 0.007499999832361937D * par8;
par5 += this.rand.nextGaussian() * 0.007499999832361937D * par8;
par1 *= par7;
par3 *= par7;
par5 *= par7;
this.motionX = par1;
this.motionY = par3;
this.motionZ = par5;
float f3 = 1;
this.prevRotationYaw = this.rotationYaw = (float) (Math.atan2(par1, par5) * 180.0D / Math.PI);
this.prevRotationPitch = this.rotationPitch = (float) (Math.atan2(par3, f3) * 180.0D / Math.PI);
this.ticksInGround = 0;
}
@Override
@SideOnly(Side.CLIENT)
/**
* Sets the position and rotation. Only difference from the other one is no bounding on the rotation. Args: posX,
* posY, posZ, yaw, pitch
*/
public void setPositionAndRotationDirect(double par1, double par3, double par5, float par7, float par8, int par9, boolean p_180426_10_) {
this.fishX = par1;
this.fishY = par3;
this.fishZ = par5;
this.fishYaw = par7;
this.fishPitch = par8;
this.fishPosRotationIncrements = par9;
this.motionX = this.velocityX;
this.motionY = this.velocityY;
this.motionZ = this.velocityZ;
}
@Override
@SideOnly(Side.CLIENT)
/**
* Sets the velocity to the args. Args: x, y, z
*/
public void setVelocity(double par1, double par3, double par5) {
this.velocityX = this.motionX = par1;
this.velocityY = this.motionY = par3;
this.velocityZ = this.motionZ = par5;
}
public boolean isFishingRod(ItemStack stack) {
return true;
}
/**
* Called to update the entity's position/logic.
*/
@Override
public void onUpdate() {
// super.onUpdate();
if (!worldObj.isRemote && this.angler == null)
this.setDead();
this.onEntityUpdate();
if (this.fishPosRotationIncrements > 0) {
double d0 = this.posX + (this.fishX - this.posX) / this.fishPosRotationIncrements;
double d1 = this.posY + (this.fishY - this.posY) / this.fishPosRotationIncrements;
double d2 = this.posZ + (this.fishZ - this.posZ) / this.fishPosRotationIncrements;
double d3 = MathHelper.wrapDegrees(this.fishYaw - this.rotationYaw);
this.rotationYaw = (float) (this.rotationYaw + d3 / this.fishPosRotationIncrements);
this.rotationPitch = (float) (this.rotationPitch + (this.fishPitch - this.rotationPitch) / this.fishPosRotationIncrements);
--this.fishPosRotationIncrements;
this.setPosition(d0, d1, d2);
this.setRotation(this.rotationYaw, this.rotationPitch);
} else {
if (!this.worldObj.isRemote && this.angler != null) {
ItemStack itemstack = this.angler.getHeldItemMainhand();
if (this.angler.isDead || !this.angler.isEntityAlive() || itemstack == null || !this.isFishingRod(itemstack) || this.getDistanceSqToEntity(this.angler) > 4 * 1024.0D) {
this.setDead();
this.angler.fishEntity = null;
return;
}
if (this.bobber != null) {
if (!this.bobber.isDead) {
this.posX = this.bobber.posX;
this.posY = this.bobber.getEntityBoundingBox().minY + this.bobber.height * 0.8D;
this.posZ = this.bobber.posZ;
return;
}
this.bobber = null;
}
}
if (this.shake > 0) {
--this.shake;
}
if (this.inGround) {
Block block = this.worldObj.getBlockState(new BlockPos(this.xTile, this.yTile, this.zTile)).getBlock();
if (block == this.inTile) {
++this.ticksInGround;
if (this.ticksInGround == 1200) {
this.setDead();
}
return;
}
this.inGround = false;
this.motionX *= this.rand.nextFloat() * 0.2F;
this.motionY *= this.rand.nextFloat() * 0.2F;
this.motionZ *= this.rand.nextFloat() * 0.2F;
this.ticksInGround = 0;
this.ticksInAir = 0;
} else {
++this.ticksInAir;
}
Vec3d vec3 = new Vec3d(this.posX, this.posY, this.posZ);
Vec3d vec31 = new Vec3d(this.posX + this.motionX, this.posY + this.motionY, this.posZ + this.motionZ);
RayTraceResult rayTraceResult = this.worldObj.rayTraceBlocks(vec3, vec31);
vec31 = new Vec3d(this.posX + this.motionX, this.posY + this.motionY, this.posZ + this.motionZ);
if (rayTraceResult != null) {
vec31 = new Vec3d(rayTraceResult.hitVec.xCoord, rayTraceResult.hitVec.yCoord, rayTraceResult.hitVec.zCoord);
}
Entity entity = null;
List<Entity> list = this.worldObj.getEntitiesWithinAABBExcludingEntity(this, this.getEntityBoundingBox().addCoord(this.motionX, this.motionY, this.motionZ).expand(1.0D, 1.0D, 1.0D));
double d4 = 0.0D;
double d5;
for (int j = 0; j < list.size(); ++j) {
Entity entity1 = list.get(j);
if (entity1.canBeCollidedWith() && (entity1 != this.angler || this.ticksInAir >= 5)) {
float f = 0.3F;
AxisAlignedBB axisalignedbb = entity1.getEntityBoundingBox().expand(f, f, f);
RayTraceResult rayTraceResult1 = axisalignedbb.calculateIntercept(vec3, vec31);
if (rayTraceResult1 != null) {
d5 = vec3.distanceTo(rayTraceResult1.hitVec);
if (d5 < d4 || d4 == 0.0D) {
entity = entity1;
d4 = d5;
}
}
}
}
if (entity != null) {
rayTraceResult = new RayTraceResult(entity);
}
if (rayTraceResult != null) {
if (rayTraceResult.entityHit != null && this.angler != null) {
if (!(rayTraceResult.entityHit instanceof EntityBoat) && (this.angler.capabilities.isCreativeMode)) {
if (rayTraceResult.entityHit.attackEntityFrom(DamageSource.causeThrownDamage(this, this.angler), 0)) {
this.bobber = rayTraceResult.entityHit;
}
}
} else {
this.inGround = true;
}
}
if (!this.inGround) {
//this.move(MoverType.SELF, this.motionX, this.motionY, this.motionZ);
float f1 = 1;
this.rotationYaw = (float) (Math.atan2(this.motionX, this.motionZ) * 180.0D / Math.PI);
for (this.rotationPitch = (float) (Math.atan2(this.motionY, f1) * 180.0D / Math.PI); this.rotationPitch - this.prevRotationPitch < -180.0F; this.prevRotationPitch -= 360.0F) {
;
}
while (this.rotationPitch - this.prevRotationPitch >= 180.0F) {
this.prevRotationPitch += 360.0F;
}
while (this.rotationYaw - this.prevRotationYaw < -180.0F) {
this.prevRotationYaw -= 360.0F;
}
while (this.rotationYaw - this.prevRotationYaw >= 180.0F) {
this.prevRotationYaw += 360.0F;
}
this.rotationPitch = this.prevRotationPitch + (this.rotationPitch - this.prevRotationPitch) * 0.2F;
this.rotationYaw = this.prevRotationYaw + (this.rotationYaw - this.prevRotationYaw) * 0.2F;
float f2 = 0.92F;
if (this.onGround || this.isCollidedHorizontally) {
f2 = 0.5F;
}
byte b0 = 5;
double d6 = 0.0D;
for (int k = 0; k < b0; ++k) {
AxisAlignedBB boundingBox = this.getEntityBoundingBox();
double d7 = boundingBox.minY + (boundingBox.maxY - boundingBox.minY) * (k + 0) / b0 - 0.125D + 0.125D;
double d8 = boundingBox.minY + (boundingBox.maxY - boundingBox.minY) * (k + 1) / b0 - 0.125D + 0.125D;
AxisAlignedBB axisalignedbb1 = new AxisAlignedBB(boundingBox.minX, d7, boundingBox.minZ, boundingBox.maxX, d8, boundingBox.maxZ);
if (this.worldObj.isMaterialInBB(axisalignedbb1, Material.WATER)) {
d6 += 1.0D / b0;
}
}
if (d6 > 0.0D) {
if (this.ticksCatchable > 0) {
--this.ticksCatchable;
} else {
BlockPos blockpos = (new BlockPos(this)).up();
short biteChance = (short) (baseCatchTime / 4);
if (this.worldObj.isRainingAt(blockpos)) {
biteChance = (short) (biteChance * 0.5);
}
if (this.angler != null) {
int efficiency = EnchantmentHelper.getEnchantmentLevel(Enchantments.EFFICIENCY, this.angler.getHeldItemMainhand());
biteChance *= 1.0 - 0.1 * efficiency;
}
if (this.rand.nextInt(biteChance) == 0) {
this.ticksCatchable = this.rand.nextInt(30) + 10;
if (this.angler != null) {
int barbed = 1;
ticksCatchable += 4 * barbed;
}
if (this.angler != null) {
int loot = EnchantmentHelper.getEnchantmentLevel(Enchantments.FORTUNE, this.angler.getHeldItemMainhand());
ticksCatchable += 4 * loot;
}
this.motionY -= 0.20000000298023224D;
this.playSound(SoundEvents.ENTITY_BOBBER_SPLASH, 0.25F, 1.0F + (this.rand.nextFloat() - this.rand.nextFloat()) * 0.4F);
// this.playSound("note.harp", 0.55F, 1.0F + (this.rand.nextFloat() - this.rand.nextFloat()) * 0.4F);
// this.playSoundEffect((double)par2 + 0.5D, (double)par3 + 0.5D, (double)par4 + 0.5D, "note." + "harp", 3.0F, 1);
// this.worldObj.spawnParticle("note", posX, posY + 1.2D, posZ, (double)16 / 24.0D, 0.0D, 0.0D);
float f3 = 1;
int l;
float f4;
float f5;
for (l = 0; l < 1.0F + this.width * 20.0F; ++l) {
f5 = (this.rand.nextFloat() * 2.0F - 1.0F) * this.width;
f4 = (this.rand.nextFloat() * 2.0F - 1.0F) * this.width;
this.worldObj.spawnParticle(EnumParticleTypes.WATER_BUBBLE, this.posX + f5, f3 + 1.0F, this.posZ + f4, this.motionX, this.motionY - this.rand.nextFloat() * 0.2F, this.motionZ);
}
for (l = 0; l < 1.0F + this.width * 20.0F; ++l) {
f5 = (this.rand.nextFloat() * 2.0F - 1.0F) * this.width;
f4 = (this.rand.nextFloat() * 2.0F - 1.0F) * this.width;
this.worldObj.spawnParticle(EnumParticleTypes.WATER_WAKE, this.posX + f5, f3 + 1.0F, this.posZ + f4, this.motionX, this.motionY, this.motionZ);
}
}
}
}
if (this.ticksCatchable > 0) {
this.motionY -= this.rand.nextFloat() * this.rand.nextFloat() * this.rand.nextFloat() * 0.2D;
}
d5 = d6 * 2.0D - 1.0D;
this.motionY += 0.03999999910593033D * d5;
if (d6 > 0.0D) {
f2 = (float) (f2 * 0.9D);
this.motionY *= 0.8D;
}
this.motionX *= f2;
this.motionY *= f2;
this.motionZ *= f2;
this.setPosition(this.posX, this.posY, this.posZ);
}
}
}
/**
* (abstract) Protected helper method to write subclass entity data to NBT.
*/
@Override
public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
par1NBTTagCompound.setShort("xTile", (short) this.xTile);
par1NBTTagCompound.setShort("yTile", (short) this.yTile);
par1NBTTagCompound.setShort("zTile", (short) this.zTile);
par1NBTTagCompound.setByte("inTile", (byte) Block.getIdFromBlock(this.inTile));
par1NBTTagCompound.setByte("shake", (byte) this.shake);
par1NBTTagCompound.setByte("inGround", (byte) (this.inGround ? 1 : 0));
}
/**
* (abstract) Protected helper method to read subclass entity data from NBT.
*/
@Override
public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
this.xTile = par1NBTTagCompound.getShort("xTile");
this.yTile = par1NBTTagCompound.getShort("yTile");
this.zTile = par1NBTTagCompound.getShort("zTile");
this.inTile = Block.getBlockById(par1NBTTagCompound.getByte("inTile") & 255);
this.shake = par1NBTTagCompound.getByte("shake") & 255;
this.inGround = par1NBTTagCompound.getByte("inGround") == 1;
}
/*
@Override
@SideOnly(Side.CLIENT)
public float getShadowSize() {
return 0.0F;
}
*/
@Override
public int handleHookRetraction() {
if (this.worldObj.isRemote) {
return 0;
} else {
byte b0 = 0;
if (this.bobber != null) {
double d0 = this.angler.posX - this.posX;
double d1 = this.angler.posY - this.posY;
double d2 = this.angler.posZ - this.posZ;
double d3 = 1;
double d4 = 0.1D;
this.bobber.motionX += d0 * d4;
this.bobber.motionY += d1 * d4 + 1;
this.bobber.motionZ += d2 * d4;
b0 = 3;
} else if (this.ticksCatchable > 0 || isAdmin) {
Biome currentBiome = worldObj.getBiome(new BlockPos(1, 0, 2));
ItemStack fishLoot;
int count = 1;
float doubleOdds = 0;
int doubleHook = 1;
if (doubleHook > 0) {
doubleOdds = 0.1F * doubleHook;
if (Math.random() < doubleOdds)
count++;
}
do {
float fishOdds = 0.5F;
int magnetic = 1;
int appealing = 1;
if (magnetic > 0) {
fishOdds -= (0.08 * magnetic);
} else if (appealing > 0) {
fishOdds += (0.08 * appealing);
}
float roll = (float) Math.random();
int heavyLine = 0;
if (this.angler != null) {
heavyLine = 1;
}
if (roll < fishOdds) {
if ((this.angler.getHeldItemMainhand().getItem() instanceof ItemFish) && this.angler.isSneaking())
fishLoot = null;
else
fishLoot = null;
} else {
fishLoot = new ItemStack(Items.APPLE);
}
if (fishLoot != null) {
FishingHelper.track(fishLoot, angler);
EntityItem entityitem = new EntityItem(worldObj, posX, posY, posZ, fishLoot);
double d5 = this.angler.posX - this.posX;
double d6 = this.angler.posY - this.posY;
double d7 = this.angler.posZ - this.posZ;
double d8 = 1;
double d9 = 0.1D;
entityitem.motionX = d5 * d9;
entityitem.motionY = d6 * d9 + 1;
entityitem.motionZ = d7 * d9;
this.worldObj.spawnEntityInWorld(entityitem);
this.angler.addStat(StatList.FISH_CAUGHT, 1);
this.angler.worldObj.spawnEntityInWorld(new EntityXPOrb(this.angler.worldObj, this.angler.posX, this.angler.posY + 0.5D, this.angler.posZ + 0.5D, this.rand.nextInt(6) + 1));
b0 = 1;
}
count--;
} while (count > 0);
}
if (this.inGround) {
b0 = 2;
}
this.setDead();
this.angler.fishEntity = null;
return b0;
}
}
/**
* Will get destroyed next tick.
*/
@Override
public void setDead() {
super.setDead();
if (this.angler != null) {
this.angler.fishEntity = null;
}
}
@Override
public Entity getThrower() {
return this.angler;
}
@Override
public void setThrower(Entity entity) {
// do nothing
}
}