package mhfc.net.common.entity.projectile; import java.util.List; import cpw.mods.fml.common.registry.IThrowableEntity; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import mhfc.net.MHFCMain; import net.minecraft.block.Block; import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.monster.EntityEnderman; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.entity.projectile.EntityArrow; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.play.server.S2BPacketChangeGameState; import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.MathHelper; import net.minecraft.util.MovingObjectPosition; import net.minecraft.util.Vec3; import net.minecraft.world.World; public abstract class EntityProjectile extends EntityArrow implements IThrowableEntity { public static final int NO_PICKUP = 0, PICKUP_ALL = 1, PICKUP_CREATIVE = 2, PICKUP_OWNER = 3; protected int xTile; protected int yTile; protected int zTile; protected Block inTile; protected int inData; protected boolean inGround; public int pickupMode; protected int ticksInGround; protected int ticksInAir; public boolean beenInGround; public float extraDamage; public int knockBack; public EntityProjectile(World world) { super(world); xTile = -1; yTile = -1; zTile = -1; inTile = null; inData = 0; inGround = false; arrowShake = 0; ticksInAir = 0; yOffset = 0F; pickupMode = EntityProjectile.NO_PICKUP; extraDamage = 0; knockBack = 0; setSize(0.5F, 0.5F); } @Override protected void entityInit() { super.entityInit(); } @Override public Entity getThrower() { return shootingEntity; } @Override public void setThrower(Entity entity) { shootingEntity = entity; } protected void setPickupModeFromEntity(EntityLivingBase entityliving) { if (entityliving instanceof EntityPlayer) { if (((EntityPlayer) entityliving).capabilities.isCreativeMode) { setPickupMode(EntityProjectile.PICKUP_CREATIVE); } else { setPickupMode( MHFCMain.config().isAllCanPickup() ? EntityProjectile.PICKUP_ALL : EntityProjectile.PICKUP_OWNER); } } else { setPickupMode(EntityProjectile.NO_PICKUP); } } @Override public void setThrowableHeading(double x, double y, double z, float speed, float deviation) { float f2 = MathHelper.sqrt_double(x * x + y * y + z * z); x /= f2; y /= f2; z /= f2; x += rand.nextGaussian() * 0.0075F * deviation; y += rand.nextGaussian() * 0.0075F * deviation; z += rand.nextGaussian() * 0.0075F * deviation; x *= speed; y *= speed; z *= speed; motionX = x; motionY = y; motionZ = z; float f3 = MathHelper.sqrt_double(x * x + z * z); prevRotationYaw = rotationYaw = (float) ((Math.atan2(x, z) * 180D) / Math.PI); prevRotationPitch = rotationPitch = (float) ((Math.atan2(y, f3) * 180D) / Math.PI); ticksInGround = 0; } @Override public void setVelocity(double d, double d1, double d2) { motionX = d; motionY = d1; motionZ = d2; if (aimRotation() && prevRotationPitch == 0.0F && prevRotationYaw == 0.0F) { float f = MathHelper.sqrt_double(d * d + d2 * d2); prevRotationYaw = rotationYaw = (float) ((Math.atan2(d, d2) * 180D) / Math.PI); prevRotationPitch = rotationPitch = (float) ((Math.atan2(d1, f) * 180D) / Math.PI); setLocationAndAngles(posX, posY, posZ, rotationYaw, rotationPitch); ticksInGround = 0; } } @Override public void onUpdate() { onEntityUpdate(); } @Override public void onEntityUpdate() { super.onEntityUpdate(); if (aimRotation()/* * && prevRotationPitch == 0.0F && prevRotationYaw == * 0.0F */) { float f = MathHelper.sqrt_double(motionX * motionX + motionZ * motionZ); prevRotationYaw = rotationYaw = (float) ((Math.atan2(motionX, motionZ) * 180D) / Math.PI); prevRotationPitch = rotationPitch = (float) ((Math.atan2(motionY, f) * 180D) / Math.PI); } Block i = worldObj.getBlock(xTile, yTile, zTile); if (i != null) { i.setBlockBoundsBasedOnState(worldObj, xTile, yTile, zTile); AxisAlignedBB axisalignedbb = i.getCollisionBoundingBoxFromPool(worldObj, xTile, yTile, zTile); if (axisalignedbb != null && axisalignedbb.isVecInside(Vec3.createVectorHelper(posX, posY, posZ))) { inGround = true; } } if (arrowShake > 0) { arrowShake--; } if (inGround) { Block j = worldObj.getBlock(xTile, yTile, zTile); int k = worldObj.getBlockMetadata(xTile, yTile, zTile); if (j == inTile && k == inData) { ticksInGround++; int t = getMaxLifetime(); if (t != 0 && ticksInGround >= t) { setDead(); } } else { inGround = false; motionX *= rand.nextFloat() * 0.2F; motionY *= rand.nextFloat() * 0.2F; motionZ *= rand.nextFloat() * 0.2F; ticksInGround = 0; ticksInAir = 0; } return; } ticksInAir++; Vec3 vec3d = Vec3.createVectorHelper(posX, posY, posZ); Vec3 vec3d1 = Vec3.createVectorHelper(posX + motionX, posY + motionY, posZ + motionZ); MovingObjectPosition movingobjectposition = worldObj.func_147447_a(vec3d, vec3d1, false, true, false); vec3d = Vec3.createVectorHelper(posX, posY, posZ); vec3d1 = Vec3.createVectorHelper(posX + motionX, posY + motionY, posZ + motionZ); if (movingobjectposition != null) { vec3d1 = Vec3.createVectorHelper( movingobjectposition.hitVec.xCoord, movingobjectposition.hitVec.yCoord, movingobjectposition.hitVec.zCoord); } Entity entity = null; @SuppressWarnings("unchecked") List<Entity> list = worldObj.getEntitiesWithinAABBExcludingEntity( this, boundingBox.addCoord(motionX, motionY, motionZ).expand(1.0D, 1.0D, 1.0D)); double d = 0.0D; for (int l = 0; l < list.size(); l++) { Entity entity1 = list.get(l); if (!entity1.canBeCollidedWith() || entity1 == shootingEntity && ticksInAir < 5) { continue; } float f4 = 0.3F; AxisAlignedBB axisalignedbb1 = entity1.boundingBox.expand(f4, f4, f4); MovingObjectPosition movingobjectposition1 = axisalignedbb1.calculateIntercept(vec3d, vec3d1); if (movingobjectposition1 == null) { continue; } double d1 = vec3d.distanceTo(movingobjectposition1.hitVec); if (d1 < d || d == 0.0D) { entity = entity1; d = d1; } } if (entity != null) { movingobjectposition = new MovingObjectPosition(entity); } if (movingobjectposition != null) { if (movingobjectposition.entityHit != null) { onEntityHit(movingobjectposition.entityHit); } else { onGroundHit(movingobjectposition); } } if (getIsCritical()) { for (int i1 = 0; i1 < 2; i1++) { worldObj.spawnParticle( "crit", posX + (motionX * i1) / 4D, posY + (motionY * i1) / 4D, posZ + (motionZ * i1) / 4D, -motionX, -motionY + 0.2D, -motionZ); } } posX += motionX; posY += motionY; posZ += motionZ; if (aimRotation()) { float f2 = MathHelper.sqrt_double(motionX * motionX + motionZ * motionZ); rotationYaw = (float) ((Math.atan2(motionX, motionZ) * 180D) / Math.PI); for (rotationPitch = (float) ((Math.atan2(motionY, f2) * 180D) / Math.PI); rotationPitch - prevRotationPitch < -180F; prevRotationPitch -= 360F) {} for (; rotationPitch - prevRotationPitch >= 180F; prevRotationPitch += 360F) {} for (; rotationYaw - prevRotationYaw < -180F; prevRotationYaw -= 360F) {} for (; rotationYaw - prevRotationYaw >= 180F; prevRotationYaw += 360F) {} rotationPitch = prevRotationPitch + (rotationPitch - prevRotationPitch) * 0.2F; rotationYaw = prevRotationYaw + (rotationYaw - prevRotationYaw) * 0.2F; } float res = getAirResistance(); float grav = getGravity(); if (isInWater()) { beenInGround = true; for (int i1 = 0; i1 < 4; i1++) { float f6 = 0.25F; worldObj.spawnParticle( "bubble", posX - motionX * f6, posY - motionY * f6, posZ - motionZ * f6, motionX, motionY, motionZ); } res *= 0.80808080F; } motionX *= res; motionY *= res; motionZ *= res; motionY -= grav; setPosition(posX, posY, posZ); func_145775_I(); } public void onEntityHit(Entity entity) { bounceBack(); applyEntityHitEffects(entity); } public void applyEntityHitEffects(Entity entity) { if (isBurning() && !(entity instanceof EntityEnderman)) { entity.setFire(5); } if (entity instanceof EntityLivingBase) { EntityLivingBase entityliving = (EntityLivingBase) entity; if (knockBack > 0) { float f = MathHelper.sqrt_double(motionX * motionX + motionZ * motionZ); if (f > 0.0F) { entity.addVelocity(motionX * knockBack * 0.6D / f, 0.1D, motionZ * knockBack * 0.6D / f); } } if (shootingEntity instanceof EntityLivingBase) { EnchantmentHelper.func_151384_a(entityliving, this.shootingEntity); EnchantmentHelper.func_151385_b((EntityLivingBase) this.shootingEntity, entityliving); } if (shootingEntity instanceof EntityPlayerMP && shootingEntity != entity && entity instanceof EntityPlayer) { ((EntityPlayerMP) shootingEntity).playerNetServerHandler.sendPacket(new S2BPacketChangeGameState(6, 0)); } } } public void onGroundHit(MovingObjectPosition mop) { xTile = mop.blockX; yTile = mop.blockY; zTile = mop.blockZ; inTile = worldObj.getBlock(xTile, yTile, zTile); inData = worldObj.getBlockMetadata(xTile, yTile, zTile); motionX = mop.hitVec.xCoord - posX; motionY = mop.hitVec.yCoord - posY; motionZ = mop.hitVec.zCoord - posZ; float f1 = MathHelper.sqrt_double(motionX * motionX + motionY * motionY + motionZ * motionZ); posX -= motionX / f1 * 0.05D; posY -= motionY / f1 * 0.05D; posZ -= motionZ / f1 * 0.05D; inGround = true; beenInGround = true; setIsCritical(false); arrowShake = getMaxArrowShake(); playHitSound(); if (inTile != null) { inTile.onEntityCollidedWithBlock(worldObj, xTile, yTile, zTile, this); } } protected void bounceBack() { motionX *= -0.1D; motionY *= -0.1D; motionZ *= -0.1D; rotationYaw += 180F; prevRotationYaw += 180F; ticksInAir = 0; } public final double getTotalVelocity() { return Math.sqrt(motionX * motionX + motionY * motionY + motionZ * motionZ); } public boolean aimRotation() { return true; } public int getMaxLifetime() { return 1200; } public ItemStack getPickupItem() { return null; } public float getAirResistance() { return 0.99F; } public float getGravity() { return 0.05F; } public int getMaxArrowShake() { return 7; } public void playHitSound() {} public boolean canBeCritical() { return false; } @Override public void setIsCritical(boolean flag) { if (canBeCritical()) { dataWatcher.updateObject(16, Byte.valueOf((byte) (flag ? 1 : 0))); } } @Override public boolean getIsCritical() { return canBeCritical() && dataWatcher.getWatchableObjectByte(16) != 0; } public void setExtraDamage(float f) { extraDamage = f; } @Override public void setKnockbackStrength(int i) { knockBack = i; } public void setPickupMode(int i) { pickupMode = i; } public int getPickupMode() { return pickupMode; } public boolean canPickup(EntityPlayer entityplayer) { if (pickupMode == EntityProjectile.PICKUP_ALL) { return true; } else if (pickupMode == EntityProjectile.PICKUP_CREATIVE) { return entityplayer.capabilities.isCreativeMode; } else if (pickupMode == EntityProjectile.PICKUP_OWNER) { return entityplayer == shootingEntity; } else { return false; } } @Override public void onCollideWithPlayer(EntityPlayer entityplayer) { if (inGround && arrowShake <= 0) { if (canPickup(entityplayer)) { if (!worldObj.isRemote) { ItemStack item = getPickupItem(); if (item == null) { return; } if (pickupMode == EntityProjectile.PICKUP_CREATIVE && entityplayer.capabilities.isCreativeMode || entityplayer.inventory.addItemStackToInventory(item)) { worldObj.playSoundAtEntity( this, "random.pop", 0.2F, ((rand.nextFloat() - rand.nextFloat()) * 0.7F + 1.0F) * 2.0F); onItemPickup(entityplayer); setDead(); } } } } } protected void onItemPickup(EntityPlayer entityplayer) { entityplayer.onItemPickup(this, 1); } @Override @SideOnly(Side.CLIENT) public float getShadowSize() { return 0.0F; } @Override protected boolean canTriggerWalking() { return false; } @Override public void writeEntityToNBT(NBTTagCompound nbttagcompound) { nbttagcompound.setShort("xTile", (short) xTile); nbttagcompound.setShort("yTile", (short) yTile); nbttagcompound.setShort("zTile", (short) zTile); nbttagcompound.setByte("inTile", (byte) Block.getIdFromBlock(inTile)); nbttagcompound.setByte("inData", (byte) inData); nbttagcompound.setByte("shake", (byte) arrowShake); nbttagcompound.setBoolean("inGround", inGround); nbttagcompound.setBoolean("beenInGround", beenInGround); nbttagcompound.setByte("pickup", (byte) pickupMode); } @Override public void readEntityFromNBT(NBTTagCompound nbttagcompound) { xTile = nbttagcompound.getShort("xTile"); yTile = nbttagcompound.getShort("yTile"); zTile = nbttagcompound.getShort("zTile"); inTile = Block.getBlockById(nbttagcompound.getByte("inTile") & 0xFF); inData = nbttagcompound.getByte("inData") & 0xFF; arrowShake = nbttagcompound.getByte("shake") & 0xFF; inGround = nbttagcompound.getBoolean("inGround"); beenInGround = nbttagcompound.getBoolean("beenInGrond"); pickupMode = nbttagcompound.getByte("pickup"); } }