package me.km.entities; import me.km.Server; import net.minecraft.block.Blocks; import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; 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.vector.Vector3d; public class EntityItemProjectile extends ItemEntity { 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) { super(thrower.world, thrower.getPosX(), thrower.getPosY() + thrower.getEyeHeight() - 0.1d, thrower.getPosZ(), stack); this.owner = thrower; super.setInfinitePickupDelay(); this.damage = damage; } public EntityItemProjectile(LivingEntity thrower, ItemStack stack) { this(thrower, stack, -1); } public LivingEntity getItemThrower() { return owner; } public void setHeadingFromThrower(Entity thrower, float rotationPitchIn, float rotationYawIn, float pitchOffset, float velocity, float inaccuracy) { 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); Vector3d vec3d = thrower.getMotion(); this.setMotion(this.getMotion().add(vec3d.x, thrower.isOnGround() ? 0.0D : vec3d.y, vec3d.z)); } public void shoot(double x, double y, double z, float velocity, float inaccuracy) { Vector3d vec3d = new Vector3d(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(horizontalMag(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) { switch(ray.getType()) { case ENTITY: Server.scriptEvents.onEntityItemProjectileHit(this, owner, this.getItem(), ((EntityRayTraceResult) ray).getEntity(), null); break; case BLOCK: Server.scriptEvents.onEntityItemProjectileHit(this, owner, 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() { super.tick(); if(hit) { 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) { this.ignoreTime++; break; } if(this.owner != null && this.ticksExisted < 2 && this.ignoreEntity == null) { this.ignoreEntity = entity; this.ignoreTime = 3; break; } } RayTraceResult ray = ProjectileHelper.func_234618_a_(this, this::func_230298_a_); 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) { this.setPortal(((BlockRayTraceResult) ray).getPos()); } else { this.onImpact(ray); hit = true; this.setDefaultPickupDelay(); } } Vector3d vec3d = this.getMotion(); setRawPosition(getPosX() + vec3d.x, getPosY() + vec3d.y, getPosZ() + vec3d.z); float f = MathHelper.sqrt(horizontalMag(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) { 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) { this.world.addParticle(ParticleTypes.BUBBLE, getPosX() - vec3d.x * 0.25D, getPosY() - vec3d.y * 0.25D, getPosZ() - vec3d.z * 0.25D, vec3d.x, vec3d.y, vec3d.z); } f1 = 0.8F; } else { f1 = 0.99F; } this.setMotion(vec3d.scale((double) f1)); if(!this.hasNoGravity()) { Vector3d vec3d1 = this.getMotion(); this.setMotion(vec3d1.x, vec3d1.y - 0.03, vec3d1.z); } this.setPosition(getPosX(), getPosY(), getPosZ()); } protected boolean func_230298_a_(Entity ent) { if(!ent.isSpectator() && ent.isAlive() && ent.canBeCollidedWith()) { Entity other = this.getItemThrower(); return other == null || ent != other || !other.isRidingSameEntity(ent); } return false; } }