217 lines
8.3 KiB
Java
217 lines
8.3 KiB
Java
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<Byte> ID_LOYALTY = SynchedEntityData.defineId(ThrownTrident.class, EntityDataSerializers.BYTE);
|
|
private static final EntityDataAccessor<Boolean> 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<? extends ThrownTrident> 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;
|
|
}
|
|
} |