201 lines
5.9 KiB
Java
201 lines
5.9 KiB
Java
package net.minecraft.world.entity.projectile;
|
|
|
|
import net.minecraft.core.particles.ParticleOptions;
|
|
import net.minecraft.core.particles.ParticleTypes;
|
|
import net.minecraft.nbt.CompoundTag;
|
|
import net.minecraft.network.protocol.Packet;
|
|
import net.minecraft.network.protocol.game.ClientGamePacketListener;
|
|
import net.minecraft.network.protocol.game.ClientboundAddEntityPacket;
|
|
import net.minecraft.network.syncher.SynchedEntityData;
|
|
import net.minecraft.server.level.ServerEntity;
|
|
import net.minecraft.world.damagesource.DamageSource;
|
|
import net.minecraft.world.entity.Entity;
|
|
import net.minecraft.world.entity.EntityType;
|
|
import net.minecraft.world.entity.LivingEntity;
|
|
import net.minecraft.world.level.ClipContext;
|
|
import net.minecraft.world.level.Level;
|
|
import net.minecraft.world.phys.HitResult;
|
|
import net.minecraft.world.phys.Vec3;
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
public abstract class AbstractHurtingProjectile extends Projectile {
|
|
public static final double INITAL_ACCELERATION_POWER = 0.1;
|
|
public static final double DEFLECTION_SCALE = 0.5;
|
|
public double accelerationPower = 0.1;
|
|
|
|
protected AbstractHurtingProjectile(EntityType<? extends AbstractHurtingProjectile> entityType, Level level) {
|
|
super(entityType, level);
|
|
}
|
|
|
|
protected AbstractHurtingProjectile(EntityType<? extends AbstractHurtingProjectile> entityType, double x, double y, double z, Level level) {
|
|
this(entityType, level);
|
|
this.setPos(x, y, z);
|
|
}
|
|
|
|
public AbstractHurtingProjectile(EntityType<? extends AbstractHurtingProjectile> entityType, double x, double y, double z, Vec3 movement, Level level) {
|
|
this(entityType, level);
|
|
this.moveTo(x, y, z, this.getYRot(), this.getXRot());
|
|
this.reapplyPosition();
|
|
this.assignDirectionalMovement(movement, this.accelerationPower);
|
|
}
|
|
|
|
public AbstractHurtingProjectile(EntityType<? extends AbstractHurtingProjectile> entityType, LivingEntity owner, Vec3 movement, Level level) {
|
|
this(entityType, owner.getX(), owner.getY(), owner.getZ(), movement, level);
|
|
this.setOwner(owner);
|
|
this.setRot(owner.getYRot(), owner.getXRot());
|
|
}
|
|
|
|
@Override
|
|
protected void defineSynchedData(SynchedEntityData.Builder builder) {
|
|
}
|
|
|
|
@Override
|
|
public boolean shouldRenderAtSqrDistance(double distance) {
|
|
double d = this.getBoundingBox().getSize() * 4.0;
|
|
if (Double.isNaN(d)) {
|
|
d = 4.0;
|
|
}
|
|
|
|
d *= 64.0;
|
|
return distance < d * d;
|
|
}
|
|
|
|
protected ClipContext.Block getClipType() {
|
|
return ClipContext.Block.COLLIDER;
|
|
}
|
|
|
|
@Override
|
|
public void tick() {
|
|
Entity entity = this.getOwner();
|
|
if (this.level().isClientSide || (entity == null || !entity.isRemoved()) && this.level().hasChunkAt(this.blockPosition())) {
|
|
super.tick();
|
|
if (this.shouldBurn()) {
|
|
this.igniteForSeconds(1.0F);
|
|
}
|
|
|
|
HitResult hitResult = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity, this.getClipType());
|
|
if (hitResult.getType() != HitResult.Type.MISS) {
|
|
this.hitTargetOrDeflectSelf(hitResult);
|
|
}
|
|
|
|
this.checkInsideBlocks();
|
|
Vec3 vec3 = this.getDeltaMovement();
|
|
double d = this.getX() + vec3.x;
|
|
double e = this.getY() + vec3.y;
|
|
double f = this.getZ() + vec3.z;
|
|
ProjectileUtil.rotateTowardsMovement(this, 0.2F);
|
|
float h;
|
|
if (this.isInWater()) {
|
|
for (int i = 0; i < 4; i++) {
|
|
float g = 0.25F;
|
|
this.level().addParticle(ParticleTypes.BUBBLE, d - vec3.x * 0.25, e - vec3.y * 0.25, f - vec3.z * 0.25, vec3.x, vec3.y, vec3.z);
|
|
}
|
|
|
|
h = this.getLiquidInertia();
|
|
} else {
|
|
h = this.getInertia();
|
|
}
|
|
|
|
this.setDeltaMovement(vec3.add(vec3.normalize().scale(this.accelerationPower)).scale(h));
|
|
ParticleOptions particleOptions = this.getTrailParticle();
|
|
if (particleOptions != null) {
|
|
this.level().addParticle(particleOptions, d, e + 0.5, f, 0.0, 0.0, 0.0);
|
|
}
|
|
|
|
this.setPos(d, e, f);
|
|
} else {
|
|
this.discard();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean hurt(DamageSource source, float amount) {
|
|
return !this.isInvulnerableTo(source);
|
|
}
|
|
|
|
@Override
|
|
protected boolean canHitEntity(Entity target) {
|
|
return super.canHitEntity(target) && !target.noPhysics;
|
|
}
|
|
|
|
protected boolean shouldBurn() {
|
|
return true;
|
|
}
|
|
|
|
@Nullable
|
|
protected ParticleOptions getTrailParticle() {
|
|
return ParticleTypes.SMOKE;
|
|
}
|
|
|
|
/**
|
|
* Return the motion factor for this projectile. The factor is multiplied by the original motion.
|
|
*/
|
|
protected float getInertia() {
|
|
return 0.95F;
|
|
}
|
|
|
|
protected float getLiquidInertia() {
|
|
return 0.8F;
|
|
}
|
|
|
|
@Override
|
|
public void addAdditionalSaveData(CompoundTag compound) {
|
|
super.addAdditionalSaveData(compound);
|
|
compound.putDouble("acceleration_power", this.accelerationPower);
|
|
}
|
|
|
|
@Override
|
|
public void readAdditionalSaveData(CompoundTag compound) {
|
|
super.readAdditionalSaveData(compound);
|
|
if (compound.contains("acceleration_power", 6)) {
|
|
this.accelerationPower = compound.getDouble("acceleration_power");
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public float getLightLevelDependentMagicValue() {
|
|
return 1.0F;
|
|
}
|
|
|
|
@Override
|
|
public Packet<ClientGamePacketListener> getAddEntityPacket(ServerEntity entity) {
|
|
Entity entity2 = this.getOwner();
|
|
int i = entity2 == null ? 0 : entity2.getId();
|
|
Vec3 vec3 = entity.getPositionBase();
|
|
return new ClientboundAddEntityPacket(
|
|
this.getId(),
|
|
this.getUUID(),
|
|
vec3.x(),
|
|
vec3.y(),
|
|
vec3.z(),
|
|
entity.getLastSentXRot(),
|
|
entity.getLastSentYRot(),
|
|
this.getType(),
|
|
i,
|
|
entity.getLastSentMovement(),
|
|
0.0
|
|
);
|
|
}
|
|
|
|
@Override
|
|
public void recreateFromPacket(ClientboundAddEntityPacket packet) {
|
|
super.recreateFromPacket(packet);
|
|
Vec3 vec3 = new Vec3(packet.getXa(), packet.getYa(), packet.getZa());
|
|
this.setDeltaMovement(vec3);
|
|
}
|
|
|
|
private void assignDirectionalMovement(Vec3 movement, double accelerationPower) {
|
|
this.setDeltaMovement(movement.normalize().scale(accelerationPower));
|
|
this.hasImpulse = true;
|
|
}
|
|
|
|
@Override
|
|
protected void onDeflection(@Nullable Entity entity, boolean deflectedByPlayer) {
|
|
super.onDeflection(entity, deflectedByPlayer);
|
|
if (deflectedByPlayer) {
|
|
this.accelerationPower = 0.1;
|
|
} else {
|
|
this.accelerationPower *= 0.5;
|
|
}
|
|
}
|
|
}
|