EntityItemProjectile.java 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. package me.km.entities;
  2. import java.util.List;
  3. import me.km.KajetansMod;
  4. import me.km.snuviscript.ScriptEvents;
  5. import me.km.utils.ReflectionUtils;
  6. import net.minecraft.entity.Entity;
  7. import net.minecraft.entity.EntityLivingBase;
  8. import net.minecraft.entity.IProjectile;
  9. import net.minecraft.entity.item.EntityItem;
  10. import net.minecraft.entity.player.EntityPlayer;
  11. import net.minecraft.item.ItemStack;
  12. import net.minecraft.util.DamageSource;
  13. import net.minecraft.util.math.AxisAlignedBB;
  14. import net.minecraft.util.math.MathHelper;
  15. import net.minecraft.util.math.Vec3d;
  16. public class EntityItemProjectile extends EntityItem implements IProjectile
  17. {
  18. private final EntityLivingBase thrower;
  19. private boolean noHit;
  20. private final float damage;
  21. public EntityItemProjectile(EntityLivingBase thrower, ItemStack stack, float damage)
  22. {
  23. super(thrower.world, thrower.posX, thrower.posY + thrower.getEyeHeight() - 0.1d, thrower.posZ, stack);
  24. this.thrower = thrower;
  25. this.noHit = true;
  26. super.setInfinitePickupDelay();
  27. this.damage = damage;
  28. }
  29. public EntityItemProjectile(EntityLivingBase thrower, ItemStack stack)
  30. {
  31. this(thrower, stack, -1);
  32. }
  33. public EntityLivingBase getItemThrower()
  34. {
  35. return thrower;
  36. }
  37. public void setHeadingFromThrower(Entity entityThrower, float rotationPitchIn, float rotationYawIn, float pitchOffset, float velocity, float inaccuracy)
  38. {
  39. float f = -MathHelper.sin(rotationYawIn * 0.017453292F) * MathHelper.cos(rotationPitchIn * 0.017453292F);
  40. float f1 = -MathHelper.sin((rotationPitchIn + pitchOffset) * 0.017453292F);
  41. float f2 = MathHelper.cos(rotationYawIn * 0.017453292F) * MathHelper.cos(rotationPitchIn * 0.017453292F);
  42. this.shoot(f, f1, f2, velocity, inaccuracy);
  43. this.motionX += entityThrower.motionX;
  44. this.motionZ += entityThrower.motionZ;
  45. if (!entityThrower.onGround)
  46. {
  47. this.motionY += entityThrower.motionY;
  48. }
  49. }
  50. @Override
  51. public void shoot(double x, double y, double z, float velocity, float inaccuracy)
  52. {
  53. float f = MathHelper.sqrt(x * x + y * y + z * z);
  54. x = x / (double)f;
  55. y = y / (double)f;
  56. z = z / (double)f;
  57. x = x + this.rand.nextGaussian() * 0.0075d * (double)inaccuracy;
  58. y = y + this.rand.nextGaussian() * 0.0075d * (double)inaccuracy;
  59. z = z + this.rand.nextGaussian() * 0.0075d * (double)inaccuracy;
  60. x = x * (double)velocity;
  61. y = y * (double)velocity;
  62. z = z * (double)velocity;
  63. this.motionX = x;
  64. this.motionY = y;
  65. this.motionZ = z;
  66. float f1 = MathHelper.sqrt(x * x + z * z);
  67. this.rotationYaw = (float)(MathHelper.atan2(x, z) * (180D / Math.PI));
  68. this.rotationPitch = (float)(MathHelper.atan2(y, (double)f1) * (180D / Math.PI));
  69. this.prevRotationYaw = this.rotationYaw;
  70. this.prevRotationPitch = this.rotationPitch;
  71. }
  72. @Override
  73. public void onUpdate()
  74. {
  75. super.onUpdate();
  76. if(noHit)
  77. {
  78. if(this.onGround)
  79. {
  80. noHit = false;
  81. this.setDefaultPickupDelay();
  82. return;
  83. }
  84. float fw = this.width / 2;
  85. float fh = this.height / 2;
  86. List<Entity> list = this.world.getEntitiesWithinAABBExcludingEntity(this,
  87. new AxisAlignedBB(prevPosX, prevPosY, prevPosZ, posX, posY, posZ).expand(fw, fh, fw));
  88. if(list.isEmpty())
  89. {
  90. return;
  91. }
  92. Vec3d oldV = new Vec3d(this.prevPosX, prevPosY, prevPosZ);
  93. Vec3d newV = new Vec3d(this.posX, this.posY, this.posZ);
  94. list.removeIf(ent ->
  95. {
  96. // this prevents the projectile from hitting its shooter during
  97. // the first ticks
  98. if(ent == thrower && ReflectionUtils.getAge(this) < 5)
  99. {
  100. return true;
  101. }
  102. // size of the projectile is 0.25 x 0.25
  103. return ent.getEntityBoundingBox().grow(0.125f).calculateIntercept(oldV, newV) == null;
  104. });
  105. if(!list.isEmpty())
  106. {
  107. noHit = false;
  108. this.setDefaultPickupDelay();
  109. onImpact(list);
  110. }
  111. }
  112. }
  113. protected void onImpact(List<Entity> list)
  114. {
  115. if(damage == -1)
  116. {
  117. if(thrower instanceof EntityPlayer)
  118. {
  119. KajetansMod.scripts.getEvent(ScriptEvents.class).onEntityItemProjectileHit(this, (EntityPlayer) thrower, this.getItem(), list);
  120. }
  121. }
  122. else
  123. {
  124. list.forEach(ent -> ent.attackEntityFrom(DamageSource.causeThrownDamage(this, thrower), damage));
  125. }
  126. }
  127. }