243 lines
9.4 KiB
Java
243 lines
9.4 KiB
Java
/*
|
|
* Decompiled with CFR 0.152.
|
|
*
|
|
* Could not load the following classes:
|
|
* org.jspecify.annotations.Nullable
|
|
*/
|
|
package net.minecraft.world.entity.projectile;
|
|
|
|
import java.util.Collection;
|
|
import java.util.List;
|
|
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.entity.projectile.AbstractArrow;
|
|
import net.minecraft.world.entity.projectile.ProjectileDeflection;
|
|
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.level.storage.ValueInput;
|
|
import net.minecraft.world.level.storage.ValueOutput;
|
|
import net.minecraft.world.phys.BlockHitResult;
|
|
import net.minecraft.world.phys.EntityHitResult;
|
|
import net.minecraft.world.phys.Vec3;
|
|
import org.jspecify.annotations.Nullable;
|
|
|
|
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> type, Level level) {
|
|
super((EntityType<? extends AbstractArrow>)type, level);
|
|
}
|
|
|
|
public ThrownTrident(Level level, LivingEntity owner, ItemStack tridentItem) {
|
|
super(EntityType.TRIDENT, owner, level, tridentItem, null);
|
|
this.entityData.set(ID_LOYALTY, this.getLoyaltyFromItem(tridentItem));
|
|
this.entityData.set(ID_FOIL, tridentItem.hasFoil());
|
|
}
|
|
|
|
public ThrownTrident(Level level, double x, double y, double z, ItemStack tridentItem) {
|
|
super(EntityType.TRIDENT, x, y, z, level, tridentItem, tridentItem);
|
|
this.entityData.set(ID_LOYALTY, this.getLoyaltyFromItem(tridentItem));
|
|
this.entityData.set(ID_FOIL, tridentItem.hasFoil());
|
|
}
|
|
|
|
@Override
|
|
protected void defineSynchedData(SynchedEntityData.Builder entityData) {
|
|
super.defineSynchedData(entityData);
|
|
entityData.define(ID_LOYALTY, (byte)0);
|
|
entityData.define(ID_FOIL, false);
|
|
}
|
|
|
|
@Override
|
|
public void tick() {
|
|
if (this.inGroundTime > 4) {
|
|
this.dealtDamage = true;
|
|
}
|
|
Entity currentOwner = this.getOwner();
|
|
byte loyalty = this.entityData.get(ID_LOYALTY);
|
|
if (loyalty > 0 && (this.dealtDamage || this.isNoPhysics()) && currentOwner != null) {
|
|
if (!this.isAcceptibleReturnOwner()) {
|
|
Level level = this.level();
|
|
if (level instanceof ServerLevel) {
|
|
ServerLevel level2 = (ServerLevel)level;
|
|
if (this.pickup == AbstractArrow.Pickup.ALLOWED) {
|
|
this.spawnAtLocation(level2, this.getPickupItem(), 0.1f);
|
|
}
|
|
}
|
|
this.discard();
|
|
} else {
|
|
if (!(currentOwner instanceof Player) && this.position().distanceTo(currentOwner.getEyePosition()) < (double)currentOwner.getBbWidth() + 1.0) {
|
|
this.discard();
|
|
return;
|
|
}
|
|
this.setNoPhysics(true);
|
|
Vec3 vec = currentOwner.getEyePosition().subtract(this.position());
|
|
this.setPosRaw(this.getX(), this.getY() + vec.y * 0.015 * (double)loyalty, this.getZ());
|
|
double accel = 0.05 * (double)loyalty;
|
|
this.setDeltaMovement(this.getDeltaMovement().scale(0.95).add(vec.normalize().scale(accel)));
|
|
if (this.clientSideReturnTridentTickCount == 0) {
|
|
this.playSound(SoundEvents.TRIDENT_RETURN, 10.0f, 1.0f);
|
|
}
|
|
++this.clientSideReturnTridentTickCount;
|
|
}
|
|
}
|
|
super.tick();
|
|
}
|
|
|
|
private boolean isAcceptibleReturnOwner() {
|
|
Entity currentOwner = this.getOwner();
|
|
if (currentOwner == null || !currentOwner.isAlive()) {
|
|
return false;
|
|
}
|
|
return !(currentOwner instanceof ServerPlayer) || !currentOwner.isSpectator();
|
|
}
|
|
|
|
public boolean isFoil() {
|
|
return this.entityData.get(ID_FOIL);
|
|
}
|
|
|
|
@Override
|
|
protected @Nullable EntityHitResult findHitEntity(Vec3 from, Vec3 to) {
|
|
if (this.dealtDamage) {
|
|
return null;
|
|
}
|
|
return super.findHitEntity(from, to);
|
|
}
|
|
|
|
@Override
|
|
protected Collection<EntityHitResult> findHitEntities(Vec3 from, Vec3 to) {
|
|
EntityHitResult e = this.findHitEntity(from, to);
|
|
if (e != null) {
|
|
return List.of(e);
|
|
}
|
|
return List.of();
|
|
}
|
|
|
|
@Override
|
|
protected void onHitEntity(EntityHitResult hitResult) {
|
|
ServerLevel serverLevel;
|
|
Entity entity = hitResult.getEntity();
|
|
float dmg = 8.0f;
|
|
Entity currentOwner = this.getOwner();
|
|
DamageSource damageSource = this.damageSources().trident(this, currentOwner == null ? this : currentOwner);
|
|
Level level = this.level();
|
|
if (level instanceof ServerLevel) {
|
|
serverLevel = (ServerLevel)level;
|
|
dmg = EnchantmentHelper.modifyDamage(serverLevel, this.getWeaponItem(), entity, damageSource, dmg);
|
|
}
|
|
this.dealtDamage = true;
|
|
if (entity.hurtOrSimulate(damageSource, dmg)) {
|
|
if (entity.getType() == EntityType.ENDERMAN) {
|
|
return;
|
|
}
|
|
level = this.level();
|
|
if (level instanceof ServerLevel) {
|
|
serverLevel = (ServerLevel)level;
|
|
EnchantmentHelper.doPostAttackEffectsWithItemSourceOnBreak(serverLevel, entity, damageSource, this.getWeaponItem(), weapon -> this.kill(serverLevel));
|
|
}
|
|
if (entity instanceof LivingEntity) {
|
|
LivingEntity mob = (LivingEntity)entity;
|
|
this.doKnockback(mob, damageSource);
|
|
this.doPostHurtEffects(mob);
|
|
}
|
|
}
|
|
this.deflect(ProjectileDeflection.REVERSE, entity, this.owner, 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 level, BlockHitResult hitResult, ItemStack weapon) {
|
|
LivingEntity livingOwner;
|
|
Vec3 compensatedHitPosition = hitResult.getBlockPos().clampLocationWithin(hitResult.getLocation());
|
|
Entity entity = this.getOwner();
|
|
EnchantmentHelper.onHitBlock(level, weapon, entity instanceof LivingEntity ? (livingOwner = (LivingEntity)entity) : null, this, null, compensatedHitPosition, level.getBlockState(hitResult.getBlockPos()), item -> this.kill(level));
|
|
}
|
|
|
|
@Override
|
|
public ItemStack getWeaponItem() {
|
|
return this.getPickupItemStackOrigin();
|
|
}
|
|
|
|
@Override
|
|
protected boolean tryPickup(Player player) {
|
|
return super.tryPickup(player) || this.isNoPhysics() && this.ownedBy(player) && player.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 player) {
|
|
if (this.ownedBy(player) || this.getOwner() == null) {
|
|
super.playerTouch(player);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void readAdditionalSaveData(ValueInput input) {
|
|
super.readAdditionalSaveData(input);
|
|
this.dealtDamage = input.getBooleanOr("DealtDamage", false);
|
|
this.entityData.set(ID_LOYALTY, this.getLoyaltyFromItem(this.getPickupItemStackOrigin()));
|
|
}
|
|
|
|
@Override
|
|
protected void addAdditionalSaveData(ValueOutput output) {
|
|
super.addAdditionalSaveData(output);
|
|
output.putBoolean("DealtDamage", this.dealtDamage);
|
|
}
|
|
|
|
private byte getLoyaltyFromItem(ItemStack tridentItem) {
|
|
Level level = this.level();
|
|
if (level instanceof ServerLevel) {
|
|
ServerLevel serverLevel = (ServerLevel)level;
|
|
return (byte)Mth.clamp(EnchantmentHelper.getTridentReturnToOwnerAcceleration(serverLevel, tridentItem, this), 0, 127);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
@Override
|
|
public void tickDespawn() {
|
|
byte loyalty = this.entityData.get(ID_LOYALTY);
|
|
if (this.pickup != AbstractArrow.Pickup.ALLOWED || loyalty <= 0) {
|
|
super.tickDespawn();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected float getWaterInertia() {
|
|
return 0.99f;
|
|
}
|
|
|
|
@Override
|
|
public boolean shouldRender(double camX, double camY, double camZ) {
|
|
return true;
|
|
}
|
|
}
|
|
|