minecraft-src/net/minecraft/world/entity/projectile/EvokerFangs.java
2025-07-04 03:45:38 +03:00

159 lines
5 KiB
Java

package net.minecraft.world.entity.projectile;
import java.util.UUID;
import net.minecraft.core.UUIDUtil;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.syncher.SynchedEntityData.Builder;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundEvents;
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.entity.TraceableEntity;
import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.level.Level;
import org.jetbrains.annotations.Nullable;
public class EvokerFangs extends Entity implements TraceableEntity {
public static final int ATTACK_DURATION = 20;
public static final int LIFE_OFFSET = 2;
public static final int ATTACK_TRIGGER_TICKS = 14;
private static final int DEFAULT_WARMUP_DELAY = 0;
private int warmupDelayTicks = 0;
private boolean sentSpikeEvent;
private int lifeTicks = 22;
private boolean clientSideAttackStarted;
@Nullable
private LivingEntity owner;
@Nullable
private UUID ownerUUID;
public EvokerFangs(EntityType<? extends EvokerFangs> entityType, Level level) {
super(entityType, level);
}
public EvokerFangs(Level level, double x, double y, double z, float yRot, int warmupDelay, LivingEntity owner) {
this(EntityType.EVOKER_FANGS, level);
this.warmupDelayTicks = warmupDelay;
this.setOwner(owner);
this.setYRot(yRot * (180.0F / (float)Math.PI));
this.setPos(x, y, z);
}
@Override
protected void defineSynchedData(Builder builder) {
}
public void setOwner(@Nullable LivingEntity owner) {
this.owner = owner;
this.ownerUUID = owner == null ? null : owner.getUUID();
}
@Nullable
public LivingEntity getOwner() {
if (this.owner == null && this.ownerUUID != null && this.level() instanceof ServerLevel) {
Entity entity = ((ServerLevel)this.level()).getEntity(this.ownerUUID);
if (entity instanceof LivingEntity) {
this.owner = (LivingEntity)entity;
}
}
return this.owner;
}
@Override
protected void readAdditionalSaveData(CompoundTag tag) {
this.warmupDelayTicks = tag.getIntOr("Warmup", 0);
this.ownerUUID = (UUID)tag.read("Owner", UUIDUtil.CODEC).orElse(null);
}
@Override
protected void addAdditionalSaveData(CompoundTag tag) {
tag.putInt("Warmup", this.warmupDelayTicks);
tag.storeNullable("Owner", UUIDUtil.CODEC, this.ownerUUID);
}
@Override
public void tick() {
super.tick();
if (this.level().isClientSide) {
if (this.clientSideAttackStarted) {
this.lifeTicks--;
if (this.lifeTicks == 14) {
for (int i = 0; i < 12; i++) {
double d = this.getX() + (this.random.nextDouble() * 2.0 - 1.0) * this.getBbWidth() * 0.5;
double e = this.getY() + 0.05 + this.random.nextDouble();
double f = this.getZ() + (this.random.nextDouble() * 2.0 - 1.0) * this.getBbWidth() * 0.5;
double g = (this.random.nextDouble() * 2.0 - 1.0) * 0.3;
double h = 0.3 + this.random.nextDouble() * 0.3;
double j = (this.random.nextDouble() * 2.0 - 1.0) * 0.3;
this.level().addParticle(ParticleTypes.CRIT, d, e + 1.0, f, g, h, j);
}
}
}
} else if (--this.warmupDelayTicks < 0) {
if (this.warmupDelayTicks == -8) {
for (LivingEntity livingEntity : this.level().getEntitiesOfClass(LivingEntity.class, this.getBoundingBox().inflate(0.2, 0.0, 0.2))) {
this.dealDamageTo(livingEntity);
}
}
if (!this.sentSpikeEvent) {
this.level().broadcastEntityEvent(this, (byte)4);
this.sentSpikeEvent = true;
}
if (--this.lifeTicks < 0) {
this.discard();
}
}
}
private void dealDamageTo(LivingEntity target) {
LivingEntity livingEntity = this.getOwner();
if (target.isAlive() && !target.isInvulnerable() && target != livingEntity) {
if (livingEntity == null) {
target.hurt(this.damageSources().magic(), 6.0F);
} else {
if (livingEntity.isAlliedTo(target)) {
return;
}
DamageSource damageSource = this.damageSources().indirectMagic(this, livingEntity);
if (this.level() instanceof ServerLevel serverLevel && target.hurtServer(serverLevel, damageSource, 6.0F)) {
EnchantmentHelper.doPostAttackEffects(serverLevel, target, damageSource);
}
}
}
}
@Override
public void handleEntityEvent(byte id) {
super.handleEntityEvent(id);
if (id == 4) {
this.clientSideAttackStarted = true;
if (!this.isSilent()) {
this.level()
.playLocalSound(
this.getX(), this.getY(), this.getZ(), SoundEvents.EVOKER_FANGS_ATTACK, this.getSoundSource(), 1.0F, this.random.nextFloat() * 0.2F + 0.85F, false
);
}
}
}
public float getAnimationProgress(float partialTicks) {
if (!this.clientSideAttackStarted) {
return 0.0F;
} else {
int i = this.lifeTicks - 2;
return i <= 0 ? 1.0F : 1.0F - (i - partialTicks) / 20.0F;
}
}
@Override
public boolean hurtServer(ServerLevel level, DamageSource damageSource, float amount) {
return false;
}
}