|
@@ -1,146 +1,197 @@
|
|
|
package me.km.entities;
|
|
|
|
|
|
-import java.util.List;
|
|
|
import me.km.Server;
|
|
|
import me.km.overrides.ModEntityPlayerMP;
|
|
|
-import me.km.utils.ReflectionUtils;
|
|
|
+import net.minecraft.block.Blocks;
|
|
|
import net.minecraft.entity.Entity;
|
|
|
import net.minecraft.entity.LivingEntity;
|
|
|
import net.minecraft.entity.IProjectile;
|
|
|
import net.minecraft.entity.item.ItemEntity;
|
|
|
+import net.minecraft.entity.projectile.ProjectileHelper;
|
|
|
import net.minecraft.item.ItemStack;
|
|
|
+import net.minecraft.particles.ParticleTypes;
|
|
|
import net.minecraft.util.DamageSource;
|
|
|
import net.minecraft.util.math.AxisAlignedBB;
|
|
|
+import net.minecraft.util.math.BlockRayTraceResult;
|
|
|
+import net.minecraft.util.math.EntityRayTraceResult;
|
|
|
import net.minecraft.util.math.MathHelper;
|
|
|
+import net.minecraft.util.math.RayTraceContext;
|
|
|
+import net.minecraft.util.math.RayTraceResult;
|
|
|
+import net.minecraft.util.math.Vec3d;
|
|
|
|
|
|
public class EntityItemProjectile extends ItemEntity implements IProjectile
|
|
|
{
|
|
|
- private final LivingEntity thrower;
|
|
|
- private boolean noHit;
|
|
|
+ private LivingEntity owner;
|
|
|
+ private boolean hit = false;
|
|
|
private final float damage;
|
|
|
+ private Entity ignoreEntity = null;
|
|
|
+ private int ignoreTime = 0;
|
|
|
|
|
|
- public EntityItemProjectile(LivingEntity thrower, ItemStack stack, float damage)
|
|
|
+ public EntityItemProjectile(LivingEntity thrower, ItemStack stack, float damage)
|
|
|
{
|
|
|
super(thrower.world, thrower.posX, thrower.posY + thrower.getEyeHeight() - 0.1d, thrower.posZ, stack);
|
|
|
- this.thrower = thrower;
|
|
|
- this.noHit = true;
|
|
|
+ this.owner = thrower;
|
|
|
super.setInfinitePickupDelay();
|
|
|
this.damage = damage;
|
|
|
}
|
|
|
-
|
|
|
- public EntityItemProjectile(LivingEntity thrower, ItemStack stack)
|
|
|
+
|
|
|
+ public EntityItemProjectile(LivingEntity thrower, ItemStack stack)
|
|
|
{
|
|
|
this(thrower, stack, -1);
|
|
|
}
|
|
|
|
|
|
- public LivingEntity getItemThrower()
|
|
|
+ public LivingEntity getItemThrower()
|
|
|
{
|
|
|
- return thrower;
|
|
|
+ return owner;
|
|
|
}
|
|
|
|
|
|
public void setHeadingFromThrower(Entity thrower, float rotationPitchIn, float rotationYawIn, float pitchOffset, float velocity, float inaccuracy)
|
|
|
{
|
|
|
- float f = -MathHelper.sin(rotationYawIn * 0.017453292F) * MathHelper.cos(rotationPitchIn * 0.017453292F);
|
|
|
- float f1 = -MathHelper.sin((rotationPitchIn + pitchOffset) * 0.017453292F);
|
|
|
- float f2 = MathHelper.cos(rotationYawIn * 0.017453292F) * MathHelper.cos(rotationPitchIn * 0.017453292F);
|
|
|
- this.shoot(f, f1, f2, velocity, inaccuracy);
|
|
|
-
|
|
|
- double y = thrower.onGround ? 0.0 : thrower.getMotion().getY();
|
|
|
- this.setMotion(this.getMotion().add(thrower.getMotion().getX(), y, thrower.getMotion().getZ()));
|
|
|
- }
|
|
|
-
|
|
|
- public void shoot(Entity shooter, float pitch, float yaw, float velocity, float inaccuracy)
|
|
|
- {
|
|
|
- float f = -MathHelper.sin(yaw * 0.017453292F) * MathHelper.cos(pitch * 0.017453292F);
|
|
|
- float f1 = -MathHelper.sin(pitch * 0.017453292F);
|
|
|
- float f2 = MathHelper.cos(yaw * 0.017453292F) * MathHelper.cos(pitch * 0.017453292F);
|
|
|
- this.shoot(f, f1, f2, velocity, inaccuracy);
|
|
|
-
|
|
|
- double y = shooter.onGround ? 0.0 : shooter.getMotion().getY();
|
|
|
- this.setMotion(this.getMotion().add(shooter.getMotion().getX(), y, shooter.getMotion().getZ()));
|
|
|
+ float f = -MathHelper.sin(rotationYawIn * ((float) Math.PI / 180.0f)) * MathHelper.cos(rotationPitchIn * ((float) Math.PI / 180.0f));
|
|
|
+ float f1 = -MathHelper.sin((rotationPitchIn + pitchOffset) * ((float) Math.PI / 180.0f));
|
|
|
+ float f2 = MathHelper.cos(rotationYawIn * ((float) Math.PI / 180.0f)) * MathHelper.cos(rotationPitchIn * ((float) Math.PI / 180.0f));
|
|
|
+ shoot(f, f1, f2, velocity, inaccuracy);
|
|
|
+ Vec3d vec3d = thrower.getMotion();
|
|
|
+ this.setMotion(this.getMotion().add(vec3d.x, thrower.onGround ? 0.0D : vec3d.y, vec3d.z));
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
@Override
|
|
|
public void shoot(double x, double y, double z, float velocity, float inaccuracy)
|
|
|
{
|
|
|
- float f = MathHelper.sqrt(x * x + y * y + z * z);
|
|
|
- x = x / (double)f;
|
|
|
- y = y / (double)f;
|
|
|
- z = z / (double)f;
|
|
|
- x = x + this.rand.nextGaussian() * 0.0075d * (double)inaccuracy;
|
|
|
- y = y + this.rand.nextGaussian() * 0.0075d * (double)inaccuracy;
|
|
|
- z = z + this.rand.nextGaussian() * 0.0075d * (double)inaccuracy;
|
|
|
- x = x * (double)velocity;
|
|
|
- y = y * (double)velocity;
|
|
|
- z = z * (double)velocity;
|
|
|
- this.setMotion(x, y, z);
|
|
|
- float f1 = MathHelper.sqrt(x * x + z * z);
|
|
|
- this.rotationYaw = (float)(MathHelper.atan2(x, z) * (180D / Math.PI));
|
|
|
- this.rotationPitch = (float)(MathHelper.atan2(y, (double)f1) * (180D / Math.PI));
|
|
|
+ Vec3d vec3d = new Vec3d(x, y, z)
|
|
|
+ .normalize()
|
|
|
+ .add(rand.nextGaussian() * 0.0075 * inaccuracy, rand.nextGaussian() * 0.0075 * inaccuracy, rand.nextGaussian() * 0.0075 * inaccuracy)
|
|
|
+ .scale(velocity);
|
|
|
+ setMotion(vec3d);
|
|
|
+ float f1 = MathHelper.sqrt(func_213296_b(vec3d));
|
|
|
+ this.rotationYaw = (float) (MathHelper.atan2(x, z) * (180.0 / Math.PI));
|
|
|
+ this.rotationPitch = (float) (MathHelper.atan2(y, f1) * (180.0 / Math.PI));
|
|
|
this.prevRotationYaw = this.rotationYaw;
|
|
|
this.prevRotationPitch = this.rotationPitch;
|
|
|
}
|
|
|
|
|
|
+ private void onImpact(RayTraceResult ray)
|
|
|
+ {
|
|
|
+ if(damage == -1)
|
|
|
+ {
|
|
|
+ if(!(owner instanceof ModEntityPlayerMP))
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ ModEntityPlayerMP p = (ModEntityPlayerMP) owner;
|
|
|
+ switch(ray.getType())
|
|
|
+ {
|
|
|
+ case ENTITY:
|
|
|
+ Server.scriptEvents.onEntityItemProjectileHit(this, p, this.getItem(), ((EntityRayTraceResult) ray).getEntity(), null);
|
|
|
+ break;
|
|
|
+ case BLOCK:
|
|
|
+ Server.scriptEvents.onEntityItemProjectileHit(this, p, this.getItem(), null, ((BlockRayTraceResult) ray).getPos());
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if(ray.getType() == RayTraceResult.Type.ENTITY)
|
|
|
+ {
|
|
|
+ ((EntityRayTraceResult) ray).getEntity().attackEntityFrom(DamageSource.causeThrownDamage(this, owner), damage);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
@Override
|
|
|
- public void tick()
|
|
|
+ public void tick()
|
|
|
{
|
|
|
super.tick();
|
|
|
- if(noHit)
|
|
|
+ if(hit)
|
|
|
{
|
|
|
- if(this.onGround)
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ AxisAlignedBB axisalignedbb = this.getBoundingBox().expand(this.getMotion()).grow(2.0D);
|
|
|
+
|
|
|
+ for(Entity entity : this.world.getEntitiesInAABBexcluding(this, axisalignedbb, (p) -> !p.isSpectator() && p.canBeCollidedWith()))
|
|
|
+ {
|
|
|
+ if(entity == this.ignoreEntity)
|
|
|
{
|
|
|
- noHit = false;
|
|
|
- this.setDefaultPickupDelay();
|
|
|
- return;
|
|
|
+ this.ignoreTime++;
|
|
|
+ break;
|
|
|
}
|
|
|
-
|
|
|
- float fw = this.getWidth() / 2;
|
|
|
- float fh = this.getHeight() / 2;
|
|
|
- List<Entity> list = this.world.getEntitiesWithinAABBExcludingEntity(this,
|
|
|
- new AxisAlignedBB(prevPosX, prevPosY, prevPosZ, posX, posY, posZ).expand(fw, fh, fw));
|
|
|
- if(list.isEmpty())
|
|
|
+
|
|
|
+ if(this.owner != null && this.ticksExisted < 2 && this.ignoreEntity == null)
|
|
|
{
|
|
|
- return;
|
|
|
+ this.ignoreEntity = entity;
|
|
|
+ this.ignoreTime = 3;
|
|
|
+ break;
|
|
|
}
|
|
|
-
|
|
|
- double minX = Math.min(prevPosX, posX);
|
|
|
- double minY = Math.min(prevPosY, posY);
|
|
|
- double minZ = Math.min(prevPosZ, posZ);
|
|
|
- double maxX = Math.max(prevPosX, posX);
|
|
|
- double maxY = Math.max(prevPosY, posY);
|
|
|
- double maxZ = Math.max(prevPosZ, posZ);
|
|
|
- list.removeIf(ent ->
|
|
|
+ }
|
|
|
+
|
|
|
+ RayTraceResult ray = ProjectileHelper.func_221267_a(this, axisalignedbb,
|
|
|
+ (p) -> !p.isSpectator() && p.canBeCollidedWith() && p != this.ignoreEntity, RayTraceContext.BlockMode.OUTLINE, true);
|
|
|
+ if(this.ignoreEntity != null && this.ignoreTime-- <= 0)
|
|
|
+ {
|
|
|
+ this.ignoreEntity = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(ray.getType() != RayTraceResult.Type.MISS)
|
|
|
+ {
|
|
|
+ if(ray.getType() == RayTraceResult.Type.BLOCK && this.world.getBlockState(((BlockRayTraceResult) ray).getPos()).getBlock() == Blocks.NETHER_PORTAL)
|
|
|
{
|
|
|
-
|
|
|
-
|
|
|
- if(ent == thrower && ReflectionUtils.getAge(this) < 5)
|
|
|
- {
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- return !ent.getBoundingBox().grow(0.25f).intersects(minX, minY, minZ, maxX, maxY, maxZ);
|
|
|
- });
|
|
|
- if(!list.isEmpty())
|
|
|
+ this.setPortal(((BlockRayTraceResult) ray).getPos());
|
|
|
+ }
|
|
|
+ else
|
|
|
{
|
|
|
- noHit = false;
|
|
|
+ this.onImpact(ray);
|
|
|
+ hit = true;
|
|
|
this.setDefaultPickupDelay();
|
|
|
- onImpact(list);
|
|
|
}
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- protected void onImpact(List<Entity> list)
|
|
|
- {
|
|
|
- if(damage == -1)
|
|
|
+ Vec3d vec3d = this.getMotion();
|
|
|
+ this.posX += vec3d.x;
|
|
|
+ this.posY += vec3d.y;
|
|
|
+ this.posZ += vec3d.z;
|
|
|
+ float f = MathHelper.sqrt(func_213296_b(vec3d));
|
|
|
+ this.rotationYaw = (float) (MathHelper.atan2(vec3d.x, vec3d.z) * (double) (180F / (float) Math.PI));
|
|
|
+
|
|
|
+ for(this.rotationPitch = (float) (MathHelper.atan2(vec3d.y, (double) f) * (double) (180F / (float) Math.PI)); this.rotationPitch - this.prevRotationPitch < -180.0F; this.prevRotationPitch -= 360.0F)
|
|
|
+ {
|
|
|
+ }
|
|
|
+
|
|
|
+ while(this.rotationPitch - this.prevRotationPitch >= 180.0F)
|
|
|
{
|
|
|
- if(thrower instanceof ModEntityPlayerMP)
|
|
|
+ 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 = MathHelper.lerp(0.2F, this.prevRotationPitch, this.rotationPitch);
|
|
|
+ this.rotationYaw = MathHelper.lerp(0.2F, this.prevRotationYaw, this.rotationYaw);
|
|
|
+ float f1;
|
|
|
+ if(this.isInWater())
|
|
|
+ {
|
|
|
+ for(int i = 0; i < 4; ++i)
|
|
|
{
|
|
|
- Server.scriptEvents.onEntityItemProjectileHit(this, (ModEntityPlayerMP) thrower, this.getItem(), list);
|
|
|
+ this.world.addParticle(ParticleTypes.BUBBLE, this.posX - vec3d.x * 0.25D, this.posY - vec3d.y * 0.25D, this.posZ - vec3d.z * 0.25D, vec3d.x, vec3d.y, vec3d.z);
|
|
|
}
|
|
|
+ f1 = 0.8F;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- list.forEach(ent -> ent.attackEntityFrom(DamageSource.causeThrownDamage(this, thrower), damage));
|
|
|
+ f1 = 0.99F;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.setMotion(vec3d.scale((double) f1));
|
|
|
+ if(!this.hasNoGravity())
|
|
|
+ {
|
|
|
+ Vec3d vec3d1 = this.getMotion();
|
|
|
+ this.setMotion(vec3d1.x, vec3d1.y - 0.03, vec3d1.z);
|
|
|
}
|
|
|
+
|
|
|
+ this.setPosition(this.posX, this.posY, this.posZ);
|
|
|
}
|
|
|
}
|