157 lines
		
	
	
	
		
			4.7 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			157 lines
		
	
	
	
		
			4.7 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| package net.minecraft.world.damagesource;
 | |
| 
 | |
| import net.minecraft.core.Holder;
 | |
| import net.minecraft.core.component.DataComponents;
 | |
| import net.minecraft.network.chat.Component;
 | |
| import net.minecraft.resources.ResourceKey;
 | |
| import net.minecraft.tags.TagKey;
 | |
| import net.minecraft.world.entity.Entity;
 | |
| import net.minecraft.world.entity.LivingEntity;
 | |
| import net.minecraft.world.entity.player.Player;
 | |
| import net.minecraft.world.item.ItemStack;
 | |
| import net.minecraft.world.phys.Vec3;
 | |
| import org.jetbrains.annotations.Nullable;
 | |
| 
 | |
| public class DamageSource {
 | |
| 	private final Holder<DamageType> type;
 | |
| 	@Nullable
 | |
| 	private final Entity causingEntity;
 | |
| 	@Nullable
 | |
| 	private final Entity directEntity;
 | |
| 	@Nullable
 | |
| 	private final Vec3 damageSourcePosition;
 | |
| 
 | |
| 	public String toString() {
 | |
| 		return "DamageSource (" + this.type().msgId() + ")";
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * How much satiate (food) is consumed by this {@code DamageSource}.
 | |
| 	 */
 | |
| 	public float getFoodExhaustion() {
 | |
| 		return this.type().exhaustion();
 | |
| 	}
 | |
| 
 | |
| 	public boolean isDirect() {
 | |
| 		return this.causingEntity == this.directEntity;
 | |
| 	}
 | |
| 
 | |
| 	private DamageSource(Holder<DamageType> type, @Nullable Entity directEntity, @Nullable Entity causingEntity, @Nullable Vec3 damageSourcePosition) {
 | |
| 		this.type = type;
 | |
| 		this.causingEntity = causingEntity;
 | |
| 		this.directEntity = directEntity;
 | |
| 		this.damageSourcePosition = damageSourcePosition;
 | |
| 	}
 | |
| 
 | |
| 	public DamageSource(Holder<DamageType> type, @Nullable Entity directEntity, @Nullable Entity causingEntity) {
 | |
| 		this(type, directEntity, causingEntity, null);
 | |
| 	}
 | |
| 
 | |
| 	public DamageSource(Holder<DamageType> type, Vec3 damageSourcePosition) {
 | |
| 		this(type, null, null, damageSourcePosition);
 | |
| 	}
 | |
| 
 | |
| 	public DamageSource(Holder<DamageType> type, @Nullable Entity entity) {
 | |
| 		this(type, entity, entity);
 | |
| 	}
 | |
| 
 | |
| 	public DamageSource(Holder<DamageType> type) {
 | |
| 		this(type, null, null, null);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Retrieves the immediate causer of the damage, e.g. the arrow entity, not its shooter
 | |
| 	 */
 | |
| 	@Nullable
 | |
| 	public Entity getDirectEntity() {
 | |
| 		return this.directEntity;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Retrieves the true causer of the damage, e.g. the player who fired an arrow, the shulker who fired the bullet, etc.
 | |
| 	 */
 | |
| 	@Nullable
 | |
| 	public Entity getEntity() {
 | |
| 		return this.causingEntity;
 | |
| 	}
 | |
| 
 | |
| 	@Nullable
 | |
| 	public ItemStack getWeaponItem() {
 | |
| 		return this.directEntity != null ? this.directEntity.getWeaponItem() : null;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Gets the death message that is displayed when the player dies
 | |
| 	 */
 | |
| 	public Component getLocalizedDeathMessage(LivingEntity livingEntity) {
 | |
| 		String string = "death.attack." + this.type().msgId();
 | |
| 		if (this.causingEntity == null && this.directEntity == null) {
 | |
| 			LivingEntity livingEntity3 = livingEntity.getKillCredit();
 | |
| 			String string2 = string + ".player";
 | |
| 			return livingEntity3 != null
 | |
| 				? Component.translatable(string2, livingEntity.getDisplayName(), livingEntity3.getDisplayName())
 | |
| 				: Component.translatable(string, livingEntity.getDisplayName());
 | |
| 		} else {
 | |
| 			Component component = this.causingEntity == null ? this.directEntity.getDisplayName() : this.causingEntity.getDisplayName();
 | |
| 			ItemStack itemStack = this.causingEntity instanceof LivingEntity livingEntity2 ? livingEntity2.getMainHandItem() : ItemStack.EMPTY;
 | |
| 			return !itemStack.isEmpty() && itemStack.has(DataComponents.CUSTOM_NAME)
 | |
| 				? Component.translatable(string + ".item", livingEntity.getDisplayName(), component, itemStack.getDisplayName())
 | |
| 				: Component.translatable(string, livingEntity.getDisplayName(), component);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Return the name of damage type.
 | |
| 	 */
 | |
| 	public String getMsgId() {
 | |
| 		return this.type().msgId();
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Return whether this damage source will have its damage amount scaled based on the current difficulty.
 | |
| 	 */
 | |
| 	public boolean scalesWithDifficulty() {
 | |
| 		return switch (this.type().scaling()) {
 | |
| 			case NEVER -> false;
 | |
| 			case WHEN_CAUSED_BY_LIVING_NON_PLAYER -> this.causingEntity instanceof LivingEntity && !(this.causingEntity instanceof Player);
 | |
| 			case ALWAYS -> true;
 | |
| 		};
 | |
| 	}
 | |
| 
 | |
| 	public boolean isCreativePlayer() {
 | |
| 		return this.getEntity() instanceof Player player && player.getAbilities().instabuild;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Gets the location from which the damage originates.
 | |
| 	 */
 | |
| 	@Nullable
 | |
| 	public Vec3 getSourcePosition() {
 | |
| 		if (this.damageSourcePosition != null) {
 | |
| 			return this.damageSourcePosition;
 | |
| 		} else {
 | |
| 			return this.directEntity != null ? this.directEntity.position() : null;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	@Nullable
 | |
| 	public Vec3 sourcePositionRaw() {
 | |
| 		return this.damageSourcePosition;
 | |
| 	}
 | |
| 
 | |
| 	public boolean is(TagKey<DamageType> damageTypeKey) {
 | |
| 		return this.type.is(damageTypeKey);
 | |
| 	}
 | |
| 
 | |
| 	public boolean is(ResourceKey<DamageType> damageTypeKey) {
 | |
| 		return this.type.is(damageTypeKey);
 | |
| 	}
 | |
| 
 | |
| 	public DamageType type() {
 | |
| 		return this.type.value();
 | |
| 	}
 | |
| 
 | |
| 	public Holder<DamageType> typeHolder() {
 | |
| 		return this.type;
 | |
| 	}
 | |
| }
 |