package net.minecraft.world.entity.projectile; import javax.annotation.Nullable; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvents; import net.minecraft.util.Mth; 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.player.Player; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.item.enchantment.EnchantmentHelper; import net.minecraft.world.level.Level; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.EntityHitResult; import net.minecraft.world.phys.Vec3; public class ThrownTrident extends AbstractArrow { private static final EntityDataAccessor ID_LOYALTY = SynchedEntityData.defineId(ThrownTrident.class, EntityDataSerializers.BYTE); private static final EntityDataAccessor ID_FOIL = SynchedEntityData.defineId(ThrownTrident.class, EntityDataSerializers.BOOLEAN); private static final float WATER_INERTIA = 0.99F; private static final boolean DEFAULT_DEALT_DAMAGE = false; private boolean dealtDamage = false; public int clientSideReturnTridentTickCount; public ThrownTrident(EntityType p_37561_, Level p_37562_) { super(p_37561_, p_37562_); } public ThrownTrident(Level p_37569_, LivingEntity p_37570_, ItemStack p_37571_) { super(EntityType.TRIDENT, p_37570_, p_37569_, p_37571_, null); this.entityData.set(ID_LOYALTY, this.getLoyaltyFromItem(p_37571_)); this.entityData.set(ID_FOIL, p_37571_.hasFoil()); } public ThrownTrident(Level p_334242_, double p_336226_, double p_330090_, double p_331538_, ItemStack p_333817_) { super(EntityType.TRIDENT, p_336226_, p_330090_, p_331538_, p_334242_, p_333817_, p_333817_); this.entityData.set(ID_LOYALTY, this.getLoyaltyFromItem(p_333817_)); this.entityData.set(ID_FOIL, p_333817_.hasFoil()); } @Override protected void defineSynchedData(SynchedEntityData.Builder p_332339_) { super.defineSynchedData(p_332339_); p_332339_.define(ID_LOYALTY, (byte)0); p_332339_.define(ID_FOIL, false); } @Override public void tick() { if (this.inGroundTime > 4) { this.dealtDamage = true; } Entity entity = this.getOwner(); int i = this.entityData.get(ID_LOYALTY); if (i > 0 && (this.dealtDamage || this.isNoPhysics()) && entity != null) { if (!this.isAcceptibleReturnOwner()) { if (this.level() instanceof ServerLevel serverlevel && this.pickup == AbstractArrow.Pickup.ALLOWED) { this.spawnAtLocation(serverlevel, this.getPickupItem(), 0.1F); } this.discard(); } else { if (!(entity instanceof Player) && this.position().distanceTo(entity.getEyePosition()) < entity.getBbWidth() + 1.0) { this.discard(); return; } this.setNoPhysics(true); Vec3 vec3 = entity.getEyePosition().subtract(this.position()); this.setPosRaw(this.getX(), this.getY() + vec3.y * 0.015 * i, this.getZ()); double d0 = 0.05 * i; this.setDeltaMovement(this.getDeltaMovement().scale(0.95).add(vec3.normalize().scale(d0))); if (this.clientSideReturnTridentTickCount == 0) { this.playSound(SoundEvents.TRIDENT_RETURN, 10.0F, 1.0F); } this.clientSideReturnTridentTickCount++; } } super.tick(); } private boolean isAcceptibleReturnOwner() { Entity entity = this.getOwner(); return entity == null || !entity.isAlive() ? false : !(entity instanceof ServerPlayer) || !entity.isSpectator(); } public boolean isFoil() { return this.entityData.get(ID_FOIL); } @Nullable @Override protected EntityHitResult findHitEntity(Vec3 p_37575_, Vec3 p_37576_) { return this.dealtDamage ? null : super.findHitEntity(p_37575_, p_37576_); } @Override protected void onHitEntity(EntityHitResult p_37573_) { Entity entity = p_37573_.getEntity(); float f = 8.0F; Entity entity1 = this.getOwner(); DamageSource damagesource = this.damageSources().trident(this, (Entity)(entity1 == null ? this : entity1)); if (this.level() instanceof ServerLevel serverlevel) { f = EnchantmentHelper.modifyDamage(serverlevel, this.getWeaponItem(), entity, damagesource, f); } this.dealtDamage = true; if (entity.hurtOrSimulate(damagesource, f)) { if (entity.getType() == EntityType.ENDERMAN) { return; } if (this.level() instanceof ServerLevel serverlevel1) { EnchantmentHelper.doPostAttackEffectsWithItemSourceOnBreak(serverlevel1, entity, damagesource, this.getWeaponItem(), p_359359_ -> this.kill(serverlevel1)); } if (entity instanceof LivingEntity livingentity) { this.doKnockback(livingentity, damagesource); this.doPostHurtEffects(livingentity); } } this.deflect(ProjectileDeflection.REVERSE, entity, this.getOwner(), false); this.setDeltaMovement(this.getDeltaMovement().multiply(0.02, 0.2, 0.02)); this.playSound(SoundEvents.TRIDENT_HIT, 1.0F, 1.0F); } @Override protected void hitBlockEnchantmentEffects(ServerLevel p_344367_, BlockHitResult p_343898_, ItemStack p_344547_) { Vec3 vec3 = p_343898_.getBlockPos().clampLocationWithin(p_343898_.getLocation()); EnchantmentHelper.onHitBlock( p_344367_, p_344547_, this.getOwner() instanceof LivingEntity livingentity ? livingentity : null, this, null, vec3, p_344367_.getBlockState(p_343898_.getBlockPos()), p_359361_ -> this.kill(p_344367_) ); } @Override public ItemStack getWeaponItem() { return this.getPickupItemStackOrigin(); } @Override protected boolean tryPickup(Player p_150196_) { return super.tryPickup(p_150196_) || this.isNoPhysics() && this.ownedBy(p_150196_) && p_150196_.getInventory().add(this.getPickupItem()); } @Override protected ItemStack getDefaultPickupItem() { return new ItemStack(Items.TRIDENT); } @Override protected SoundEvent getDefaultHitGroundSoundEvent() { return SoundEvents.TRIDENT_HIT_GROUND; } @Override public void playerTouch(Player p_37580_) { if (this.ownedBy(p_37580_) || this.getOwner() == null) { super.playerTouch(p_37580_); } } @Override public void readAdditionalSaveData(CompoundTag p_37578_) { super.readAdditionalSaveData(p_37578_); this.dealtDamage = p_37578_.getBooleanOr("DealtDamage", false); this.entityData.set(ID_LOYALTY, this.getLoyaltyFromItem(this.getPickupItemStackOrigin())); } @Override public void addAdditionalSaveData(CompoundTag p_37582_) { super.addAdditionalSaveData(p_37582_); p_37582_.putBoolean("DealtDamage", this.dealtDamage); } private byte getLoyaltyFromItem(ItemStack p_343400_) { return this.level() instanceof ServerLevel serverlevel ? (byte)Mth.clamp(EnchantmentHelper.getTridentReturnToOwnerAcceleration(serverlevel, p_343400_, this), 0, 127) : 0; } @Override public void tickDespawn() { int i = this.entityData.get(ID_LOYALTY); if (this.pickup != AbstractArrow.Pickup.ALLOWED || i <= 0) { super.tickDespawn(); } } @Override protected float getWaterInertia() { return 0.99F; } @Override public boolean shouldRender(double p_37588_, double p_37589_, double p_37590_) { return true; } }