package joshie.mariculture.modules.fishery.entity;
import joshie.mariculture.api.MaricultureAPI;
import joshie.mariculture.api.fishing.FishingTrait;
import joshie.mariculture.modules.fishery.Fishery;
import joshie.mariculture.modules.fishery.utils.FishingRodHelper;
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.EntityItem;
import net.minecraft.entity.item.EntityXPOrb;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.projectile.EntityFishHook;
import net.minecraft.init.Blocks;
import net.minecraft.init.SoundEvents;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.math.*;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import net.minecraft.world.storage.loot.LootContext;
import java.util.List;
/**
* This class exists simply because vanilla checks for fishing rod instead of instanceof ItemFishingRod
**/
public class EntityFishHookMC extends EntityFishHook {
private ItemStack bait;
public EntityFishHookMC(World world, EntityPlayer player, ItemStack bait) {
super(world, player);
this.bait = bait;
}
@SuppressWarnings("unused")
public EntityFishHookMC(World world) {
super(world);
}
@Override
@SuppressWarnings("StatementWithEmptyBody")
public void onUpdate() {
if (worldObj.isRemote) {
int i = getDataManager().get(DATA_HOOKED_ENTITY);
if (i > 0 && caughtEntity == null) {
caughtEntity = worldObj.getEntityByID(i - 1);
}
} else {
if (angler == null || angler.isDead || !angler.isEntityAlive() || angler.getHeldItemMainhand() == null || angler.getHeldItemMainhand().getItem() != Fishery.FISHING_ROD || getDistanceSqToEntity(angler) > 1024.0D) {
setDead();
if (angler != null) angler.fishEntity = null;
return;
}
}
if (caughtEntity != null) {
if (!caughtEntity.isDead) {
posX = caughtEntity.posX;
double d17 = (double) caughtEntity.height;
posY = caughtEntity.getEntityBoundingBox().minY + d17 * 0.8D;
posZ = caughtEntity.posZ;
return;
}
caughtEntity = null;
}
if (fishPosRotationIncrements > 0) {
double d3 = posX + (fishX - posX) / (double) fishPosRotationIncrements;
double d4 = posY + (fishY - posY) / (double) fishPosRotationIncrements;
double d6 = posZ + (fishZ - posZ) / (double) fishPosRotationIncrements;
double d8 = MathHelper.wrapDegrees(fishYaw - (double) rotationYaw);
rotationYaw = (float) ((double) rotationYaw + d8 / (double) fishPosRotationIncrements);
rotationPitch = (float) ((double) rotationPitch + (fishPitch - (double) rotationPitch) / (double) fishPosRotationIncrements);
--fishPosRotationIncrements;
setPosition(d3, d4, d6);
setRotation(rotationYaw, rotationPitch);
} else {
if (inGround) {
if (worldObj.getBlockState(field_189740_d).getBlock() == inTile) {
++ticksInGround;
if (ticksInGround == 1200) {
setDead();
}
return;
}
inGround = false;
motionX *= (double) (rand.nextFloat() * 0.2F);
motionY *= (double) (rand.nextFloat() * 0.2F);
motionZ *= (double) (rand.nextFloat() * 0.2F);
ticksInGround = 0;
ticksInAir = 0;
} else {
++ticksInAir;
}
if (!worldObj.isRemote) {
Vec3d vec3d1 = new Vec3d(posX, posY, posZ);
Vec3d vec3d = new Vec3d(posX + motionX, posY + motionY, posZ + motionZ);
RayTraceResult raytraceresult = worldObj.rayTraceBlocks(vec3d1, vec3d);
vec3d1 = new Vec3d(posX, posY, posZ);
vec3d = new Vec3d(posX + motionX, posY + motionY, posZ + motionZ);
if (raytraceresult != null) {
vec3d = new Vec3d(raytraceresult.hitVec.xCoord, raytraceresult.hitVec.yCoord, raytraceresult.hitVec.zCoord);
}
Entity entity = null;
List<Entity> list = worldObj.getEntitiesWithinAABBExcludingEntity(this, getEntityBoundingBox().addCoord(motionX, motionY, motionZ).expandXyz(1.0D));
double d0 = 0.0D;
for (Entity entity1: list) {
if (entity1.canBeCollidedWith() && (entity1 != angler || ticksInAir >= 5)) {
AxisAlignedBB axisalignedbb1 = entity1.getEntityBoundingBox().expandXyz(0.30000001192092896D);
RayTraceResult raytraceresult1 = axisalignedbb1.calculateIntercept(vec3d1, vec3d);
if (raytraceresult1 != null) {
double d1 = vec3d1.squareDistanceTo(raytraceresult1.hitVec);
if (d1 < d0 || d0 == 0.0D) {
entity = entity1;
d0 = d1;
}
}
}
}
if (entity != null) {
raytraceresult = new RayTraceResult(entity);
}
if (raytraceresult != null) {
if (raytraceresult.entityHit != null) {
caughtEntity = raytraceresult.entityHit;
getDataManager().set(DATA_HOOKED_ENTITY, caughtEntity.getEntityId() + 1);
} else {
inGround = true;
}
}
}
if (!inGround) {
moveEntity(motionX, motionY, motionZ);
float f2 = MathHelper.sqrt_double(motionX * motionX + motionZ * motionZ);
rotationYaw = (float) (MathHelper.atan2(motionX, motionZ) * (180D / Math.PI));
for (rotationPitch = (float) (MathHelper.atan2(motionY, (double) f2) * (180D / Math.PI)); rotationPitch - prevRotationPitch < -180.0F; prevRotationPitch -= 360.0F) {}
while (rotationPitch - prevRotationPitch >= 180.0F) {
prevRotationPitch += 360.0F;
}
while (rotationYaw - prevRotationYaw < -180.0F) {
prevRotationYaw -= 360.0F;
}
while (rotationYaw - prevRotationYaw >= 180.0F) {
prevRotationYaw += 360.0F;
}
rotationPitch = prevRotationPitch + (rotationPitch - prevRotationPitch) * 0.2F;
rotationYaw = prevRotationYaw + (rotationYaw - prevRotationYaw) * 0.2F;
float f3 = 0.92F;
if (onGround || isCollidedHorizontally) {
f3 = 0.5F;
}
int k = 5;
double d5 = 0.0D;
for (int l = 0; l < k; ++l) {
AxisAlignedBB axisalignedbb = getEntityBoundingBox();
double d9 = axisalignedbb.maxY - axisalignedbb.minY;
double d10 = axisalignedbb.minY + d9 * (double) l / (double) k;
double d11 = axisalignedbb.minY + d9 * (double) (l + 1) / (double) k;
AxisAlignedBB axisalignedbb2 = new AxisAlignedBB(axisalignedbb.minX, d10, axisalignedbb.minZ, axisalignedbb.maxX, d11, axisalignedbb.maxZ);
if (worldObj.isAABBInMaterial(axisalignedbb2, Material.WATER)) {
d5 += 1.0D / (double) k;
}
}
if (!worldObj.isRemote && d5 > 0.0D) {
WorldServer worldserver = (WorldServer) worldObj;
int i1 = 1;
BlockPos blockpos = (new BlockPos(this)).up();
if (rand.nextFloat() < 0.25F && worldObj.isRainingAt(blockpos)) {
i1 = 2;
}
if (rand.nextFloat() < 0.5F && !worldObj.canSeeSky(blockpos)) {
--i1;
}
if (ticksCatchable > 0) {
--ticksCatchable;
if (ticksCatchable <= 0) {
ticksCaughtDelay = 0;
ticksCatchableDelay = 0;
}
} else if (ticksCatchableDelay > 0) {
ticksCatchableDelay -= i1;
if (ticksCatchableDelay <= 0) {
motionY -= 0.20000000298023224D;
playSound(SoundEvents.ENTITY_BOBBER_SPLASH, 0.25F, 1.0F + (rand.nextFloat() - rand.nextFloat()) * 0.4F);
float f6 = (float) MathHelper.floor_double(getEntityBoundingBox().minY);
worldserver.spawnParticle(EnumParticleTypes.WATER_BUBBLE, posX, (double) (f6 + 1.0F), posZ, (int) (1.0F + width * 20.0F), (double) width, 0.0D, (double) width, 0.20000000298023224D);
worldserver.spawnParticle(EnumParticleTypes.WATER_WAKE, posX, (double) (f6 + 1.0F), posZ, (int) (1.0F + width * 20.0F), (double) width, 0.0D, (double) width, 0.20000000298023224D);
ticksCatchable = MathHelper.getRandomIntegerInRange(rand, 10, 30);
} else {
fishApproachAngle = (float) ((double) fishApproachAngle + rand.nextGaussian() * 4.0D);
float f5 = fishApproachAngle * 0.017453292F;
float f8 = MathHelper.sin(f5);
float f10 = MathHelper.cos(f5);
double d13 = posX + (double) (f8 * (float) ticksCatchableDelay * 0.1F);
double d15 = (double) ((float) MathHelper.floor_double(getEntityBoundingBox().minY) + 1.0F);
double d16 = posZ + (double) (f10 * (float) ticksCatchableDelay * 0.1F);
Block block1 = worldserver.getBlockState(new BlockPos((int) d13, (int) d15 - 1, (int) d16)).getBlock();
if (block1 == Blocks.WATER || block1 == Blocks.FLOWING_WATER) {
if (rand.nextFloat() < 0.15F) {
worldserver.spawnParticle(EnumParticleTypes.WATER_BUBBLE, d13, d15 - 0.10000000149011612D, d16, 1, (double) f8, 0.1D, (double) f10, 0.0D);
}
float f = f8 * 0.04F;
float f1 = f10 * 0.04F;
worldserver.spawnParticle(EnumParticleTypes.WATER_WAKE, d13, d15, d16, 0, (double) f1, 0.01D, (double) (-f), 1.0D);
worldserver.spawnParticle(EnumParticleTypes.WATER_WAKE, d13, d15, d16, 0, (double) (-f1), 0.01D, (double) f, 1.0D);
}
}
} else if (ticksCaughtDelay > 0) {
ticksCaughtDelay -= i1;
float f4 = 0.15F;
if (ticksCaughtDelay < 20) {
f4 = (float) ((double) f4 + (double) (20 - ticksCaughtDelay) * 0.05D);
} else if (ticksCaughtDelay < 40) {
f4 = (float) ((double) f4 + (double) (40 - ticksCaughtDelay) * 0.02D);
} else if (ticksCaughtDelay < 60) {
f4 = (float) ((double) f4 + (double) (60 - ticksCaughtDelay) * 0.01D);
}
if (rand.nextFloat() < f4) {
float f7 = MathHelper.randomFloatClamp(rand, 0.0F, 360.0F) * 0.017453292F;
float f9 = MathHelper.randomFloatClamp(rand, 25.0F, 60.0F);
double d12 = posX + (double) (MathHelper.sin(f7) * f9 * 0.1F);
double d14 = (double) ((float) MathHelper.floor_double(getEntityBoundingBox().minY) + 1.0F);
double d2 = posZ + (double) (MathHelper.cos(f7) * f9 * 0.1F);
Block block = worldserver.getBlockState(new BlockPos((int) d12, (int) d14 - 1, (int) d2)).getBlock();
if (block == Blocks.WATER || block == Blocks.FLOWING_WATER) {
worldserver.spawnParticle(EnumParticleTypes.WATER_SPLASH, d12, d14, d2, 2 + rand.nextInt(2), 0.10000000149011612D, 0.0D, 0.10000000149011612D, 0.0D);
}
}
if (ticksCaughtDelay <= 0) {
fishApproachAngle = MathHelper.randomFloatClamp(rand, 0.0F, 360.0F);
ticksCatchableDelay = MathHelper.getRandomIntegerInRange(rand, 20, 80);
}
} else {
ticksCaughtDelay = MathHelper.getRandomIntegerInRange(rand, 100, 900);
ticksCaughtDelay -= EnchantmentHelper.getLureModifier(angler) * 20 * 5;
}
if (ticksCatchable > 0) {
motionY -= (double) (rand.nextFloat() * rand.nextFloat() * rand.nextFloat()) * 0.2D;
}
}
double d7 = d5 * 2.0D - 1.0D;
motionY += 0.03999999910593033D * d7;
if (d5 > 0.0D) {
f3 = (float) ((double) f3 * 0.9D);
motionY *= 0.8D;
}
motionX *= (double) f3;
motionY *= (double) f3;
motionZ *= (double) f3;
setPosition(posX, posY, posZ);
}
}
}
@Override
public int handleHookRetraction() {
if (worldObj.isRemote) {
return 0;
} else {
int i = 0;
if (caughtEntity != null) {
bringInHookedEntity();
worldObj.setEntityState(this, (byte) 31);
i = caughtEntity instanceof EntityItem ? 3 : 5;
} else if (ticksCatchable > 0) {
LootContext.Builder lootcontext$builder = new LootContext.Builder((WorldServer) worldObj);
float luck = (float) EnchantmentHelper.getLuckOfSeaModifier(angler) + angler.getLuck();
for (FishingTrait trait: FishingRodHelper.getTraits(angler.getHeldItemMainhand())) {
luck = trait.modifyLuck(angler, rand, luck);
}
lootcontext$builder.withLuck(luck);
lootcontext$builder.withPlayer(angler);
lootcontext$builder.withLootedEntity(this);
for (ItemStack itemstack : worldObj.getLootTableManager().getLootTableFromLocation(MaricultureAPI.fishing.getLootTableFromBait(bait)).generateLootForPools(rand, lootcontext$builder.build())) {
EntityItem entityitem = new EntityItem(worldObj, posX, posY, posZ, itemstack);
double d0 = angler.posX - posX;
double d1 = angler.posY - posY;
double d2 = angler.posZ - posZ;
double d3 = (double) MathHelper.sqrt_double(d0 * d0 + d1 * d1 + d2 * d2);
double d4 = 0.1D;
entityitem.motionX = d0 * d4;
entityitem.motionY = d1 * d4 + (double) MathHelper.sqrt_double(d3) * 0.08D;
entityitem.motionZ = d2 * d4;
worldObj.spawnEntityInWorld(entityitem);
int xp = rand.nextInt(6) + 1;
for (FishingTrait trait: FishingRodHelper.getTraits(angler.getHeldItemMainhand())) {
xp = trait.modifyXP(angler, itemstack, rand, xp);
}
angler.worldObj.spawnEntityInWorld(new EntityXPOrb(angler.worldObj, angler.posX, angler.posY + 0.5D, angler.posZ + 0.5D, xp));
}
i = 1;
}
if (inGround) {
i = 2;
}
setDead();
angler.fishEntity = null;
return i;
}
}
@Override
public void writeEntityToNBT(NBTTagCompound compound) {
super.writeEntityToNBT(compound);
if (bait != null) {
compound.setTag("Bait", bait.writeToNBT(new NBTTagCompound()));
}
}
@Override
public void readEntityFromNBT(NBTTagCompound compound) {
super.readEntityFromNBT(compound);
if (compound.hasKey("Bait")) {
bait = ItemStack.loadItemStackFromNBT(compound.getCompoundTag("Bait"));
}
}
}