EntityItemProjectile.java 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  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.LivingEntity;
  8. import net.minecraft.entity.IProjectile;
  9. import net.minecraft.entity.item.ItemEntity;
  10. import net.minecraft.entity.player.PlayerEntity;
  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 ItemEntity implements IProjectile
  17. {
  18. private final LivingEntity thrower;
  19. private boolean noHit;
  20. private final float damage;
  21. public EntityItemProjectile(LivingEntity 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(LivingEntity thrower, ItemStack stack)
  30. {
  31. this(thrower, stack, -1);
  32. }
  33. public LivingEntity getItemThrower()
  34. {
  35. return thrower;
  36. }
  37. public void setHeadingFromThrower(Entity thrower, 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. double y = thrower.onGround ? 0.0 : thrower.getMotion().getY();
  44. this.setMotion(this.getMotion().add(thrower.getMotion().getX(), y, thrower.getMotion().getZ()));
  45. }
  46. public void shoot(Entity shooter, float pitch, float yaw, float velocity, float inaccuracy)
  47. {
  48. float f = -MathHelper.sin(yaw * 0.017453292F) * MathHelper.cos(pitch * 0.017453292F);
  49. float f1 = -MathHelper.sin(pitch * 0.017453292F);
  50. float f2 = MathHelper.cos(yaw * 0.017453292F) * MathHelper.cos(pitch * 0.017453292F);
  51. this.shoot(f, f1, f2, velocity, inaccuracy);
  52. double y = shooter.onGround ? 0.0 : shooter.getMotion().getY();
  53. this.setMotion(this.getMotion().add(shooter.getMotion().getX(), y, shooter.getMotion().getZ()));
  54. }
  55. @Override
  56. public void shoot(double x, double y, double z, float velocity, float inaccuracy)
  57. {
  58. float f = MathHelper.sqrt(x * x + y * y + z * z);
  59. x = x / (double)f;
  60. y = y / (double)f;
  61. z = z / (double)f;
  62. x = x + this.rand.nextGaussian() * 0.0075d * (double)inaccuracy;
  63. y = y + this.rand.nextGaussian() * 0.0075d * (double)inaccuracy;
  64. z = z + this.rand.nextGaussian() * 0.0075d * (double)inaccuracy;
  65. x = x * (double)velocity;
  66. y = y * (double)velocity;
  67. z = z * (double)velocity;
  68. this.setMotion(x, y, z);
  69. float f1 = MathHelper.sqrt(x * x + z * z);
  70. this.rotationYaw = (float)(MathHelper.atan2(x, z) * (180D / Math.PI));
  71. this.rotationPitch = (float)(MathHelper.atan2(y, (double)f1) * (180D / Math.PI));
  72. this.prevRotationYaw = this.rotationYaw;
  73. this.prevRotationPitch = this.rotationPitch;
  74. }
  75. @Override
  76. public void tick()
  77. {
  78. super.tick();
  79. if(noHit)
  80. {
  81. if(this.onGround)
  82. {
  83. noHit = false;
  84. this.setDefaultPickupDelay();
  85. return;
  86. }
  87. float fw = this.getWidth() / 2;
  88. float fh = this.getHeight() / 2;
  89. List<Entity> list = this.world.getEntitiesWithinAABBExcludingEntity(this,
  90. new AxisAlignedBB(prevPosX, prevPosY, prevPosZ, posX, posY, posZ).expand(fw, fh, fw));
  91. if(list.isEmpty())
  92. {
  93. return;
  94. }
  95. Vec3d oldV = new Vec3d(this.prevPosX, prevPosY, prevPosZ);
  96. Vec3d newV = new Vec3d(this.posX, this.posY, this.posZ);
  97. list.removeIf(ent ->
  98. {
  99. // this prevents the projectile from hitting its shooter during
  100. // the first ticks
  101. if(ent == thrower && ReflectionUtils.getAge(this) < 5)
  102. {
  103. return true;
  104. }
  105. // size of the projectile is 0.25 x 0.25
  106. return !ent.getBoundingBox().grow(0.25f).intersects(oldV, newV);
  107. });
  108. if(!list.isEmpty())
  109. {
  110. noHit = false;
  111. this.setDefaultPickupDelay();
  112. onImpact(list);
  113. }
  114. }
  115. }
  116. protected void onImpact(List<Entity> list)
  117. {
  118. if(damage == -1)
  119. {
  120. if(KajetansMod.scripts != null && thrower instanceof PlayerEntity)
  121. {
  122. ScriptEvents.onEntityItemProjectileHit(this, (PlayerEntity) thrower, this.getItem(), list);
  123. }
  124. }
  125. else
  126. {
  127. list.forEach(ent -> ent.attackEntityFrom(DamageSource.causeThrownDamage(this, thrower), damage));
  128. }
  129. }
  130. }