package net.minecraft.world.entity.projectile; import net.minecraft.core.BlockPos; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.InsideBlockEffectApplier; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.HitResult.Type; public abstract class ThrowableProjectile extends Projectile { private static final float MIN_CAMERA_DISTANCE_SQUARED = 12.25F; protected ThrowableProjectile(EntityType entityType, Level level) { super(entityType, level); } protected ThrowableProjectile(EntityType entityType, double x, double y, double z, Level level) { this(entityType, level); this.setPos(x, y, z); } @Override public boolean shouldRenderAtSqrDistance(double distance) { if (this.tickCount < 2 && distance < 12.25) { return false; } else { double d = this.getBoundingBox().getSize() * 4.0; if (Double.isNaN(d)) { d = 4.0; } d *= 64.0; return distance < d * d; } } @Override public boolean canUsePortal(boolean allowPassengers) { return true; } @Override public void tick() { this.handleFirstTickBubbleColumn(); this.applyGravity(); this.applyInertia(); HitResult hitResult = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity); Vec3 vec3; if (hitResult.getType() != Type.MISS) { vec3 = hitResult.getLocation(); } else { vec3 = this.position().add(this.getDeltaMovement()); } this.setPos(vec3); this.updateRotation(); this.applyEffectsFromBlocks(); super.tick(); if (hitResult.getType() != Type.MISS && this.isAlive()) { this.hitTargetOrDeflectSelf(hitResult); } } private void applyInertia() { Vec3 vec3 = this.getDeltaMovement(); Vec3 vec32 = this.position(); float g; if (this.isInWater()) { for (int i = 0; i < 4; i++) { float f = 0.25F; this.level().addParticle(ParticleTypes.BUBBLE, vec32.x - vec3.x * 0.25, vec32.y - vec3.y * 0.25, vec32.z - vec3.z * 0.25, vec3.x, vec3.y, vec3.z); } g = 0.8F; } else { g = 0.99F; } this.setDeltaMovement(vec3.scale(g)); } private void handleFirstTickBubbleColumn() { if (this.firstTick) { for (BlockPos blockPos : BlockPos.betweenClosed(this.getBoundingBox())) { BlockState blockState = this.level().getBlockState(blockPos); if (blockState.is(Blocks.BUBBLE_COLUMN)) { blockState.entityInside(this.level(), blockPos, this, InsideBlockEffectApplier.NOOP); } } } } @Override protected double getDefaultGravity() { return 0.03; } }