package net.minecraft.world.entity; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Objects; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.mojang.datafixers.util.Pair; import com.mojang.logging.LogUtils; import com.mojang.serialization.DataResult; import com.mojang.serialization.Dynamic; import it.unimi.dsi.fastutil.doubles.DoubleDoubleImmutablePair; import it.unimi.dsi.fastutil.objects.Reference2ObjectArrayMap; import it.unimi.dsi.fastutil.objects.Reference2ObjectMap; import java.util.Collection; import java.util.ConcurrentModificationException; import java.util.EnumMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.UUID; import java.util.Map.Entry; import java.util.function.BiConsumer; import java.util.function.Function; import java.util.function.Predicate; import javax.annotation.Nonnull; import javax.annotation.Nullable; import net.minecraft.BlockUtil; import net.minecraft.Util; import net.minecraft.advancements.CriteriaTriggers; import net.minecraft.commands.arguments.EntityAnchorArgument; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Holder; import net.minecraft.core.component.DataComponents; import net.minecraft.core.particles.BlockParticleOption; import net.minecraft.core.particles.ItemParticleOption; import net.minecraft.core.particles.ParticleOptions; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.Tag; import net.minecraft.network.protocol.game.ClientboundAddEntityPacket; import net.minecraft.network.protocol.game.ClientboundAnimatePacket; import net.minecraft.network.protocol.game.ClientboundEntityEventPacket; import net.minecraft.network.protocol.game.ClientboundRemoveMobEffectPacket; import net.minecraft.network.protocol.game.ClientboundSetEquipmentPacket; import net.minecraft.network.protocol.game.ClientboundTakeItemEntityPacket; import net.minecraft.network.protocol.game.ClientboundUpdateMobEffectPacket; import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.resources.RegistryOps; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerChunkCache; 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.sounds.SoundSource; import net.minecraft.stats.Stats; import net.minecraft.tags.BlockTags; import net.minecraft.tags.DamageTypeTags; import net.minecraft.tags.EntityTypeTags; import net.minecraft.tags.FluidTags; import net.minecraft.tags.ItemTags; import net.minecraft.tags.TagKey; import net.minecraft.util.Mth; import net.minecraft.util.profiling.Profiler; import net.minecraft.util.profiling.ProfilerFiller; import net.minecraft.world.Difficulty; import net.minecraft.world.InteractionHand; import net.minecraft.world.damagesource.CombatRules; import net.minecraft.world.damagesource.CombatTracker; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.damagesource.DamageTypes; import net.minecraft.world.effect.MobEffect; import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.effect.MobEffectUtil; import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.ai.Brain; import net.minecraft.world.entity.ai.attributes.Attribute; import net.minecraft.world.entity.ai.attributes.AttributeInstance; import net.minecraft.world.entity.ai.attributes.AttributeMap; import net.minecraft.world.entity.ai.attributes.AttributeModifier; import net.minecraft.world.entity.ai.attributes.AttributeSupplier; import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.entity.ai.attributes.DefaultAttributes; import net.minecraft.world.entity.animal.FlyingAnimal; import net.minecraft.world.entity.animal.wolf.Wolf; import net.minecraft.world.entity.boss.wither.WitherBoss; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.projectile.AbstractArrow; import net.minecraft.world.entity.projectile.Projectile; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.item.component.BlocksAttacks; import net.minecraft.world.item.component.DeathProtection; import net.minecraft.world.item.component.Weapon; import net.minecraft.world.item.enchantment.Enchantment; import net.minecraft.world.item.enchantment.EnchantmentHelper; import net.minecraft.world.item.enchantment.effects.EnchantmentLocationBasedEffect; import net.minecraft.world.item.equipment.Equippable; import net.minecraft.world.level.ClipContext; import net.minecraft.world.level.GameRules; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.BedBlock; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.HoneyBlock; import net.minecraft.world.level.block.LadderBlock; import net.minecraft.world.level.block.PowderSnowBlock; import net.minecraft.world.level.block.SoundType; import net.minecraft.world.level.block.TrapDoorBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.gameevent.GameEvent; import net.minecraft.world.level.material.Fluid; import net.minecraft.world.level.material.FluidState; import net.minecraft.world.level.storage.loot.LootParams; import net.minecraft.world.level.storage.loot.LootTable; import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; import net.minecraft.world.level.storage.loot.parameters.LootContextParams; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.world.scores.PlayerTeam; import net.minecraft.world.scores.Scoreboard; import org.jetbrains.annotations.Contract; import org.slf4j.Logger; public abstract class LivingEntity extends Entity implements Attackable { private static final Logger LOGGER = LogUtils.getLogger(); private static final String TAG_ACTIVE_EFFECTS = "active_effects"; private static final ResourceLocation SPEED_MODIFIER_POWDER_SNOW_ID = ResourceLocation.withDefaultNamespace("powder_snow"); private static final ResourceLocation SPRINTING_MODIFIER_ID = ResourceLocation.withDefaultNamespace("sprinting"); private static final AttributeModifier SPEED_MODIFIER_SPRINTING = new AttributeModifier(SPRINTING_MODIFIER_ID, 0.3F, AttributeModifier.Operation.ADD_MULTIPLIED_TOTAL); public static final int EQUIPMENT_SLOT_OFFSET = 98; public static final int ARMOR_SLOT_OFFSET = 100; public static final int BODY_ARMOR_OFFSET = 105; public static final int SADDLE_OFFSET = 106; public static final int SWING_DURATION = 6; public static final int PLAYER_HURT_EXPERIENCE_TIME = 100; private static final int DAMAGE_SOURCE_TIMEOUT = 40; public static final double MIN_MOVEMENT_DISTANCE = 0.003; public static final double DEFAULT_BASE_GRAVITY = 0.08; public static final int DEATH_DURATION = 20; protected static final float INPUT_FRICTION = 0.98F; private static final int TICKS_PER_ELYTRA_FREE_FALL_EVENT = 10; private static final int FREE_FALL_EVENTS_PER_ELYTRA_BREAK = 2; public static final float BASE_JUMP_POWER = 0.42F; private static final double MAX_LINE_OF_SIGHT_TEST_RANGE = 128.0; protected static final int LIVING_ENTITY_FLAG_IS_USING = 1; protected static final int LIVING_ENTITY_FLAG_OFF_HAND = 2; protected static final int LIVING_ENTITY_FLAG_SPIN_ATTACK = 4; protected static final EntityDataAccessor DATA_LIVING_ENTITY_FLAGS = SynchedEntityData.defineId(LivingEntity.class, EntityDataSerializers.BYTE); private static final EntityDataAccessor DATA_HEALTH_ID = SynchedEntityData.defineId(LivingEntity.class, EntityDataSerializers.FLOAT); private static final EntityDataAccessor> DATA_EFFECT_PARTICLES = SynchedEntityData.defineId(LivingEntity.class, EntityDataSerializers.PARTICLES); private static final EntityDataAccessor DATA_EFFECT_AMBIENCE_ID = SynchedEntityData.defineId(LivingEntity.class, EntityDataSerializers.BOOLEAN); private static final EntityDataAccessor DATA_ARROW_COUNT_ID = SynchedEntityData.defineId(LivingEntity.class, EntityDataSerializers.INT); private static final EntityDataAccessor DATA_STINGER_COUNT_ID = SynchedEntityData.defineId(LivingEntity.class, EntityDataSerializers.INT); private static final EntityDataAccessor> SLEEPING_POS_ID = SynchedEntityData.defineId(LivingEntity.class, EntityDataSerializers.OPTIONAL_BLOCK_POS); private static final int PARTICLE_FREQUENCY_WHEN_INVISIBLE = 15; protected static final EntityDimensions SLEEPING_DIMENSIONS = EntityDimensions.fixed(0.2F, 0.2F).withEyeHeight(0.2F); public static final float EXTRA_RENDER_CULLING_SIZE_WITH_BIG_HAT = 0.5F; public static final float DEFAULT_BABY_SCALE = 0.5F; public static final String ATTRIBUTES_FIELD = "attributes"; public static final Predicate PLAYER_NOT_WEARING_DISGUISE_ITEM = p_390518_ -> { if (p_390518_ instanceof Player player) { ItemStack itemstack = player.getItemBySlot(EquipmentSlot.HEAD); return !itemstack.is(ItemTags.GAZE_DISGUISE_EQUIPMENT); } else { return true; } }; private final AttributeMap attributes; private final CombatTracker combatTracker = new CombatTracker(this); private final Map, MobEffectInstance> activeEffects = Maps.newHashMap(); private final Map lastEquipmentItems = Util.makeEnumMap(EquipmentSlot.class, p_390519_ -> ItemStack.EMPTY); public boolean swinging; private boolean discardFriction = false; public InteractionHand swingingArm; public int swingTime; public int removeArrowTime; public int removeStingerTime; public int hurtTime; public int hurtDuration; public int deathTime; public float oAttackAnim; public float attackAnim; protected int attackStrengthTicker; public final WalkAnimationState walkAnimation = new WalkAnimationState(); public final int invulnerableDuration = 20; public float yBodyRot; public float yBodyRotO; public float yHeadRot; public float yHeadRotO; public final ElytraAnimationState elytraAnimationState = new ElytraAnimationState(this); @Nullable protected EntityReference lastHurtByPlayer; protected int lastHurtByPlayerMemoryTime; protected boolean dead; protected int noActionTime; protected float lastHurt; protected boolean jumping; public float xxa; public float yya; public float zza; protected InterpolationHandler interpolation = new InterpolationHandler(this); protected double lerpYHeadRot; protected int lerpHeadSteps; private boolean effectsDirty = true; @Nullable private EntityReference lastHurtByMob; private int lastHurtByMobTimestamp; @Nullable private LivingEntity lastHurtMob; private int lastHurtMobTimestamp; private float speed; private int noJumpDelay; private float absorptionAmount; protected ItemStack useItem = ItemStack.EMPTY; protected int useItemRemaining; protected int fallFlyTicks; private BlockPos lastPos; private Optional lastClimbablePos = Optional.empty(); @Nullable private DamageSource lastDamageSource; private long lastDamageStamp; protected int autoSpinAttackTicks; protected float autoSpinAttackDmg; @Nullable protected ItemStack autoSpinAttackItemStack; private float swimAmount; private float swimAmountO; protected Brain brain; private boolean skipDropExperience; private final EnumMap>> activeLocationDependentEnchantments = new EnumMap<>(EquipmentSlot.class); protected final EntityEquipment equipment; protected LivingEntity(EntityType p_20966_, Level p_20967_) { super(p_20966_, p_20967_); this.attributes = new AttributeMap(DefaultAttributes.getSupplier(p_20966_)); this.setHealth(this.getMaxHealth()); this.equipment = this.createEquipment(); this.blocksBuilding = true; this.reapplyPosition(); this.setYRot((float)(Math.random() * (float) (Math.PI * 2))); this.yHeadRot = this.getYRot(); NbtOps nbtops = NbtOps.INSTANCE; this.brain = this.makeBrain(new Dynamic<>(nbtops, nbtops.createMap(ImmutableMap.of(nbtops.createString("memories"), nbtops.emptyMap())))); } @Contract( pure = true ) protected EntityEquipment createEquipment() { return new EntityEquipment(); } public Brain getBrain() { return this.brain; } protected Brain.Provider brainProvider() { return Brain.provider(ImmutableList.of(), ImmutableList.of()); } protected Brain makeBrain(Dynamic p_21069_) { return this.brainProvider().makeBrain(p_21069_); } @Override public void kill(ServerLevel p_367431_) { this.hurtServer(p_367431_, this.damageSources().genericKill(), Float.MAX_VALUE); } public boolean canAttackType(EntityType p_21032_) { return true; } @Override protected void defineSynchedData(SynchedEntityData.Builder p_329703_) { p_329703_.define(DATA_LIVING_ENTITY_FLAGS, (byte)0); p_329703_.define(DATA_EFFECT_PARTICLES, List.of()); p_329703_.define(DATA_EFFECT_AMBIENCE_ID, false); p_329703_.define(DATA_ARROW_COUNT_ID, 0); p_329703_.define(DATA_STINGER_COUNT_ID, 0); p_329703_.define(DATA_HEALTH_ID, 1.0F); p_329703_.define(SLEEPING_POS_ID, Optional.empty()); } public static AttributeSupplier.Builder createLivingAttributes() { return AttributeSupplier.builder() .add(Attributes.MAX_HEALTH) .add(Attributes.KNOCKBACK_RESISTANCE) .add(Attributes.MOVEMENT_SPEED) .add(Attributes.ARMOR) .add(Attributes.ARMOR_TOUGHNESS) .add(Attributes.MAX_ABSORPTION) .add(Attributes.STEP_HEIGHT) .add(Attributes.SCALE) .add(Attributes.GRAVITY) .add(Attributes.SAFE_FALL_DISTANCE) .add(Attributes.FALL_DAMAGE_MULTIPLIER) .add(Attributes.JUMP_STRENGTH) .add(Attributes.OXYGEN_BONUS) .add(Attributes.BURNING_TIME) .add(Attributes.EXPLOSION_KNOCKBACK_RESISTANCE) .add(Attributes.WATER_MOVEMENT_EFFICIENCY) .add(Attributes.MOVEMENT_EFFICIENCY) .add(Attributes.ATTACK_KNOCKBACK); } @Override protected void checkFallDamage(double p_20990_, boolean p_20991_, BlockState p_20992_, BlockPos p_20993_) { if (!this.isInWater()) { this.updateInWaterStateAndDoWaterCurrentPushing(); } if (this.level() instanceof ServerLevel serverlevel && p_20991_ && this.fallDistance > 0.0) { this.onChangedBlock(serverlevel, p_20993_); double d6 = Math.max(0, Mth.floor(this.calculateFallPower(this.fallDistance))); if (d6 > 0.0 && !p_20992_.isAir()) { double d0 = this.getX(); double d1 = this.getY(); double d2 = this.getZ(); BlockPos blockpos = this.blockPosition(); if (p_20993_.getX() != blockpos.getX() || p_20993_.getZ() != blockpos.getZ()) { double d3 = d0 - p_20993_.getX() - 0.5; double d4 = d2 - p_20993_.getZ() - 0.5; double d5 = Math.max(Math.abs(d3), Math.abs(d4)); d0 = p_20993_.getX() + 0.5 + d3 / d5 * 0.5; d2 = p_20993_.getZ() + 0.5 + d4 / d5 * 0.5; } double d7 = Math.min(0.2F + d6 / 15.0, 2.5); int i = (int)(150.0 * d7); serverlevel.sendParticles(new BlockParticleOption(ParticleTypes.BLOCK, p_20992_), d0, d1, d2, i, 0.0, 0.0, 0.0, 0.15F); } } super.checkFallDamage(p_20990_, p_20991_, p_20992_, p_20993_); if (p_20991_) { this.lastClimbablePos = Optional.empty(); } } public final boolean canBreatheUnderwater() { return this.getType().is(EntityTypeTags.CAN_BREATHE_UNDER_WATER); } public float getSwimAmount(float p_20999_) { return Mth.lerp(p_20999_, this.swimAmountO, this.swimAmount); } public boolean hasLandedInLiquid() { return this.getDeltaMovement().y() < 1.0E-5F && this.isInLiquid(); } @Override public void baseTick() { this.oAttackAnim = this.attackAnim; if (this.firstTick) { this.getSleepingPos().ifPresent(this::setPosToBed); } if (this.level() instanceof ServerLevel serverlevel) { EnchantmentHelper.tickEffects(serverlevel, this); } super.baseTick(); ProfilerFiller profilerfiller = Profiler.get(); profilerfiller.push("livingEntityBaseTick"); if (this.fireImmune() || this.level().isClientSide) { this.clearFire(); } if (this.isAlive() && this.level() instanceof ServerLevel serverlevel1) { boolean flag = this instanceof Player; if (this.isInWall()) { this.hurtServer(serverlevel1, this.damageSources().inWall(), 1.0F); } else if (flag && !serverlevel1.getWorldBorder().isWithinBounds(this.getBoundingBox())) { double d0 = serverlevel1.getWorldBorder().getDistanceToBorder(this) + serverlevel1.getWorldBorder().getDamageSafeZone(); if (d0 < 0.0) { double d1 = serverlevel1.getWorldBorder().getDamagePerBlock(); if (d1 > 0.0) { this.hurtServer(serverlevel1, this.damageSources().outOfBorder(), Math.max(1, Mth.floor(-d0 * d1))); } } } if (this.isEyeInFluid(FluidTags.WATER) && !serverlevel1.getBlockState(BlockPos.containing(this.getX(), this.getEyeY(), this.getZ())).is(Blocks.BUBBLE_COLUMN)) { boolean flag1 = !this.canBreatheUnderwater() && !MobEffectUtil.hasWaterBreathing(this) && (!flag || !((Player)this).getAbilities().invulnerable); if (flag1) { this.setAirSupply(this.decreaseAirSupply(this.getAirSupply())); if (this.getAirSupply() == -20) { this.setAirSupply(0); serverlevel1.broadcastEntityEvent(this, (byte)67); this.hurtServer(serverlevel1, this.damageSources().drown(), 2.0F); } } else if (this.getAirSupply() < this.getMaxAirSupply()) { this.setAirSupply(this.increaseAirSupply(this.getAirSupply())); } if (this.isPassenger() && this.getVehicle() != null && this.getVehicle().dismountsUnderwater()) { this.stopRiding(); } } else if (this.getAirSupply() < this.getMaxAirSupply()) { this.setAirSupply(this.increaseAirSupply(this.getAirSupply())); } BlockPos blockpos = this.blockPosition(); if (!Objects.equal(this.lastPos, blockpos)) { this.lastPos = blockpos; this.onChangedBlock(serverlevel1, blockpos); } } if (this.hurtTime > 0) { this.hurtTime--; } if (this.invulnerableTime > 0 && !(this instanceof ServerPlayer)) { this.invulnerableTime--; } if (this.isDeadOrDying() && this.level().shouldTickDeath(this)) { this.tickDeath(); } if (this.lastHurtByPlayerMemoryTime > 0) { this.lastHurtByPlayerMemoryTime--; } else { this.lastHurtByPlayer = null; } if (this.lastHurtMob != null && !this.lastHurtMob.isAlive()) { this.lastHurtMob = null; } LivingEntity livingentity = this.getLastHurtByMob(); if (livingentity != null) { if (!livingentity.isAlive()) { this.setLastHurtByMob(null); } else if (this.tickCount - this.lastHurtByMobTimestamp > 100) { this.setLastHurtByMob(null); } } this.tickEffects(); this.yHeadRotO = this.yHeadRot; this.yBodyRotO = this.yBodyRot; this.yRotO = this.getYRot(); this.xRotO = this.getXRot(); profilerfiller.pop(); } @Override protected float getBlockSpeedFactor() { return Mth.lerp((float)this.getAttributeValue(Attributes.MOVEMENT_EFFICIENCY), super.getBlockSpeedFactor(), 1.0F); } public float getLuck() { return 0.0F; } protected void removeFrost() { AttributeInstance attributeinstance = this.getAttribute(Attributes.MOVEMENT_SPEED); if (attributeinstance != null) { if (attributeinstance.getModifier(SPEED_MODIFIER_POWDER_SNOW_ID) != null) { attributeinstance.removeModifier(SPEED_MODIFIER_POWDER_SNOW_ID); } } } protected void tryAddFrost() { if (!this.getBlockStateOnLegacy().isAir()) { int i = this.getTicksFrozen(); if (i > 0) { AttributeInstance attributeinstance = this.getAttribute(Attributes.MOVEMENT_SPEED); if (attributeinstance == null) { return; } float f = -0.05F * this.getPercentFrozen(); attributeinstance.addTransientModifier(new AttributeModifier(SPEED_MODIFIER_POWDER_SNOW_ID, f, AttributeModifier.Operation.ADD_VALUE)); } } } protected void onChangedBlock(ServerLevel p_343619_, BlockPos p_21175_) { EnchantmentHelper.runLocationChangedEffects(p_343619_, this); } public boolean isBaby() { return false; } public float getAgeScale() { return this.isBaby() ? 0.5F : 1.0F; } public final float getScale() { AttributeMap attributemap = this.getAttributes(); return attributemap == null ? 1.0F : this.sanitizeScale((float)attributemap.getValue(Attributes.SCALE)); } protected float sanitizeScale(float p_330116_) { return p_330116_; } public boolean isAffectedByFluids() { return true; } protected void tickDeath() { this.deathTime++; if (this.deathTime >= 20 && !this.level().isClientSide() && !this.isRemoved()) { this.level().broadcastEntityEvent(this, (byte)60); this.remove(Entity.RemovalReason.KILLED); } } public boolean shouldDropExperience() { return !this.isBaby(); } protected boolean shouldDropLoot() { return !this.isBaby(); } protected int decreaseAirSupply(int p_21303_) { AttributeInstance attributeinstance = this.getAttribute(Attributes.OXYGEN_BONUS); double d0; if (attributeinstance != null) { d0 = attributeinstance.getValue(); } else { d0 = 0.0; } return d0 > 0.0 && this.random.nextDouble() >= 1.0 / (d0 + 1.0) ? p_21303_ : p_21303_ - 1; } protected int increaseAirSupply(int p_21307_) { return Math.min(p_21307_ + 4, this.getMaxAirSupply()); } public final int getExperienceReward(ServerLevel p_342563_, @Nullable Entity p_343916_) { return EnchantmentHelper.processMobExperience(p_342563_, p_343916_, this, this.getBaseExperienceReward(p_342563_)); } protected int getBaseExperienceReward(ServerLevel p_361539_) { return 0; } protected boolean isAlwaysExperienceDropper() { return false; } @Nullable public LivingEntity getLastHurtByMob() { return EntityReference.get(this.lastHurtByMob, this.level(), LivingEntity.class); } @Nullable public Player getLastHurtByPlayer() { return EntityReference.get(this.lastHurtByPlayer, this.level(), Player.class); } @Override public LivingEntity getLastAttacker() { return this.getLastHurtByMob(); } public int getLastHurtByMobTimestamp() { return this.lastHurtByMobTimestamp; } public void setLastHurtByPlayer(Player p_395411_, int p_391223_) { this.setLastHurtByPlayer(new EntityReference<>(p_395411_), p_391223_); } public void setLastHurtByPlayer(UUID p_393536_, int p_396369_) { this.setLastHurtByPlayer(new EntityReference<>(p_393536_), p_396369_); } private void setLastHurtByPlayer(EntityReference p_394032_, int p_392614_) { this.lastHurtByPlayer = p_394032_; this.lastHurtByPlayerMemoryTime = p_392614_; } public void setLastHurtByMob(@Nullable LivingEntity p_21039_) { this.lastHurtByMob = p_21039_ != null ? new EntityReference<>(p_21039_) : null; this.lastHurtByMobTimestamp = this.tickCount; } @Nullable public LivingEntity getLastHurtMob() { return this.lastHurtMob; } public int getLastHurtMobTimestamp() { return this.lastHurtMobTimestamp; } public void setLastHurtMob(Entity p_21336_) { if (p_21336_ instanceof LivingEntity) { this.lastHurtMob = (LivingEntity)p_21336_; } else { this.lastHurtMob = null; } this.lastHurtMobTimestamp = this.tickCount; } public int getNoActionTime() { return this.noActionTime; } public void setNoActionTime(int p_21311_) { this.noActionTime = p_21311_; } public boolean shouldDiscardFriction() { return this.discardFriction; } public void setDiscardFriction(boolean p_147245_) { this.discardFriction = p_147245_; } protected boolean doesEmitEquipEvent(EquipmentSlot p_217035_) { return true; } public void onEquipItem(EquipmentSlot p_238393_, ItemStack p_238394_, ItemStack p_238395_) { if (!this.level().isClientSide() && !this.isSpectator()) { if (!ItemStack.isSameItemSameComponents(p_238394_, p_238395_) && !this.firstTick) { Equippable equippable = p_238395_.get(DataComponents.EQUIPPABLE); if (!this.isSilent() && equippable != null && p_238393_ == equippable.slot()) { this.level() .playSeededSound( null, this.getX(), this.getY(), this.getZ(), this.getEquipSound(p_238393_, p_238395_, equippable), this.getSoundSource(), 1.0F, 1.0F, this.random.nextLong() ); } if (this.doesEmitEquipEvent(p_238393_)) { this.gameEvent(equippable != null ? GameEvent.EQUIP : GameEvent.UNEQUIP); } } } } protected Holder getEquipSound(EquipmentSlot p_397900_, ItemStack p_395451_, Equippable p_396028_) { return p_396028_.equipSound(); } @Override public void remove(Entity.RemovalReason p_276115_) { if ((p_276115_ == Entity.RemovalReason.KILLED || p_276115_ == Entity.RemovalReason.DISCARDED) && this.level() instanceof ServerLevel serverlevel) { this.triggerOnDeathMobEffects(serverlevel, p_276115_); } super.remove(p_276115_); this.brain.clearMemories(); } protected void triggerOnDeathMobEffects(ServerLevel p_366893_, Entity.RemovalReason p_344022_) { for (MobEffectInstance mobeffectinstance : this.getActiveEffects()) { mobeffectinstance.onMobRemoved(p_366893_, this, p_344022_); } this.activeEffects.clear(); } @Override public void addAdditionalSaveData(CompoundTag p_21145_) { p_21145_.putFloat("Health", this.getHealth()); p_21145_.putShort("HurtTime", (short)this.hurtTime); p_21145_.putInt("HurtByTimestamp", this.lastHurtByMobTimestamp); p_21145_.putShort("DeathTime", (short)this.deathTime); p_21145_.putFloat("AbsorptionAmount", this.getAbsorptionAmount()); p_21145_.put("attributes", this.getAttributes().save()); RegistryOps registryops = this.registryAccess().createSerializationContext(NbtOps.INSTANCE); if (!this.activeEffects.isEmpty()) { p_21145_.store("active_effects", MobEffectInstance.CODEC.listOf(), registryops, List.copyOf(this.activeEffects.values())); } p_21145_.putBoolean("FallFlying", this.isFallFlying()); this.getSleepingPos().ifPresent(p_390517_ -> p_21145_.store("sleeping_pos", BlockPos.CODEC, p_390517_)); DataResult dataresult = this.brain.serializeStart(NbtOps.INSTANCE); dataresult.resultOrPartial(LOGGER::error).ifPresent(p_21102_ -> p_21145_.put("Brain", p_21102_)); if (this.lastHurtByPlayer != null) { this.lastHurtByPlayer.store(p_21145_, "last_hurt_by_player"); p_21145_.putInt("last_hurt_by_player_memory_time", this.lastHurtByPlayerMemoryTime); } if (this.lastHurtByMob != null) { this.lastHurtByMob.store(p_21145_, "last_hurt_by_mob"); p_21145_.putInt("ticks_since_last_hurt_by_mob", this.tickCount - this.lastHurtByMobTimestamp); } if (!this.equipment.isEmpty()) { p_21145_.store("equipment", EntityEquipment.CODEC, registryops, this.equipment); } } @Nullable public ItemEntity drop(ItemStack p_395943_, boolean p_393118_, boolean p_392158_) { if (p_395943_.isEmpty()) { return null; } else if (this.level().isClientSide) { this.swing(InteractionHand.MAIN_HAND); return null; } else { ItemEntity itementity = this.createItemStackToDrop(p_395943_, p_393118_, p_392158_); if (itementity != null) { this.level().addFreshEntity(itementity); } return itementity; } } @Override public void readAdditionalSaveData(CompoundTag p_21096_) { this.internalSetAbsorptionAmount(p_21096_.getFloatOr("AbsorptionAmount", 0.0F)); if (this.level() != null && !this.level().isClientSide) { p_21096_.getList("attributes").ifPresent(this.getAttributes()::load); } RegistryOps registryops = this.registryAccess().createSerializationContext(NbtOps.INSTANCE); List list = p_21096_.read("active_effects", MobEffectInstance.CODEC.listOf(), registryops).orElse(List.of()); this.activeEffects.clear(); for (MobEffectInstance mobeffectinstance : list) { this.activeEffects.put(mobeffectinstance.getEffect(), mobeffectinstance); } this.setHealth(p_21096_.getFloatOr("Health", this.getMaxHealth())); this.hurtTime = p_21096_.getShortOr("HurtTime", (short)0); this.deathTime = p_21096_.getShortOr("DeathTime", (short)0); this.lastHurtByMobTimestamp = p_21096_.getIntOr("HurtByTimestamp", 0); p_21096_.getString("Team").ifPresent(p_390514_ -> { Scoreboard scoreboard = this.level().getScoreboard(); PlayerTeam playerteam = scoreboard.getPlayerTeam(p_390514_); boolean flag = playerteam != null && scoreboard.addPlayerToTeam(this.getStringUUID(), playerteam); if (!flag) { LOGGER.warn("Unable to add mob to team \"{}\" (that team probably doesn't exist)", p_390514_); } }); this.setSharedFlag(7, p_21096_.getBooleanOr("FallFlying", false)); p_21096_.read("sleeping_pos", BlockPos.CODEC).ifPresentOrElse(p_390515_ -> { this.setSleepingPos(p_390515_); this.entityData.set(DATA_POSE, Pose.SLEEPING); if (!this.firstTick) { this.setPosToBed(p_390515_); } }, this::clearSleepingPos); p_21096_.getCompound("Brain").ifPresent(p_390523_ -> this.brain = this.makeBrain(new Dynamic<>(NbtOps.INSTANCE, p_390523_))); this.lastHurtByPlayer = EntityReference.read(p_21096_, "last_hurt_by_player"); this.lastHurtByPlayerMemoryTime = p_21096_.getIntOr("last_hurt_by_player_memory_time", 0); this.lastHurtByMob = EntityReference.read(p_21096_, "last_hurt_by_mob"); this.lastHurtByMobTimestamp = p_21096_.getIntOr("ticks_since_last_hurt_by_mob", 0) + this.tickCount; this.equipment.setAll(p_21096_.read("equipment", EntityEquipment.CODEC, registryops).orElseGet(EntityEquipment::new)); } protected void tickEffects() { if (this.level() instanceof ServerLevel serverlevel) { Iterator> iterator = this.activeEffects.keySet().iterator(); try { while (iterator.hasNext()) { Holder holder = iterator.next(); MobEffectInstance mobeffectinstance = this.activeEffects.get(holder); if (!mobeffectinstance.tickServer(serverlevel, this, () -> this.onEffectUpdated(mobeffectinstance, true, null))) { iterator.remove(); this.onEffectsRemoved(List.of(mobeffectinstance)); } else if (mobeffectinstance.getDuration() % 600 == 0) { this.onEffectUpdated(mobeffectinstance, false, null); } } } catch (ConcurrentModificationException concurrentmodificationexception) { } if (this.effectsDirty) { this.updateInvisibilityStatus(); this.updateGlowingStatus(); this.effectsDirty = false; } } else { for (MobEffectInstance mobeffectinstance1 : this.activeEffects.values()) { mobeffectinstance1.tickClient(); } List list = this.entityData.get(DATA_EFFECT_PARTICLES); if (!list.isEmpty()) { boolean flag = this.entityData.get(DATA_EFFECT_AMBIENCE_ID); int j = this.isInvisible() ? 15 : 4; int i = flag ? 5 : 1; if (this.random.nextInt(j * i) == 0) { this.level().addParticle(Util.getRandom(list, this.random), this.getRandomX(0.5), this.getRandomY(), this.getRandomZ(0.5), 1.0, 1.0, 1.0); } } } } protected void updateInvisibilityStatus() { if (this.activeEffects.isEmpty()) { this.removeEffectParticles(); this.setInvisible(false); } else { this.setInvisible(this.hasEffect(MobEffects.INVISIBILITY)); this.updateSynchronizedMobEffectParticles(); } } private void updateSynchronizedMobEffectParticles() { List list = this.activeEffects.values().stream().filter(MobEffectInstance::isVisible).map(MobEffectInstance::getParticleOptions).toList(); this.entityData.set(DATA_EFFECT_PARTICLES, list); this.entityData.set(DATA_EFFECT_AMBIENCE_ID, areAllEffectsAmbient(this.activeEffects.values())); } private void updateGlowingStatus() { boolean flag = this.isCurrentlyGlowing(); if (this.getSharedFlag(6) != flag) { this.setSharedFlag(6, flag); } } public double getVisibilityPercent(@Nullable Entity p_20969_) { double d0 = 1.0; if (this.isDiscrete()) { d0 *= 0.8; } if (this.isInvisible()) { float f = this.getArmorCoverPercentage(); if (f < 0.1F) { f = 0.1F; } d0 *= 0.7 * f; } if (p_20969_ != null) { ItemStack itemstack = this.getItemBySlot(EquipmentSlot.HEAD); EntityType entitytype = p_20969_.getType(); if (entitytype == EntityType.SKELETON && itemstack.is(Items.SKELETON_SKULL) || entitytype == EntityType.ZOMBIE && itemstack.is(Items.ZOMBIE_HEAD) || entitytype == EntityType.PIGLIN && itemstack.is(Items.PIGLIN_HEAD) || entitytype == EntityType.PIGLIN_BRUTE && itemstack.is(Items.PIGLIN_HEAD) || entitytype == EntityType.CREEPER && itemstack.is(Items.CREEPER_HEAD)) { d0 *= 0.5; } } return d0; } public boolean canAttack(LivingEntity p_21171_) { return p_21171_ instanceof Player && this.level().getDifficulty() == Difficulty.PEACEFUL ? false : p_21171_.canBeSeenAsEnemy(); } public boolean canBeSeenAsEnemy() { return !this.isInvulnerable() && this.canBeSeenByAnyone(); } public boolean canBeSeenByAnyone() { return !this.isSpectator() && this.isAlive(); } public static boolean areAllEffectsAmbient(Collection p_21180_) { for (MobEffectInstance mobeffectinstance : p_21180_) { if (mobeffectinstance.isVisible() && !mobeffectinstance.isAmbient()) { return false; } } return true; } protected void removeEffectParticles() { this.entityData.set(DATA_EFFECT_PARTICLES, List.of()); } public boolean removeAllEffects() { if (this.level().isClientSide) { return false; } else if (this.activeEffects.isEmpty()) { return false; } else { Map, MobEffectInstance> map = Maps.newHashMap(this.activeEffects); this.activeEffects.clear(); this.onEffectsRemoved(map.values()); return true; } } public Collection getActiveEffects() { return this.activeEffects.values(); } public Map, MobEffectInstance> getActiveEffectsMap() { return this.activeEffects; } public boolean hasEffect(Holder p_329256_) { return this.activeEffects.containsKey(p_329256_); } @Nullable public MobEffectInstance getEffect(Holder p_328338_) { return this.activeEffects.get(p_328338_); } public float getEffectBlendFactor(Holder p_397089_, float p_396175_) { MobEffectInstance mobeffectinstance = this.getEffect(p_397089_); return mobeffectinstance != null ? mobeffectinstance.getBlendFactor(this, p_396175_) : 0.0F; } public final boolean addEffect(MobEffectInstance p_21165_) { return this.addEffect(p_21165_, null); } public boolean addEffect(MobEffectInstance p_147208_, @Nullable Entity p_147209_) { if (!this.canBeAffected(p_147208_)) { return false; } else { MobEffectInstance mobeffectinstance = this.activeEffects.get(p_147208_.getEffect()); boolean flag = false; if (mobeffectinstance == null) { this.activeEffects.put(p_147208_.getEffect(), p_147208_); this.onEffectAdded(p_147208_, p_147209_); flag = true; p_147208_.onEffectAdded(this); } else if (mobeffectinstance.update(p_147208_)) { this.onEffectUpdated(mobeffectinstance, true, p_147209_); flag = true; } p_147208_.onEffectStarted(this); return flag; } } public boolean canBeAffected(MobEffectInstance p_21197_) { if (this.getType().is(EntityTypeTags.IMMUNE_TO_INFESTED)) { return !p_21197_.is(MobEffects.INFESTED); } else if (this.getType().is(EntityTypeTags.IMMUNE_TO_OOZING)) { return !p_21197_.is(MobEffects.OOZING); } else { return !this.getType().is(EntityTypeTags.IGNORES_POISON_AND_REGEN) ? true : !p_21197_.is(MobEffects.REGENERATION) && !p_21197_.is(MobEffects.POISON); } } public void forceAddEffect(MobEffectInstance p_147216_, @Nullable Entity p_147217_) { if (this.canBeAffected(p_147216_)) { MobEffectInstance mobeffectinstance = this.activeEffects.put(p_147216_.getEffect(), p_147216_); if (mobeffectinstance == null) { this.onEffectAdded(p_147216_, p_147217_); } else { p_147216_.copyBlendState(mobeffectinstance); this.onEffectUpdated(p_147216_, true, p_147217_); } } } public boolean isInvertedHealAndHarm() { return this.getType().is(EntityTypeTags.INVERTED_HEALING_AND_HARM); } @Nullable public final MobEffectInstance removeEffectNoUpdate(Holder p_329442_) { return this.activeEffects.remove(p_329442_); } public boolean removeEffect(Holder p_335910_) { MobEffectInstance mobeffectinstance = this.removeEffectNoUpdate(p_335910_); if (mobeffectinstance != null) { this.onEffectsRemoved(List.of(mobeffectinstance)); return true; } else { return false; } } protected void onEffectAdded(MobEffectInstance p_147190_, @Nullable Entity p_147191_) { if (!this.level().isClientSide) { this.effectsDirty = true; p_147190_.getEffect().value().addAttributeModifiers(this.getAttributes(), p_147190_.getAmplifier()); this.sendEffectToPassengers(p_147190_); } } public void sendEffectToPassengers(MobEffectInstance p_289695_) { for (Entity entity : this.getPassengers()) { if (entity instanceof ServerPlayer serverplayer) { serverplayer.connection.send(new ClientboundUpdateMobEffectPacket(this.getId(), p_289695_, false)); } } } protected void onEffectUpdated(MobEffectInstance p_147192_, boolean p_147193_, @Nullable Entity p_147194_) { if (!this.level().isClientSide) { this.effectsDirty = true; if (p_147193_) { MobEffect mobeffect = p_147192_.getEffect().value(); mobeffect.removeAttributeModifiers(this.getAttributes()); mobeffect.addAttributeModifiers(this.getAttributes(), p_147192_.getAmplifier()); this.refreshDirtyAttributes(); } this.sendEffectToPassengers(p_147192_); } } protected void onEffectsRemoved(Collection p_364717_) { if (!this.level().isClientSide) { this.effectsDirty = true; for (MobEffectInstance mobeffectinstance : p_364717_) { mobeffectinstance.getEffect().value().removeAttributeModifiers(this.getAttributes()); for (Entity entity : this.getPassengers()) { if (entity instanceof ServerPlayer serverplayer) { serverplayer.connection.send(new ClientboundRemoveMobEffectPacket(this.getId(), mobeffectinstance.getEffect())); } } } this.refreshDirtyAttributes(); } } private void refreshDirtyAttributes() { Set set = this.getAttributes().getAttributesToUpdate(); for (AttributeInstance attributeinstance : set) { this.onAttributeUpdated(attributeinstance.getAttribute()); } set.clear(); } protected void onAttributeUpdated(Holder p_328945_) { if (p_328945_.is(Attributes.MAX_HEALTH)) { float f = this.getMaxHealth(); if (this.getHealth() > f) { this.setHealth(f); } } else if (p_328945_.is(Attributes.MAX_ABSORPTION)) { float f1 = this.getMaxAbsorption(); if (this.getAbsorptionAmount() > f1) { this.setAbsorptionAmount(f1); } } else if (p_328945_.is(Attributes.SCALE)) { this.refreshDimensions(); } } public void heal(float p_21116_) { float f = this.getHealth(); if (f > 0.0F) { this.setHealth(f + p_21116_); } } public float getHealth() { return this.entityData.get(DATA_HEALTH_ID); } public void setHealth(float p_21154_) { this.entityData.set(DATA_HEALTH_ID, Mth.clamp(p_21154_, 0.0F, this.getMaxHealth())); } public boolean isDeadOrDying() { return this.getHealth() <= 0.0F; } @Override public boolean hurtServer(ServerLevel p_361743_, DamageSource p_361865_, float p_365677_) { if (this.isInvulnerableTo(p_361743_, p_361865_)) { return false; } else if (this.isDeadOrDying()) { return false; } else if (p_361865_.is(DamageTypeTags.IS_FIRE) && this.hasEffect(MobEffects.FIRE_RESISTANCE)) { return false; } else { if (this.isSleeping()) { this.stopSleeping(); } this.noActionTime = 0; if (p_365677_ < 0.0F) { p_365677_ = 0.0F; } float f = this.applyItemBlocking(p_361743_, p_361865_, p_365677_); p_365677_ -= f; boolean flag = f > 0.0F; if (p_361865_.is(DamageTypeTags.IS_FREEZING) && this.getType().is(EntityTypeTags.FREEZE_HURTS_EXTRA_TYPES)) { p_365677_ *= 5.0F; } if (p_361865_.is(DamageTypeTags.DAMAGES_HELMET) && !this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { this.hurtHelmet(p_361865_, p_365677_); p_365677_ *= 0.75F; } if (Float.isNaN(p_365677_) || Float.isInfinite(p_365677_)) { p_365677_ = Float.MAX_VALUE; } boolean flag1 = true; if (this.invulnerableTime > 10.0F && !p_361865_.is(DamageTypeTags.BYPASSES_COOLDOWN)) { if (p_365677_ <= this.lastHurt) { return false; } this.actuallyHurt(p_361743_, p_361865_, p_365677_ - this.lastHurt); this.lastHurt = p_365677_; flag1 = false; } else { this.lastHurt = p_365677_; this.invulnerableTime = 20; this.actuallyHurt(p_361743_, p_361865_, p_365677_); this.hurtDuration = 10; this.hurtTime = this.hurtDuration; } this.resolveMobResponsibleForDamage(p_361865_); this.resolvePlayerResponsibleForDamage(p_361865_); if (flag1) { BlocksAttacks blocksattacks = this.getUseItem().get(DataComponents.BLOCKS_ATTACKS); if (flag && blocksattacks != null) { blocksattacks.onBlocked(p_361743_, this); } else { p_361743_.broadcastDamageEvent(this, p_361865_); } if (!p_361865_.is(DamageTypeTags.NO_IMPACT) && (!flag || p_365677_ > 0.0F)) { this.markHurt(); } if (!p_361865_.is(DamageTypeTags.NO_KNOCKBACK)) { double d0 = 0.0; double d1 = 0.0; if (p_361865_.getDirectEntity() instanceof Projectile projectile) { DoubleDoubleImmutablePair doubledoubleimmutablepair = projectile.calculateHorizontalHurtKnockbackDirection(this, p_361865_); d0 = -doubledoubleimmutablepair.leftDouble(); d1 = -doubledoubleimmutablepair.rightDouble(); } else if (p_361865_.getSourcePosition() != null) { d0 = p_361865_.getSourcePosition().x() - this.getX(); d1 = p_361865_.getSourcePosition().z() - this.getZ(); } this.knockback(0.4F, d0, d1); if (!flag) { this.indicateDamage(d0, d1); } } } if (this.isDeadOrDying()) { if (!this.checkTotemDeathProtection(p_361865_)) { if (flag1) { this.makeSound(this.getDeathSound()); this.playSecondaryHurtSound(p_361865_); } this.die(p_361865_); } } else if (flag1) { this.playHurtSound(p_361865_); this.playSecondaryHurtSound(p_361865_); } boolean flag2 = !flag || p_365677_ > 0.0F; if (flag2) { this.lastDamageSource = p_361865_; this.lastDamageStamp = this.level().getGameTime(); for (MobEffectInstance mobeffectinstance : this.getActiveEffects()) { mobeffectinstance.onMobHurt(p_361743_, this, p_361865_, p_365677_); } } if (this instanceof ServerPlayer serverplayer) { CriteriaTriggers.ENTITY_HURT_PLAYER.trigger(serverplayer, p_361865_, p_365677_, p_365677_, flag); if (f > 0.0F && f < 3.4028235E37F) { serverplayer.awardStat(Stats.DAMAGE_BLOCKED_BY_SHIELD, Math.round(f * 10.0F)); } } if (p_361865_.getEntity() instanceof ServerPlayer serverplayer1) { CriteriaTriggers.PLAYER_HURT_ENTITY.trigger(serverplayer1, this, p_361865_, p_365677_, p_365677_, flag); } return flag2; } } public float applyItemBlocking(ServerLevel p_396198_, DamageSource p_392511_, float p_394545_) { if (p_394545_ <= 0.0F) { return 0.0F; } else { ItemStack itemstack = this.getItemBlockingWith(); if (itemstack == null) { return 0.0F; } else { BlocksAttacks blocksattacks = itemstack.get(DataComponents.BLOCKS_ATTACKS); if (blocksattacks != null && !blocksattacks.bypassedBy().map(p_392511_::is).orElse(false)) { if (p_392511_.getDirectEntity() instanceof AbstractArrow abstractarrow && abstractarrow.getPierceLevel() > 0) { return 0.0F; } else { Vec3 vec3 = p_392511_.getSourcePosition(); double d0; if (vec3 != null) { Vec3 vec31 = this.calculateViewVector(0.0F, this.getYHeadRot()); Vec3 vec32 = vec3.subtract(this.position()); vec32 = new Vec3(vec32.x, 0.0, vec32.z).normalize(); d0 = Math.acos(vec32.dot(vec31)); } else { d0 = (float) Math.PI; } float f = blocksattacks.resolveBlockedDamage(p_392511_, p_394545_, d0); blocksattacks.hurtBlockingItem(this.level(), itemstack, this, this.getUsedItemHand(), f); if (!p_392511_.is(DamageTypeTags.IS_PROJECTILE) && p_392511_.getDirectEntity() instanceof LivingEntity livingentity) { this.blockUsingItem(p_396198_, livingentity); } return f; } } else { return 0.0F; } } } } private void playSecondaryHurtSound(DamageSource p_394905_) { if (p_394905_.is(DamageTypes.THORNS)) { SoundSource soundsource = this instanceof Player ? SoundSource.PLAYERS : SoundSource.HOSTILE; this.level().playSound(null, this.position().x, this.position().y, this.position().z, SoundEvents.THORNS_HIT, soundsource); } } protected void resolveMobResponsibleForDamage(DamageSource p_377003_) { if (p_377003_.getEntity() instanceof LivingEntity livingentity && !p_377003_.is(DamageTypeTags.NO_ANGER) && (!p_377003_.is(DamageTypes.WIND_CHARGE) || !this.getType().is(EntityTypeTags.NO_ANGER_FROM_WIND_CHARGE))) { this.setLastHurtByMob(livingentity); } } @Nullable protected Player resolvePlayerResponsibleForDamage(DamageSource p_378258_) { Entity entity = p_378258_.getEntity(); if (entity instanceof Player player) { this.setLastHurtByPlayer(player, 100); } else if (entity instanceof Wolf wolf && wolf.isTame()) { if (wolf.getOwnerReference() != null) { this.setLastHurtByPlayer(wolf.getOwnerReference().getUUID(), 100); } else { this.lastHurtByPlayer = null; this.lastHurtByPlayerMemoryTime = 0; } } return EntityReference.get(this.lastHurtByPlayer, this.level(), Player.class); } protected void blockUsingItem(ServerLevel p_395319_, LivingEntity p_392570_) { p_392570_.blockedByItem(this); } protected void blockedByItem(LivingEntity p_21246_) { p_21246_.knockback(0.5, p_21246_.getX() - this.getX(), p_21246_.getZ() - this.getZ()); } private boolean checkTotemDeathProtection(DamageSource p_21263_) { if (p_21263_.is(DamageTypeTags.BYPASSES_INVULNERABILITY)) { return false; } else { ItemStack itemstack = null; DeathProtection deathprotection = null; for (InteractionHand interactionhand : InteractionHand.values()) { ItemStack itemstack1 = this.getItemInHand(interactionhand); deathprotection = itemstack1.get(DataComponents.DEATH_PROTECTION); if (deathprotection != null) { itemstack = itemstack1.copy(); itemstack1.shrink(1); break; } } if (itemstack != null) { if (this instanceof ServerPlayer serverplayer) { serverplayer.awardStat(Stats.ITEM_USED.get(itemstack.getItem())); CriteriaTriggers.USED_TOTEM.trigger(serverplayer, itemstack); this.gameEvent(GameEvent.ITEM_INTERACT_FINISH); } this.setHealth(1.0F); deathprotection.applyEffects(itemstack, this); this.level().broadcastEntityEvent(this, (byte)35); } return deathprotection != null; } } @Nullable public DamageSource getLastDamageSource() { if (this.level().getGameTime() - this.lastDamageStamp > 40L) { this.lastDamageSource = null; } return this.lastDamageSource; } protected void playHurtSound(DamageSource p_21160_) { this.makeSound(this.getHurtSound(p_21160_)); } public void makeSound(@Nullable SoundEvent p_334191_) { if (p_334191_ != null) { this.playSound(p_334191_, this.getSoundVolume(), this.getVoicePitch()); } } private void breakItem(ItemStack p_21279_) { if (!p_21279_.isEmpty()) { Holder holder = p_21279_.get(DataComponents.BREAK_SOUND); if (holder != null && !this.isSilent()) { this.level() .playLocalSound( this.getX(), this.getY(), this.getZ(), holder.value(), this.getSoundSource(), 0.8F, 0.8F + this.level().random.nextFloat() * 0.4F, false ); } this.spawnItemParticles(p_21279_, 5); } } public void die(DamageSource p_21014_) { if (!this.isRemoved() && !this.dead) { Entity entity = p_21014_.getEntity(); LivingEntity livingentity = this.getKillCredit(); if (livingentity != null) { livingentity.awardKillScore(this, p_21014_); } if (this.isSleeping()) { this.stopSleeping(); } if (!this.level().isClientSide && this.hasCustomName()) { LOGGER.info("Named entity {} died: {}", this, this.getCombatTracker().getDeathMessage().getString()); } this.dead = true; this.getCombatTracker().recheckStatus(); if (this.level() instanceof ServerLevel serverlevel) { if (entity == null || entity.killedEntity(serverlevel, this)) { this.gameEvent(GameEvent.ENTITY_DIE); this.dropAllDeathLoot(serverlevel, p_21014_); this.createWitherRose(livingentity); } this.level().broadcastEntityEvent(this, (byte)3); } this.setPose(Pose.DYING); } } protected void createWitherRose(@Nullable LivingEntity p_21269_) { if (this.level() instanceof ServerLevel serverlevel) { boolean flag = false; if (p_21269_ instanceof WitherBoss) { if (serverlevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { BlockPos blockpos = this.blockPosition(); BlockState blockstate = Blocks.WITHER_ROSE.defaultBlockState(); if (this.level().getBlockState(blockpos).isAir() && blockstate.canSurvive(this.level(), blockpos)) { this.level().setBlock(blockpos, blockstate, 3); flag = true; } } if (!flag) { ItemEntity itementity = new ItemEntity(this.level(), this.getX(), this.getY(), this.getZ(), new ItemStack(Items.WITHER_ROSE)); this.level().addFreshEntity(itementity); } } } } protected void dropAllDeathLoot(ServerLevel p_342160_, DamageSource p_21192_) { boolean flag = this.lastHurtByPlayerMemoryTime > 0; if (this.shouldDropLoot() && p_342160_.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { this.dropFromLootTable(p_342160_, p_21192_, flag); this.dropCustomDeathLoot(p_342160_, p_21192_, flag); } this.dropEquipment(p_342160_); this.dropExperience(p_342160_, p_21192_.getEntity()); } protected void dropEquipment(ServerLevel p_365823_) { } protected void dropExperience(ServerLevel p_370040_, @Nullable Entity p_342525_) { if (!this.wasExperienceConsumed() && (this.isAlwaysExperienceDropper() || this.lastHurtByPlayerMemoryTime > 0 && this.shouldDropExperience() && p_370040_.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT))) { ExperienceOrb.award(p_370040_, this.position(), this.getExperienceReward(p_370040_, p_342525_)); } } protected void dropCustomDeathLoot(ServerLevel p_344205_, DamageSource p_21018_, boolean p_21020_) { } public long getLootTableSeed() { return 0L; } protected float getKnockback(Entity p_344037_, DamageSource p_343881_) { float f = (float)this.getAttributeValue(Attributes.ATTACK_KNOCKBACK); return this.level() instanceof ServerLevel serverlevel ? EnchantmentHelper.modifyKnockback(serverlevel, this.getWeaponItem(), p_344037_, p_343881_, f) : f; } protected void dropFromLootTable(ServerLevel p_365510_, DamageSource p_364726_, boolean p_367117_) { Optional> optional = this.getLootTable(); if (!optional.isEmpty()) { LootTable loottable = p_365510_.getServer().reloadableRegistries().getLootTable(optional.get()); LootParams.Builder lootparams$builder = new LootParams.Builder(p_365510_) .withParameter(LootContextParams.THIS_ENTITY, this) .withParameter(LootContextParams.ORIGIN, this.position()) .withParameter(LootContextParams.DAMAGE_SOURCE, p_364726_) .withOptionalParameter(LootContextParams.ATTACKING_ENTITY, p_364726_.getEntity()) .withOptionalParameter(LootContextParams.DIRECT_ATTACKING_ENTITY, p_364726_.getDirectEntity()); Player player = this.getLastHurtByPlayer(); if (p_367117_ && player != null) { lootparams$builder = lootparams$builder.withParameter(LootContextParams.LAST_DAMAGE_PLAYER, player).withLuck(player.getLuck()); } LootParams lootparams = lootparams$builder.create(LootContextParamSets.ENTITY); loottable.getRandomItems(lootparams, this.getLootTableSeed(), p_358880_ -> this.spawnAtLocation(p_365510_, p_358880_)); } } public boolean dropFromGiftLootTable(ServerLevel p_363120_, ResourceKey p_363326_, BiConsumer p_368812_) { return this.dropFromLootTable( p_363120_, p_363326_, p_374930_ -> p_374930_.withParameter(LootContextParams.ORIGIN, this.position()) .withParameter(LootContextParams.THIS_ENTITY, this) .create(LootContextParamSets.GIFT), p_368812_ ); } protected void dropFromShearingLootTable(ServerLevel p_361428_, ResourceKey p_365429_, ItemStack p_361064_, BiConsumer p_369621_) { this.dropFromLootTable( p_361428_, p_365429_, p_374933_ -> p_374933_.withParameter(LootContextParams.ORIGIN, this.position()) .withParameter(LootContextParams.THIS_ENTITY, this) .withParameter(LootContextParams.TOOL, p_361064_) .create(LootContextParamSets.SHEARING), p_369621_ ); } protected boolean dropFromLootTable( ServerLevel p_363272_, ResourceKey p_363593_, Function p_362309_, BiConsumer p_366393_ ) { LootTable loottable = p_363272_.getServer().reloadableRegistries().getLootTable(p_363593_); LootParams lootparams = p_362309_.apply(new LootParams.Builder(p_363272_)); List list = loottable.getRandomItems(lootparams); if (!list.isEmpty()) { list.forEach(p_358893_ -> p_366393_.accept(p_363272_, p_358893_)); return true; } else { return false; } } public void knockback(double p_147241_, double p_147242_, double p_147243_) { p_147241_ *= 1.0 - this.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE); if (!(p_147241_ <= 0.0)) { this.hasImpulse = true; Vec3 vec3 = this.getDeltaMovement(); while (p_147242_ * p_147242_ + p_147243_ * p_147243_ < 1.0E-5F) { p_147242_ = (Math.random() - Math.random()) * 0.01; p_147243_ = (Math.random() - Math.random()) * 0.01; } Vec3 vec31 = new Vec3(p_147242_, 0.0, p_147243_).normalize().scale(p_147241_); this.setDeltaMovement( vec3.x / 2.0 - vec31.x, this.onGround() ? Math.min(0.4, vec3.y / 2.0 + p_147241_) : vec3.y, vec3.z / 2.0 - vec31.z ); } } public void indicateDamage(double p_270514_, double p_270826_) { } @Nullable protected SoundEvent getHurtSound(DamageSource p_21239_) { return SoundEvents.GENERIC_HURT; } @Nullable protected SoundEvent getDeathSound() { return SoundEvents.GENERIC_DEATH; } private SoundEvent getFallDamageSound(int p_21313_) { return p_21313_ > 4 ? this.getFallSounds().big() : this.getFallSounds().small(); } public void skipDropExperience() { this.skipDropExperience = true; } public boolean wasExperienceConsumed() { return this.skipDropExperience; } public float getHurtDir() { return 0.0F; } protected AABB getHitbox() { AABB aabb = this.getBoundingBox(); Entity entity = this.getVehicle(); if (entity != null) { Vec3 vec3 = entity.getPassengerRidingPosition(this); return aabb.setMinY(Math.max(vec3.y, aabb.minY)); } else { return aabb; } } public Map> activeLocationDependentEnchantments(EquipmentSlot p_363512_) { return this.activeLocationDependentEnchantments.computeIfAbsent(p_363512_, p_358895_ -> new Reference2ObjectArrayMap<>()); } public LivingEntity.Fallsounds getFallSounds() { return new LivingEntity.Fallsounds(SoundEvents.GENERIC_SMALL_FALL, SoundEvents.GENERIC_BIG_FALL); } public Optional getLastClimbablePos() { return this.lastClimbablePos; } public boolean onClimbable() { if (this.isSpectator()) { return false; } else { BlockPos blockpos = this.blockPosition(); BlockState blockstate = this.getInBlockState(); if (blockstate.is(BlockTags.CLIMBABLE)) { this.lastClimbablePos = Optional.of(blockpos); return true; } else if (blockstate.getBlock() instanceof TrapDoorBlock && this.trapdoorUsableAsLadder(blockpos, blockstate)) { this.lastClimbablePos = Optional.of(blockpos); return true; } else { return false; } } } private boolean trapdoorUsableAsLadder(BlockPos p_21177_, BlockState p_21178_) { if (!p_21178_.getValue(TrapDoorBlock.OPEN)) { return false; } else { BlockState blockstate = this.level().getBlockState(p_21177_.below()); return blockstate.is(Blocks.LADDER) && blockstate.getValue(LadderBlock.FACING) == p_21178_.getValue(TrapDoorBlock.FACING); } } @Override public boolean isAlive() { return !this.isRemoved() && this.getHealth() > 0.0F; } public boolean isLookingAtMe(LivingEntity p_365362_, double p_366130_, boolean p_364554_, boolean p_368791_, double... p_377772_) { Vec3 vec3 = p_365362_.getViewVector(1.0F).normalize(); for (double d0 : p_377772_) { Vec3 vec31 = new Vec3(this.getX() - p_365362_.getX(), d0 - p_365362_.getEyeY(), this.getZ() - p_365362_.getZ()); double d1 = vec31.length(); vec31 = vec31.normalize(); double d2 = vec3.dot(vec31); if (d2 > 1.0 - p_366130_ / (p_364554_ ? d1 : 1.0) && p_365362_.hasLineOfSight(this, p_368791_ ? ClipContext.Block.VISUAL : ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, d0)) { return true; } } return false; } @Override public int getMaxFallDistance() { return this.getComfortableFallDistance(0.0F); } protected final int getComfortableFallDistance(float p_327795_) { return Mth.floor(p_327795_ + 3.0F); } @Override public boolean causeFallDamage(double p_393354_, float p_147187_, DamageSource p_147189_) { boolean flag = super.causeFallDamage(p_393354_, p_147187_, p_147189_); int i = this.calculateFallDamage(p_393354_, p_147187_); if (i > 0) { this.playSound(this.getFallDamageSound(i), 1.0F, 1.0F); this.playBlockFallSound(); this.hurt(p_147189_, i); return true; } else { return flag; } } protected int calculateFallDamage(double p_393496_, float p_21237_) { if (this.getType().is(EntityTypeTags.FALL_DAMAGE_IMMUNE)) { return 0; } else { double d0 = this.calculateFallPower(p_393496_); return Mth.floor(d0 * p_21237_ * this.getAttributeValue(Attributes.FALL_DAMAGE_MULTIPLIER)); } } private double calculateFallPower(double p_393609_) { return p_393609_ + 1.0E-6 - this.getAttributeValue(Attributes.SAFE_FALL_DISTANCE); } protected void playBlockFallSound() { if (!this.isSilent()) { int i = Mth.floor(this.getX()); int j = Mth.floor(this.getY() - 0.2F); int k = Mth.floor(this.getZ()); BlockState blockstate = this.level().getBlockState(new BlockPos(i, j, k)); if (!blockstate.isAir()) { SoundType soundtype = blockstate.getSoundType(); this.playSound(soundtype.getFallSound(), soundtype.getVolume() * 0.5F, soundtype.getPitch() * 0.75F); } } } @Override public void animateHurt(float p_265265_) { this.hurtDuration = 10; this.hurtTime = this.hurtDuration; } public int getArmorValue() { return Mth.floor(this.getAttributeValue(Attributes.ARMOR)); } protected void hurtArmor(DamageSource p_21122_, float p_21123_) { } protected void hurtHelmet(DamageSource p_147213_, float p_147214_) { } protected void doHurtEquipment(DamageSource p_330939_, float p_333962_, EquipmentSlot... p_335230_) { if (!(p_333962_ <= 0.0F)) { int i = (int)Math.max(1.0F, p_333962_ / 4.0F); for (EquipmentSlot equipmentslot : p_335230_) { ItemStack itemstack = this.getItemBySlot(equipmentslot); Equippable equippable = itemstack.get(DataComponents.EQUIPPABLE); if (equippable != null && equippable.damageOnHurt() && itemstack.isDamageableItem() && itemstack.canBeHurtBy(p_330939_)) { itemstack.hurtAndBreak(i, this, equipmentslot); } } } } protected float getDamageAfterArmorAbsorb(DamageSource p_21162_, float p_21163_) { if (!p_21162_.is(DamageTypeTags.BYPASSES_ARMOR)) { this.hurtArmor(p_21162_, p_21163_); p_21163_ = CombatRules.getDamageAfterAbsorb(this, p_21163_, p_21162_, this.getArmorValue(), (float)this.getAttributeValue(Attributes.ARMOR_TOUGHNESS)); } return p_21163_; } protected float getDamageAfterMagicAbsorb(DamageSource p_21193_, float p_21194_) { if (p_21193_.is(DamageTypeTags.BYPASSES_EFFECTS)) { return p_21194_; } else { if (this.hasEffect(MobEffects.RESISTANCE) && !p_21193_.is(DamageTypeTags.BYPASSES_RESISTANCE)) { int i = (this.getEffect(MobEffects.RESISTANCE).getAmplifier() + 1) * 5; int j = 25 - i; float f = p_21194_ * j; float f1 = p_21194_; p_21194_ = Math.max(f / 25.0F, 0.0F); float f2 = f1 - p_21194_; if (f2 > 0.0F && f2 < 3.4028235E37F) { if (this instanceof ServerPlayer) { ((ServerPlayer)this).awardStat(Stats.DAMAGE_RESISTED, Math.round(f2 * 10.0F)); } else if (p_21193_.getEntity() instanceof ServerPlayer) { ((ServerPlayer)p_21193_.getEntity()).awardStat(Stats.DAMAGE_DEALT_RESISTED, Math.round(f2 * 10.0F)); } } } if (p_21194_ <= 0.0F) { return 0.0F; } else if (p_21193_.is(DamageTypeTags.BYPASSES_ENCHANTMENTS)) { return p_21194_; } else { float f3; if (this.level() instanceof ServerLevel serverlevel) { f3 = EnchantmentHelper.getDamageProtection(serverlevel, this, p_21193_); } else { f3 = 0.0F; } if (f3 > 0.0F) { p_21194_ = CombatRules.getDamageAfterMagicAbsorb(p_21194_, f3); } return p_21194_; } } } protected void actuallyHurt(ServerLevel p_365124_, DamageSource p_21240_, float p_21241_) { if (!this.isInvulnerableTo(p_365124_, p_21240_)) { p_21241_ = this.getDamageAfterArmorAbsorb(p_21240_, p_21241_); p_21241_ = this.getDamageAfterMagicAbsorb(p_21240_, p_21241_); float f1 = Math.max(p_21241_ - this.getAbsorptionAmount(), 0.0F); this.setAbsorptionAmount(this.getAbsorptionAmount() - (p_21241_ - f1)); float f = p_21241_ - f1; if (f > 0.0F && f < 3.4028235E37F && p_21240_.getEntity() instanceof ServerPlayer serverplayer) { serverplayer.awardStat(Stats.DAMAGE_DEALT_ABSORBED, Math.round(f * 10.0F)); } if (f1 != 0.0F) { this.getCombatTracker().recordDamage(p_21240_, f1); this.setHealth(this.getHealth() - f1); this.setAbsorptionAmount(this.getAbsorptionAmount() - f1); this.gameEvent(GameEvent.ENTITY_DAMAGE); } } } public CombatTracker getCombatTracker() { return this.combatTracker; } @Nullable public LivingEntity getKillCredit() { if (this.lastHurtByPlayer != null) { return this.lastHurtByPlayer.getEntity(this.level(), Player.class); } else { return this.lastHurtByMob != null ? this.lastHurtByMob.getEntity(this.level(), LivingEntity.class) : null; } } public final float getMaxHealth() { return (float)this.getAttributeValue(Attributes.MAX_HEALTH); } public final float getMaxAbsorption() { return (float)this.getAttributeValue(Attributes.MAX_ABSORPTION); } public final int getArrowCount() { return this.entityData.get(DATA_ARROW_COUNT_ID); } public final void setArrowCount(int p_21318_) { this.entityData.set(DATA_ARROW_COUNT_ID, p_21318_); } public final int getStingerCount() { return this.entityData.get(DATA_STINGER_COUNT_ID); } public final void setStingerCount(int p_21322_) { this.entityData.set(DATA_STINGER_COUNT_ID, p_21322_); } private int getCurrentSwingDuration() { if (MobEffectUtil.hasDigSpeed(this)) { return 6 - (1 + MobEffectUtil.getDigSpeedAmplification(this)); } else { return this.hasEffect(MobEffects.MINING_FATIGUE) ? 6 + (1 + this.getEffect(MobEffects.MINING_FATIGUE).getAmplifier()) * 2 : 6; } } public void swing(InteractionHand p_21007_) { this.swing(p_21007_, false); } public void swing(InteractionHand p_21012_, boolean p_21013_) { if (!this.swinging || this.swingTime >= this.getCurrentSwingDuration() / 2 || this.swingTime < 0) { this.swingTime = -1; this.swinging = true; this.swingingArm = p_21012_; if (this.level() instanceof ServerLevel) { ClientboundAnimatePacket clientboundanimatepacket = new ClientboundAnimatePacket(this, p_21012_ == InteractionHand.MAIN_HAND ? 0 : 3); ServerChunkCache serverchunkcache = ((ServerLevel)this.level()).getChunkSource(); if (p_21013_) { serverchunkcache.broadcastAndSend(this, clientboundanimatepacket); } else { serverchunkcache.broadcast(this, clientboundanimatepacket); } } } } @Override public void handleDamageEvent(DamageSource p_270229_) { this.walkAnimation.setSpeed(1.5F); this.invulnerableTime = 20; this.hurtDuration = 10; this.hurtTime = this.hurtDuration; SoundEvent soundevent = this.getHurtSound(p_270229_); if (soundevent != null) { this.playSound(soundevent, this.getSoundVolume(), (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F); } this.lastDamageSource = p_270229_; this.lastDamageStamp = this.level().getGameTime(); } @Override public void handleEntityEvent(byte p_20975_) { switch (p_20975_) { case 3: SoundEvent soundevent = this.getDeathSound(); if (soundevent != null) { this.playSound(soundevent, this.getSoundVolume(), (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F); } if (!(this instanceof Player)) { this.setHealth(0.0F); this.die(this.damageSources().generic()); } break; case 46: int i = 128; for (int j = 0; j < 128; j++) { double d0 = j / 127.0; float f = (this.random.nextFloat() - 0.5F) * 0.2F; float f1 = (this.random.nextFloat() - 0.5F) * 0.2F; float f2 = (this.random.nextFloat() - 0.5F) * 0.2F; double d1 = Mth.lerp(d0, this.xo, this.getX()) + (this.random.nextDouble() - 0.5) * this.getBbWidth() * 2.0; double d2 = Mth.lerp(d0, this.yo, this.getY()) + this.random.nextDouble() * this.getBbHeight(); double d3 = Mth.lerp(d0, this.zo, this.getZ()) + (this.random.nextDouble() - 0.5) * this.getBbWidth() * 2.0; this.level().addParticle(ParticleTypes.PORTAL, d1, d2, d3, f, f1, f2); } break; case 47: this.breakItem(this.getItemBySlot(EquipmentSlot.MAINHAND)); break; case 48: this.breakItem(this.getItemBySlot(EquipmentSlot.OFFHAND)); break; case 49: this.breakItem(this.getItemBySlot(EquipmentSlot.HEAD)); break; case 50: this.breakItem(this.getItemBySlot(EquipmentSlot.CHEST)); break; case 51: this.breakItem(this.getItemBySlot(EquipmentSlot.LEGS)); break; case 52: this.breakItem(this.getItemBySlot(EquipmentSlot.FEET)); break; case 54: HoneyBlock.showJumpParticles(this); break; case 55: this.swapHandItems(); break; case 60: this.makePoofParticles(); break; case 65: this.breakItem(this.getItemBySlot(EquipmentSlot.BODY)); break; case 67: this.makeDrownParticles(); break; case 68: this.breakItem(this.getItemBySlot(EquipmentSlot.SADDLE)); break; default: super.handleEntityEvent(p_20975_); } } public void makePoofParticles() { for (int i = 0; i < 20; i++) { double d0 = this.random.nextGaussian() * 0.02; double d1 = this.random.nextGaussian() * 0.02; double d2 = this.random.nextGaussian() * 0.02; double d3 = 10.0; this.level() .addParticle(ParticleTypes.POOF, this.getRandomX(1.0) - d0 * 10.0, this.getRandomY() - d1 * 10.0, this.getRandomZ(1.0) - d2 * 10.0, d0, d1, d2); } } private void makeDrownParticles() { Vec3 vec3 = this.getDeltaMovement(); for (int i = 0; i < 8; i++) { double d0 = this.random.triangle(0.0, 1.0); double d1 = this.random.triangle(0.0, 1.0); double d2 = this.random.triangle(0.0, 1.0); this.level() .addParticle(ParticleTypes.BUBBLE, this.getX() + d0, this.getY() + d1, this.getZ() + d2, vec3.x, vec3.y, vec3.z); } } private void swapHandItems() { ItemStack itemstack = this.getItemBySlot(EquipmentSlot.OFFHAND); this.setItemSlot(EquipmentSlot.OFFHAND, this.getItemBySlot(EquipmentSlot.MAINHAND)); this.setItemSlot(EquipmentSlot.MAINHAND, itemstack); } @Override protected void onBelowWorld() { this.hurt(this.damageSources().fellOutOfWorld(), 4.0F); } protected void updateSwingTime() { int i = this.getCurrentSwingDuration(); if (this.swinging) { this.swingTime++; if (this.swingTime >= i) { this.swingTime = 0; this.swinging = false; } } else { this.swingTime = 0; } this.attackAnim = (float)this.swingTime / i; } @Nullable public AttributeInstance getAttribute(Holder p_332356_) { return this.getAttributes().getInstance(p_332356_); } public double getAttributeValue(Holder p_251296_) { return this.getAttributes().getValue(p_251296_); } public double getAttributeBaseValue(Holder p_248605_) { return this.getAttributes().getBaseValue(p_248605_); } public AttributeMap getAttributes() { return this.attributes; } public ItemStack getMainHandItem() { return this.getItemBySlot(EquipmentSlot.MAINHAND); } public ItemStack getOffhandItem() { return this.getItemBySlot(EquipmentSlot.OFFHAND); } public ItemStack getItemHeldByArm(HumanoidArm p_365937_) { return this.getMainArm() == p_365937_ ? this.getMainHandItem() : this.getOffhandItem(); } @Nonnull @Override public ItemStack getWeaponItem() { return this.getMainHandItem(); } public boolean isHolding(Item p_21056_) { return this.isHolding(p_147200_ -> p_147200_.is(p_21056_)); } public boolean isHolding(Predicate p_21094_) { return p_21094_.test(this.getMainHandItem()) || p_21094_.test(this.getOffhandItem()); } public ItemStack getItemInHand(InteractionHand p_21121_) { if (p_21121_ == InteractionHand.MAIN_HAND) { return this.getItemBySlot(EquipmentSlot.MAINHAND); } else if (p_21121_ == InteractionHand.OFF_HAND) { return this.getItemBySlot(EquipmentSlot.OFFHAND); } else { throw new IllegalArgumentException("Invalid hand " + p_21121_); } } public void setItemInHand(InteractionHand p_21009_, ItemStack p_21010_) { if (p_21009_ == InteractionHand.MAIN_HAND) { this.setItemSlot(EquipmentSlot.MAINHAND, p_21010_); } else { if (p_21009_ != InteractionHand.OFF_HAND) { throw new IllegalArgumentException("Invalid hand " + p_21009_); } this.setItemSlot(EquipmentSlot.OFFHAND, p_21010_); } } public boolean hasItemInSlot(EquipmentSlot p_21034_) { return !this.getItemBySlot(p_21034_).isEmpty(); } public boolean canUseSlot(EquipmentSlot p_328587_) { return true; } public ItemStack getItemBySlot(EquipmentSlot p_21127_) { return this.equipment.get(p_21127_); } public void setItemSlot(EquipmentSlot p_21036_, ItemStack p_21037_) { this.onEquipItem(p_21036_, this.equipment.set(p_21036_, p_21037_), p_21037_); } public float getArmorCoverPercentage() { int i = 0; int j = 0; for (EquipmentSlot equipmentslot : EquipmentSlotGroup.ARMOR) { if (equipmentslot.getType() == EquipmentSlot.Type.HUMANOID_ARMOR) { ItemStack itemstack = this.getItemBySlot(equipmentslot); if (!itemstack.isEmpty()) { j++; } i++; } } return i > 0 ? (float)j / i : 0.0F; } @Override public void setSprinting(boolean p_21284_) { super.setSprinting(p_21284_); AttributeInstance attributeinstance = this.getAttribute(Attributes.MOVEMENT_SPEED); attributeinstance.removeModifier(SPEED_MODIFIER_SPRINTING.id()); if (p_21284_) { attributeinstance.addTransientModifier(SPEED_MODIFIER_SPRINTING); } } protected float getSoundVolume() { return 1.0F; } public float getVoicePitch() { return this.isBaby() ? (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.5F : (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F; } protected boolean isImmobile() { return this.isDeadOrDying(); } @Override public void push(Entity p_21294_) { if (!this.isSleeping()) { super.push(p_21294_); } } private void dismountVehicle(Entity p_21029_) { Vec3 vec3; if (this.isRemoved()) { vec3 = this.position(); } else if (!p_21029_.isRemoved() && !this.level().getBlockState(p_21029_.blockPosition()).is(BlockTags.PORTALS)) { vec3 = p_21029_.getDismountLocationForPassenger(this); } else { double d0 = Math.max(this.getY(), p_21029_.getY()); vec3 = new Vec3(this.getX(), d0, this.getZ()); boolean flag = this.getBbWidth() <= 4.0F && this.getBbHeight() <= 4.0F; if (flag) { double d1 = this.getBbHeight() / 2.0; Vec3 vec31 = vec3.add(0.0, d1, 0.0); VoxelShape voxelshape = Shapes.create(AABB.ofSize(vec31, this.getBbWidth(), this.getBbHeight(), this.getBbWidth())); vec3 = this.level() .findFreePosition(this, voxelshape, vec31, this.getBbWidth(), this.getBbHeight(), this.getBbWidth()) .map(p_358887_ -> p_358887_.add(0.0, -d1, 0.0)) .orElse(vec3); } } this.dismountTo(vec3.x, vec3.y, vec3.z); } @Override public boolean shouldShowName() { return this.isCustomNameVisible(); } protected float getJumpPower() { return this.getJumpPower(1.0F); } protected float getJumpPower(float p_329899_) { return (float)this.getAttributeValue(Attributes.JUMP_STRENGTH) * p_329899_ * this.getBlockJumpFactor() + this.getJumpBoostPower(); } public float getJumpBoostPower() { return this.hasEffect(MobEffects.JUMP_BOOST) ? 0.1F * (this.getEffect(MobEffects.JUMP_BOOST).getAmplifier() + 1.0F) : 0.0F; } @VisibleForTesting public void jumpFromGround() { float f = this.getJumpPower(); if (!(f <= 1.0E-5F)) { Vec3 vec3 = this.getDeltaMovement(); this.setDeltaMovement(vec3.x, Math.max((double)f, vec3.y), vec3.z); if (this.isSprinting()) { float f1 = this.getYRot() * (float) (Math.PI / 180.0); this.addDeltaMovement(new Vec3(-Mth.sin(f1) * 0.2, 0.0, Mth.cos(f1) * 0.2)); } this.hasImpulse = true; } } protected void goDownInWater() { this.setDeltaMovement(this.getDeltaMovement().add(0.0, -0.04F, 0.0)); } protected void jumpInLiquid(TagKey p_204043_) { this.setDeltaMovement(this.getDeltaMovement().add(0.0, 0.04F, 0.0)); } protected float getWaterSlowDown() { return 0.8F; } public boolean canStandOnFluid(FluidState p_204042_) { return false; } @Override protected double getDefaultGravity() { return this.getAttributeValue(Attributes.GRAVITY); } protected double getEffectiveGravity() { boolean flag = this.getDeltaMovement().y <= 0.0; return flag && this.hasEffect(MobEffects.SLOW_FALLING) ? Math.min(this.getGravity(), 0.01) : this.getGravity(); } public void travel(Vec3 p_21280_) { FluidState fluidstate = this.level().getFluidState(this.blockPosition()); if ((this.isInWater() || this.isInLava()) && this.isAffectedByFluids() && !this.canStandOnFluid(fluidstate)) { this.travelInFluid(p_21280_); } else if (this.isFallFlying()) { this.travelFallFlying(p_21280_); } else { this.travelInAir(p_21280_); } } private void travelInAir(Vec3 p_362087_) { BlockPos blockpos = this.getBlockPosBelowThatAffectsMyMovement(); float f = this.onGround() ? this.level().getBlockState(blockpos).getBlock().getFriction() : 1.0F; float f1 = f * 0.91F; Vec3 vec3 = this.handleRelativeFrictionAndCalculateMovement(p_362087_, f); double d0 = vec3.y; MobEffectInstance mobeffectinstance = this.getEffect(MobEffects.LEVITATION); if (mobeffectinstance != null) { d0 += (0.05 * (mobeffectinstance.getAmplifier() + 1) - vec3.y) * 0.2; } else if (!this.level().isClientSide || this.level().hasChunkAt(blockpos)) { d0 -= this.getEffectiveGravity(); } else if (this.getY() > this.level().getMinY()) { d0 = -0.1; } else { d0 = 0.0; } if (this.shouldDiscardFriction()) { this.setDeltaMovement(vec3.x, d0, vec3.z); } else { float f2 = this instanceof FlyingAnimal ? f1 : 0.98F; this.setDeltaMovement(vec3.x * f1, d0 * f2, vec3.z * f1); } } private void travelInFluid(Vec3 p_362114_) { boolean flag = this.getDeltaMovement().y <= 0.0; double d0 = this.getY(); double d1 = this.getEffectiveGravity(); if (this.isInWater()) { float f = this.isSprinting() ? 0.9F : this.getWaterSlowDown(); float f1 = 0.02F; float f2 = (float)this.getAttributeValue(Attributes.WATER_MOVEMENT_EFFICIENCY); if (!this.onGround()) { f2 *= 0.5F; } if (f2 > 0.0F) { f += (0.54600006F - f) * f2; f1 += (this.getSpeed() - f1) * f2; } if (this.hasEffect(MobEffects.DOLPHINS_GRACE)) { f = 0.96F; } this.moveRelative(f1, p_362114_); this.move(MoverType.SELF, this.getDeltaMovement()); Vec3 vec3 = this.getDeltaMovement(); if (this.horizontalCollision && this.onClimbable()) { vec3 = new Vec3(vec3.x, 0.2, vec3.z); } vec3 = vec3.multiply(f, 0.8F, f); this.setDeltaMovement(this.getFluidFallingAdjustedMovement(d1, flag, vec3)); } else { this.moveRelative(0.02F, p_362114_); this.move(MoverType.SELF, this.getDeltaMovement()); if (this.getFluidHeight(FluidTags.LAVA) <= this.getFluidJumpThreshold()) { this.setDeltaMovement(this.getDeltaMovement().multiply(0.5, 0.8F, 0.5)); Vec3 vec31 = this.getFluidFallingAdjustedMovement(d1, flag, this.getDeltaMovement()); this.setDeltaMovement(vec31); } else { this.setDeltaMovement(this.getDeltaMovement().scale(0.5)); } if (d1 != 0.0) { this.setDeltaMovement(this.getDeltaMovement().add(0.0, -d1 / 4.0, 0.0)); } } Vec3 vec32 = this.getDeltaMovement(); if (this.horizontalCollision && this.isFree(vec32.x, vec32.y + 0.6F - this.getY() + d0, vec32.z)) { this.setDeltaMovement(vec32.x, 0.3F, vec32.z); } } private void travelFallFlying(Vec3 p_391378_) { if (this.onClimbable()) { this.travelInAir(p_391378_); this.stopFallFlying(); } else { Vec3 vec3 = this.getDeltaMovement(); double d0 = vec3.horizontalDistance(); this.setDeltaMovement(this.updateFallFlyingMovement(vec3)); this.move(MoverType.SELF, this.getDeltaMovement()); if (!this.level().isClientSide) { double d1 = this.getDeltaMovement().horizontalDistance(); this.handleFallFlyingCollisions(d0, d1); } } } public void stopFallFlying() { this.setSharedFlag(7, true); this.setSharedFlag(7, false); } private Vec3 updateFallFlyingMovement(Vec3 p_366729_) { Vec3 vec3 = this.getLookAngle(); float f = this.getXRot() * (float) (Math.PI / 180.0); double d0 = Math.sqrt(vec3.x * vec3.x + vec3.z * vec3.z); double d1 = p_366729_.horizontalDistance(); double d2 = this.getEffectiveGravity(); double d3 = Mth.square(Math.cos(f)); p_366729_ = p_366729_.add(0.0, d2 * (-1.0 + d3 * 0.75), 0.0); if (p_366729_.y < 0.0 && d0 > 0.0) { double d4 = p_366729_.y * -0.1 * d3; p_366729_ = p_366729_.add(vec3.x * d4 / d0, d4, vec3.z * d4 / d0); } if (f < 0.0F && d0 > 0.0) { double d5 = d1 * -Mth.sin(f) * 0.04; p_366729_ = p_366729_.add(-vec3.x * d5 / d0, d5 * 3.2, -vec3.z * d5 / d0); } if (d0 > 0.0) { p_366729_ = p_366729_.add((vec3.x / d0 * d1 - p_366729_.x) * 0.1, 0.0, (vec3.z / d0 * d1 - p_366729_.z) * 0.1); } return p_366729_.multiply(0.99F, 0.98F, 0.99F); } private void handleFallFlyingCollisions(double p_368432_, double p_367807_) { if (this.horizontalCollision) { double d0 = p_368432_ - p_367807_; float f = (float)(d0 * 10.0 - 3.0); if (f > 0.0F) { this.playSound(this.getFallDamageSound((int)f), 1.0F, 1.0F); this.hurt(this.damageSources().flyIntoWall(), f); } } } private void travelRidden(Player p_278244_, Vec3 p_278231_) { Vec3 vec3 = this.getRiddenInput(p_278244_, p_278231_); this.tickRidden(p_278244_, vec3); if (this.canSimulateMovement()) { this.setSpeed(this.getRiddenSpeed(p_278244_)); this.travel(vec3); } else { this.setDeltaMovement(Vec3.ZERO); } } protected void tickRidden(Player p_278262_, Vec3 p_275242_) { } protected Vec3 getRiddenInput(Player p_278326_, Vec3 p_275300_) { return p_275300_; } protected float getRiddenSpeed(Player p_278286_) { return this.getSpeed(); } public void calculateEntityAnimation(boolean p_268129_) { float f = (float)Mth.length(this.getX() - this.xo, p_268129_ ? this.getY() - this.yo : 0.0, this.getZ() - this.zo); if (!this.isPassenger() && this.isAlive()) { this.updateWalkAnimation(f); } else { this.walkAnimation.stop(); } } protected void updateWalkAnimation(float p_268283_) { float f = Math.min(p_268283_ * 4.0F, 1.0F); this.walkAnimation.update(f, 0.4F, this.isBaby() ? 3.0F : 1.0F); } private Vec3 handleRelativeFrictionAndCalculateMovement(Vec3 p_21075_, float p_21076_) { this.moveRelative(this.getFrictionInfluencedSpeed(p_21076_), p_21075_); this.setDeltaMovement(this.handleOnClimbable(this.getDeltaMovement())); this.move(MoverType.SELF, this.getDeltaMovement()); Vec3 vec3 = this.getDeltaMovement(); if ((this.horizontalCollision || this.jumping) && (this.onClimbable() || this.wasInPowderSnow && PowderSnowBlock.canEntityWalkOnPowderSnow(this))) { vec3 = new Vec3(vec3.x, 0.2, vec3.z); } return vec3; } public Vec3 getFluidFallingAdjustedMovement(double p_20995_, boolean p_20996_, Vec3 p_20997_) { if (p_20995_ != 0.0 && !this.isSprinting()) { double d0; if (p_20996_ && Math.abs(p_20997_.y - 0.005) >= 0.003 && Math.abs(p_20997_.y - p_20995_ / 16.0) < 0.003) { d0 = -0.003; } else { d0 = p_20997_.y - p_20995_ / 16.0; } return new Vec3(p_20997_.x, d0, p_20997_.z); } else { return p_20997_; } } private Vec3 handleOnClimbable(Vec3 p_21298_) { if (this.onClimbable()) { this.resetFallDistance(); float f = 0.15F; double d0 = Mth.clamp(p_21298_.x, -0.15F, 0.15F); double d1 = Mth.clamp(p_21298_.z, -0.15F, 0.15F); double d2 = Math.max(p_21298_.y, -0.15F); if (d2 < 0.0 && !this.getInBlockState().is(Blocks.SCAFFOLDING) && this.isSuppressingSlidingDownLadder() && this instanceof Player) { d2 = 0.0; } p_21298_ = new Vec3(d0, d2, d1); } return p_21298_; } private float getFrictionInfluencedSpeed(float p_21331_) { return this.onGround() ? this.getSpeed() * (0.21600002F / (p_21331_ * p_21331_ * p_21331_)) : this.getFlyingSpeed(); } protected float getFlyingSpeed() { return this.getControllingPassenger() instanceof Player ? this.getSpeed() * 0.1F : 0.02F; } public float getSpeed() { return this.speed; } public void setSpeed(float p_21320_) { this.speed = p_21320_; } public boolean doHurtTarget(ServerLevel p_366333_, Entity p_20970_) { this.setLastHurtMob(p_20970_); return false; } @Override public void tick() { super.tick(); this.updatingUsingItem(); this.updateSwimAmount(); if (!this.level().isClientSide) { int i = this.getArrowCount(); if (i > 0) { if (this.removeArrowTime <= 0) { this.removeArrowTime = 20 * (30 - i); } this.removeArrowTime--; if (this.removeArrowTime <= 0) { this.setArrowCount(i - 1); } } int j = this.getStingerCount(); if (j > 0) { if (this.removeStingerTime <= 0) { this.removeStingerTime = 20 * (30 - j); } this.removeStingerTime--; if (this.removeStingerTime <= 0) { this.setStingerCount(j - 1); } } this.detectEquipmentUpdates(); if (this.tickCount % 20 == 0) { this.getCombatTracker().recheckStatus(); } if (this.isSleeping() && !this.checkBedExists()) { this.stopSleeping(); } } if (!this.isRemoved()) { this.aiStep(); } double d1 = this.getX() - this.xo; double d0 = this.getZ() - this.zo; float f = (float)(d1 * d1 + d0 * d0); float f1 = this.yBodyRot; if (f > 0.0025000002F) { float f2 = (float)Mth.atan2(d0, d1) * (180.0F / (float)Math.PI) - 90.0F; float f3 = Mth.abs(Mth.wrapDegrees(this.getYRot()) - f2); if (95.0F < f3 && f3 < 265.0F) { f1 = f2 - 180.0F; } else { f1 = f2; } } if (this.attackAnim > 0.0F) { f1 = this.getYRot(); } ProfilerFiller profilerfiller = Profiler.get(); profilerfiller.push("headTurn"); this.tickHeadTurn(f1); profilerfiller.pop(); profilerfiller.push("rangeChecks"); while (this.getYRot() - this.yRotO < -180.0F) { this.yRotO -= 360.0F; } while (this.getYRot() - this.yRotO >= 180.0F) { this.yRotO += 360.0F; } while (this.yBodyRot - this.yBodyRotO < -180.0F) { this.yBodyRotO -= 360.0F; } while (this.yBodyRot - this.yBodyRotO >= 180.0F) { this.yBodyRotO += 360.0F; } while (this.getXRot() - this.xRotO < -180.0F) { this.xRotO -= 360.0F; } while (this.getXRot() - this.xRotO >= 180.0F) { this.xRotO += 360.0F; } while (this.yHeadRot - this.yHeadRotO < -180.0F) { this.yHeadRotO -= 360.0F; } while (this.yHeadRot - this.yHeadRotO >= 180.0F) { this.yHeadRotO += 360.0F; } profilerfiller.pop(); if (this.isFallFlying()) { this.fallFlyTicks++; } else { this.fallFlyTicks = 0; } if (this.isSleeping()) { this.setXRot(0.0F); } this.refreshDirtyAttributes(); this.elytraAnimationState.tick(); } private void detectEquipmentUpdates() { Map map = this.collectEquipmentChanges(); if (map != null) { this.handleHandSwap(map); if (!map.isEmpty()) { this.handleEquipmentChanges(map); } } } @Nullable private Map collectEquipmentChanges() { Map map = null; for (EquipmentSlot equipmentslot : EquipmentSlot.VALUES) { ItemStack itemstack = this.lastEquipmentItems.get(equipmentslot); ItemStack itemstack1 = this.getItemBySlot(equipmentslot); if (this.equipmentHasChanged(itemstack, itemstack1)) { if (map == null) { map = Maps.newEnumMap(EquipmentSlot.class); } map.put(equipmentslot, itemstack1); AttributeMap attributemap = this.getAttributes(); if (!itemstack.isEmpty()) { this.stopLocationBasedEffects(itemstack, equipmentslot, attributemap); } } } if (map != null) { for (Entry entry : map.entrySet()) { EquipmentSlot equipmentslot1 = entry.getKey(); ItemStack itemstack2 = entry.getValue(); if (!itemstack2.isEmpty() && !itemstack2.isBroken()) { itemstack2.forEachModifier(equipmentslot1, (p_358896_, p_358897_) -> { AttributeInstance attributeinstance = this.attributes.getInstance(p_358896_); if (attributeinstance != null) { attributeinstance.removeModifier(p_358897_.id()); attributeinstance.addTransientModifier(p_358897_); } }); if (this.level() instanceof ServerLevel serverlevel) { EnchantmentHelper.runLocationChangedEffects(serverlevel, itemstack2, this, equipmentslot1); } } } } return map; } public boolean equipmentHasChanged(ItemStack p_252265_, ItemStack p_251043_) { return !ItemStack.matches(p_251043_, p_252265_); } private void handleHandSwap(Map p_21092_) { ItemStack itemstack = p_21092_.get(EquipmentSlot.MAINHAND); ItemStack itemstack1 = p_21092_.get(EquipmentSlot.OFFHAND); if (itemstack != null && itemstack1 != null && ItemStack.matches(itemstack, this.lastEquipmentItems.get(EquipmentSlot.OFFHAND)) && ItemStack.matches(itemstack1, this.lastEquipmentItems.get(EquipmentSlot.MAINHAND))) { ((ServerLevel)this.level()).getChunkSource().broadcast(this, new ClientboundEntityEventPacket(this, (byte)55)); p_21092_.remove(EquipmentSlot.MAINHAND); p_21092_.remove(EquipmentSlot.OFFHAND); this.lastEquipmentItems.put(EquipmentSlot.MAINHAND, itemstack.copy()); this.lastEquipmentItems.put(EquipmentSlot.OFFHAND, itemstack1.copy()); } } private void handleEquipmentChanges(Map p_21143_) { List> list = Lists.newArrayListWithCapacity(p_21143_.size()); p_21143_.forEach((p_390521_, p_390522_) -> { ItemStack itemstack = p_390522_.copy(); list.add(Pair.of(p_390521_, itemstack)); this.lastEquipmentItems.put(p_390521_, itemstack); }); ((ServerLevel)this.level()).getChunkSource().broadcast(this, new ClientboundSetEquipmentPacket(this.getId(), list)); } protected void tickHeadTurn(float p_21260_) { float f = Mth.wrapDegrees(p_21260_ - this.yBodyRot); this.yBodyRot += f * 0.3F; float f1 = Mth.wrapDegrees(this.getYRot() - this.yBodyRot); float f2 = this.getMaxHeadRotationRelativeToBody(); if (Math.abs(f1) > f2) { this.yBodyRot = this.yBodyRot + (f1 - Mth.sign(f1) * f2); } } protected float getMaxHeadRotationRelativeToBody() { return 50.0F; } public void aiStep() { if (this.noJumpDelay > 0) { this.noJumpDelay--; } if (this.isInterpolating()) { this.getInterpolation().interpolate(); } else if (!this.canSimulateMovement()) { this.setDeltaMovement(this.getDeltaMovement().scale(0.98)); } if (this.lerpHeadSteps > 0) { this.lerpHeadRotationStep(this.lerpHeadSteps, this.lerpYHeadRot); this.lerpHeadSteps--; } this.equipment.tick(this); Vec3 vec3 = this.getDeltaMovement(); double d0 = vec3.x; double d1 = vec3.y; double d2 = vec3.z; if (this.getType().equals(EntityType.PLAYER)) { if (vec3.horizontalDistanceSqr() < 9.0E-6) { d0 = 0.0; d2 = 0.0; } } else { if (Math.abs(vec3.x) < 0.003) { d0 = 0.0; } if (Math.abs(vec3.z) < 0.003) { d2 = 0.0; } } if (Math.abs(vec3.y) < 0.003) { d1 = 0.0; } this.setDeltaMovement(d0, d1, d2); ProfilerFiller profilerfiller = Profiler.get(); profilerfiller.push("ai"); this.applyInput(); if (this.isImmobile()) { this.jumping = false; this.xxa = 0.0F; this.zza = 0.0F; } else if (this.isEffectiveAi() && !this.level().isClientSide) { profilerfiller.push("newAi"); this.serverAiStep(); profilerfiller.pop(); } profilerfiller.pop(); profilerfiller.push("jump"); if (this.jumping && this.isAffectedByFluids()) { double d3; if (this.isInLava()) { d3 = this.getFluidHeight(FluidTags.LAVA); } else { d3 = this.getFluidHeight(FluidTags.WATER); } boolean flag = this.isInWater() && d3 > 0.0; double d4 = this.getFluidJumpThreshold(); if (!flag || this.onGround() && !(d3 > d4)) { if (!this.isInLava() || this.onGround() && !(d3 > d4)) { if ((this.onGround() || flag && d3 <= d4) && this.noJumpDelay == 0) { this.jumpFromGround(); this.noJumpDelay = 10; } } else { this.jumpInLiquid(FluidTags.LAVA); } } else { this.jumpInLiquid(FluidTags.WATER); } } else { this.noJumpDelay = 0; } profilerfiller.pop(); profilerfiller.push("travel"); if (this.isFallFlying()) { this.updateFallFlying(); } AABB aabb = this.getBoundingBox(); Vec3 vec31 = new Vec3(this.xxa, this.yya, this.zza); if (this.hasEffect(MobEffects.SLOW_FALLING) || this.hasEffect(MobEffects.LEVITATION)) { this.resetFallDistance(); } if (this.getControllingPassenger() instanceof Player player && this.isAlive()) { this.travelRidden(player, vec31); } else if (this.canSimulateMovement()) { this.travel(vec31); } if (!this.level().isClientSide() || this.isLocalInstanceAuthoritative()) { this.applyEffectsFromBlocks(); } if (this.level().isClientSide()) { this.calculateEntityAnimation(this instanceof FlyingAnimal); } profilerfiller.pop(); if (this.level() instanceof ServerLevel serverlevel) { profilerfiller.push("freezing"); if (!this.isInPowderSnow || !this.canFreeze()) { this.setTicksFrozen(Math.max(0, this.getTicksFrozen() - 2)); } this.removeFrost(); this.tryAddFrost(); if (this.tickCount % 40 == 0 && this.isFullyFrozen() && this.canFreeze()) { this.hurtServer(serverlevel, this.damageSources().freeze(), 1.0F); } profilerfiller.pop(); } profilerfiller.push("push"); if (this.autoSpinAttackTicks > 0) { this.autoSpinAttackTicks--; this.checkAutoSpinAttack(aabb, this.getBoundingBox()); } this.pushEntities(); profilerfiller.pop(); if (this.level() instanceof ServerLevel serverlevel1 && this.isSensitiveToWater() && this.isInWaterOrRain()) { this.hurtServer(serverlevel1, this.damageSources().drown(), 1.0F); } } protected void applyInput() { this.xxa *= 0.98F; this.zza *= 0.98F; } public boolean isSensitiveToWater() { return false; } protected void updateFallFlying() { this.checkSlowFallDistance(); if (!this.level().isClientSide) { if (!this.canGlide()) { this.setSharedFlag(7, false); return; } int i = this.fallFlyTicks + 1; if (i % 10 == 0) { int j = i / 10; if (j % 2 == 0) { List list = EquipmentSlot.VALUES.stream().filter(p_358890_ -> canGlideUsing(this.getItemBySlot(p_358890_), p_358890_)).toList(); EquipmentSlot equipmentslot = Util.getRandom(list, this.random); this.getItemBySlot(equipmentslot).hurtAndBreak(1, this, equipmentslot); } this.gameEvent(GameEvent.ELYTRA_GLIDE); } } } protected boolean canGlide() { if (!this.onGround() && !this.isPassenger() && !this.hasEffect(MobEffects.LEVITATION)) { for (EquipmentSlot equipmentslot : EquipmentSlot.VALUES) { if (canGlideUsing(this.getItemBySlot(equipmentslot), equipmentslot)) { return true; } } return false; } else { return false; } } protected void serverAiStep() { } protected void pushEntities() { List list = this.level().getPushableEntities(this, this.getBoundingBox()); if (!list.isEmpty()) { if (this.level() instanceof ServerLevel serverlevel) { int j = serverlevel.getGameRules().getInt(GameRules.RULE_MAX_ENTITY_CRAMMING); if (j > 0 && list.size() > j - 1 && this.random.nextInt(4) == 0) { int i = 0; for (Entity entity : list) { if (!entity.isPassenger()) { i++; } } if (i > j - 1) { this.hurtServer(serverlevel, this.damageSources().cramming(), 6.0F); } } } for (Entity entity1 : list) { this.doPush(entity1); } } } protected void checkAutoSpinAttack(AABB p_21072_, AABB p_21073_) { AABB aabb = p_21072_.minmax(p_21073_); List list = this.level().getEntities(this, aabb); if (!list.isEmpty()) { for (Entity entity : list) { if (entity instanceof LivingEntity) { this.doAutoAttackOnTouch((LivingEntity)entity); this.autoSpinAttackTicks = 0; this.setDeltaMovement(this.getDeltaMovement().scale(-0.2)); break; } } } else if (this.horizontalCollision) { this.autoSpinAttackTicks = 0; } if (!this.level().isClientSide && this.autoSpinAttackTicks <= 0) { this.setLivingEntityFlag(4, false); this.autoSpinAttackDmg = 0.0F; this.autoSpinAttackItemStack = null; } } protected void doPush(Entity p_20971_) { p_20971_.push(this); } protected void doAutoAttackOnTouch(LivingEntity p_21277_) { } public boolean isAutoSpinAttack() { return (this.entityData.get(DATA_LIVING_ENTITY_FLAGS) & 4) != 0; } @Override public void stopRiding() { Entity entity = this.getVehicle(); super.stopRiding(); if (entity != null && entity != this.getVehicle() && !this.level().isClientSide) { this.dismountVehicle(entity); } } @Override public void rideTick() { super.rideTick(); this.resetFallDistance(); } @Override public InterpolationHandler getInterpolation() { return this.interpolation; } @Override public void lerpHeadTo(float p_21005_, int p_21006_) { this.lerpYHeadRot = p_21005_; this.lerpHeadSteps = p_21006_; } public void setJumping(boolean p_21314_) { this.jumping = p_21314_; } public void onItemPickup(ItemEntity p_21054_) { Entity entity = p_21054_.getOwner(); if (entity instanceof ServerPlayer) { CriteriaTriggers.THROWN_ITEM_PICKED_UP_BY_ENTITY.trigger((ServerPlayer)entity, p_21054_.getItem(), this); } } public void take(Entity p_21030_, int p_21031_) { if (!p_21030_.isRemoved() && !this.level().isClientSide && (p_21030_ instanceof ItemEntity || p_21030_ instanceof AbstractArrow || p_21030_ instanceof ExperienceOrb)) { ((ServerLevel)this.level()).getChunkSource().broadcast(p_21030_, new ClientboundTakeItemEntityPacket(p_21030_.getId(), this.getId(), p_21031_)); } } public boolean hasLineOfSight(Entity p_147185_) { return this.hasLineOfSight(p_147185_, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, p_147185_.getEyeY()); } public boolean hasLineOfSight(Entity p_364584_, ClipContext.Block p_368226_, ClipContext.Fluid p_368626_, double p_375593_) { if (p_364584_.level() != this.level()) { return false; } else { Vec3 vec3 = new Vec3(this.getX(), this.getEyeY(), this.getZ()); Vec3 vec31 = new Vec3(p_364584_.getX(), p_375593_, p_364584_.getZ()); return vec31.distanceTo(vec3) > 128.0 ? false : this.level().clip(new ClipContext(vec3, vec31, p_368226_, p_368626_, this)).getType() == HitResult.Type.MISS; } } @Override public float getViewYRot(float p_21286_) { return p_21286_ == 1.0F ? this.yHeadRot : Mth.rotLerp(p_21286_, this.yHeadRotO, this.yHeadRot); } public float getAttackAnim(float p_21325_) { float f = this.attackAnim - this.oAttackAnim; if (f < 0.0F) { f++; } return this.oAttackAnim + f * p_21325_; } @Override public boolean isPickable() { return !this.isRemoved(); } @Override public boolean isPushable() { return this.isAlive() && !this.isSpectator() && !this.onClimbable(); } @Override public float getYHeadRot() { return this.yHeadRot; } @Override public void setYHeadRot(float p_21306_) { this.yHeadRot = p_21306_; } @Override public void setYBodyRot(float p_21309_) { this.yBodyRot = p_21309_; } @Override public Vec3 getRelativePortalPosition(Direction.Axis p_21085_, BlockUtil.FoundRectangle p_21086_) { return resetForwardDirectionOfRelativePortalPosition(super.getRelativePortalPosition(p_21085_, p_21086_)); } public static Vec3 resetForwardDirectionOfRelativePortalPosition(Vec3 p_21290_) { return new Vec3(p_21290_.x, p_21290_.y, 0.0); } public float getAbsorptionAmount() { return this.absorptionAmount; } public final void setAbsorptionAmount(float p_21328_) { this.internalSetAbsorptionAmount(Mth.clamp(p_21328_, 0.0F, this.getMaxAbsorption())); } protected void internalSetAbsorptionAmount(float p_299471_) { this.absorptionAmount = p_299471_; } public void onEnterCombat() { } public void onLeaveCombat() { } protected void updateEffectVisibility() { this.effectsDirty = true; } public abstract HumanoidArm getMainArm(); public boolean isUsingItem() { return (this.entityData.get(DATA_LIVING_ENTITY_FLAGS) & 1) > 0; } public InteractionHand getUsedItemHand() { return (this.entityData.get(DATA_LIVING_ENTITY_FLAGS) & 2) > 0 ? InteractionHand.OFF_HAND : InteractionHand.MAIN_HAND; } private void updatingUsingItem() { if (this.isUsingItem()) { if (ItemStack.isSameItem(this.getItemInHand(this.getUsedItemHand()), this.useItem)) { this.useItem = this.getItemInHand(this.getUsedItemHand()); this.updateUsingItem(this.useItem); } else { this.stopUsingItem(); } } } @Nullable private ItemEntity createItemStackToDrop(ItemStack p_395029_, boolean p_394798_, boolean p_392209_) { if (p_395029_.isEmpty()) { return null; } else { double d0 = this.getEyeY() - 0.3F; ItemEntity itementity = new ItemEntity(this.level(), this.getX(), d0, this.getZ(), p_395029_); itementity.setPickUpDelay(40); if (p_392209_) { itementity.setThrower(this); } if (p_394798_) { float f = this.random.nextFloat() * 0.5F; float f1 = this.random.nextFloat() * (float) (Math.PI * 2); itementity.setDeltaMovement(-Mth.sin(f1) * f, 0.2F, Mth.cos(f1) * f); } else { float f7 = 0.3F; float f8 = Mth.sin(this.getXRot() * (float) (Math.PI / 180.0)); float f2 = Mth.cos(this.getXRot() * (float) (Math.PI / 180.0)); float f3 = Mth.sin(this.getYRot() * (float) (Math.PI / 180.0)); float f4 = Mth.cos(this.getYRot() * (float) (Math.PI / 180.0)); float f5 = this.random.nextFloat() * (float) (Math.PI * 2); float f6 = 0.02F * this.random.nextFloat(); itementity.setDeltaMovement( -f3 * f2 * 0.3F + Math.cos(f5) * f6, -f8 * 0.3F + 0.1F + (this.random.nextFloat() - this.random.nextFloat()) * 0.1F, f4 * f2 * 0.3F + Math.sin(f5) * f6 ); } return itementity; } } protected void updateUsingItem(ItemStack p_147201_) { p_147201_.onUseTick(this.level(), this, this.getUseItemRemainingTicks()); if (--this.useItemRemaining == 0 && !this.level().isClientSide && !p_147201_.useOnRelease()) { this.completeUsingItem(); } } private void updateSwimAmount() { this.swimAmountO = this.swimAmount; if (this.isVisuallySwimming()) { this.swimAmount = Math.min(1.0F, this.swimAmount + 0.09F); } else { this.swimAmount = Math.max(0.0F, this.swimAmount - 0.09F); } } protected void setLivingEntityFlag(int p_21156_, boolean p_21157_) { int i = this.entityData.get(DATA_LIVING_ENTITY_FLAGS); if (p_21157_) { i |= p_21156_; } else { i &= ~p_21156_; } this.entityData.set(DATA_LIVING_ENTITY_FLAGS, (byte)i); } public void startUsingItem(InteractionHand p_21159_) { ItemStack itemstack = this.getItemInHand(p_21159_); if (!itemstack.isEmpty() && !this.isUsingItem()) { this.useItem = itemstack; this.useItemRemaining = itemstack.getUseDuration(this); if (!this.level().isClientSide) { this.setLivingEntityFlag(1, true); this.setLivingEntityFlag(2, p_21159_ == InteractionHand.OFF_HAND); this.gameEvent(GameEvent.ITEM_INTERACT_START); } } } @Override public void onSyncedDataUpdated(EntityDataAccessor p_21104_) { super.onSyncedDataUpdated(p_21104_); if (SLEEPING_POS_ID.equals(p_21104_)) { if (this.level().isClientSide) { this.getSleepingPos().ifPresent(this::setPosToBed); } } else if (DATA_LIVING_ENTITY_FLAGS.equals(p_21104_) && this.level().isClientSide) { if (this.isUsingItem() && this.useItem.isEmpty()) { this.useItem = this.getItemInHand(this.getUsedItemHand()); if (!this.useItem.isEmpty()) { this.useItemRemaining = this.useItem.getUseDuration(this); } } else if (!this.isUsingItem() && !this.useItem.isEmpty()) { this.useItem = ItemStack.EMPTY; this.useItemRemaining = 0; } } } @Override public void lookAt(EntityAnchorArgument.Anchor p_21078_, Vec3 p_21079_) { super.lookAt(p_21078_, p_21079_); this.yHeadRotO = this.yHeadRot; this.yBodyRot = this.yHeadRot; this.yBodyRotO = this.yBodyRot; } @Override public float getPreciseBodyRotation(float p_345405_) { return Mth.lerp(p_345405_, this.yBodyRotO, this.yBodyRot); } public void spawnItemParticles(ItemStack p_21061_, int p_21062_) { for (int i = 0; i < p_21062_; i++) { Vec3 vec3 = new Vec3((this.random.nextFloat() - 0.5) * 0.1, Math.random() * 0.1 + 0.1, 0.0); vec3 = vec3.xRot(-this.getXRot() * (float) (Math.PI / 180.0)); vec3 = vec3.yRot(-this.getYRot() * (float) (Math.PI / 180.0)); double d0 = -this.random.nextFloat() * 0.6 - 0.3; Vec3 vec31 = new Vec3((this.random.nextFloat() - 0.5) * 0.3, d0, 0.6); vec31 = vec31.xRot(-this.getXRot() * (float) (Math.PI / 180.0)); vec31 = vec31.yRot(-this.getYRot() * (float) (Math.PI / 180.0)); vec31 = vec31.add(this.getX(), this.getEyeY(), this.getZ()); this.level() .addParticle( new ItemParticleOption(ParticleTypes.ITEM, p_21061_), vec31.x, vec31.y, vec31.z, vec3.x, vec3.y + 0.05, vec3.z ); } } protected void completeUsingItem() { if (!this.level().isClientSide || this.isUsingItem()) { InteractionHand interactionhand = this.getUsedItemHand(); if (!this.useItem.equals(this.getItemInHand(interactionhand))) { this.releaseUsingItem(); } else { if (!this.useItem.isEmpty() && this.isUsingItem()) { ItemStack itemstack = this.useItem.finishUsingItem(this.level(), this); if (itemstack != this.useItem) { this.setItemInHand(interactionhand, itemstack); } this.stopUsingItem(); } } } } public void handleExtraItemsCreatedOnUse(ItemStack p_367452_) { } public ItemStack getUseItem() { return this.useItem; } public int getUseItemRemainingTicks() { return this.useItemRemaining; } public int getTicksUsingItem() { return this.isUsingItem() ? this.useItem.getUseDuration(this) - this.getUseItemRemainingTicks() : 0; } public void releaseUsingItem() { ItemStack itemstack = this.getItemInHand(this.getUsedItemHand()); if (!this.useItem.isEmpty() && ItemStack.isSameItem(itemstack, this.useItem)) { this.useItem = itemstack; this.useItem.releaseUsing(this.level(), this, this.getUseItemRemainingTicks()); if (this.useItem.useOnRelease()) { this.updatingUsingItem(); } } this.stopUsingItem(); } public void stopUsingItem() { if (!this.level().isClientSide) { boolean flag = this.isUsingItem(); this.setLivingEntityFlag(1, false); if (flag) { this.gameEvent(GameEvent.ITEM_INTERACT_FINISH); } } this.useItem = ItemStack.EMPTY; this.useItemRemaining = 0; } public boolean isBlocking() { return this.getItemBlockingWith() != null; } @Nullable public ItemStack getItemBlockingWith() { if (!this.isUsingItem()) { return null; } else { BlocksAttacks blocksattacks = this.useItem.get(DataComponents.BLOCKS_ATTACKS); if (blocksattacks != null) { int i = this.useItem.getItem().getUseDuration(this.useItem, this) - this.useItemRemaining; if (i >= blocksattacks.blockDelayTicks()) { return this.useItem; } } return null; } } public boolean isSuppressingSlidingDownLadder() { return this.isShiftKeyDown(); } public boolean isFallFlying() { return this.getSharedFlag(7); } @Override public boolean isVisuallySwimming() { return super.isVisuallySwimming() || !this.isFallFlying() && this.hasPose(Pose.FALL_FLYING); } public int getFallFlyingTicks() { return this.fallFlyTicks; } public boolean randomTeleport(double p_20985_, double p_20986_, double p_20987_, boolean p_20988_) { double d0 = this.getX(); double d1 = this.getY(); double d2 = this.getZ(); double d3 = p_20986_; boolean flag = false; BlockPos blockpos = BlockPos.containing(p_20985_, p_20986_, p_20987_); Level level = this.level(); if (level.hasChunkAt(blockpos)) { boolean flag1 = false; while (!flag1 && blockpos.getY() > level.getMinY()) { BlockPos blockpos1 = blockpos.below(); BlockState blockstate = level.getBlockState(blockpos1); if (blockstate.blocksMotion()) { flag1 = true; } else { d3--; blockpos = blockpos1; } } if (flag1) { this.teleportTo(p_20985_, d3, p_20987_); if (level.noCollision(this) && !level.containsAnyLiquid(this.getBoundingBox())) { flag = true; } } } if (!flag) { this.teleportTo(d0, d1, d2); return false; } else { if (p_20988_) { level.broadcastEntityEvent(this, (byte)46); } if (this instanceof PathfinderMob pathfindermob) { pathfindermob.getNavigation().stop(); } return true; } } public boolean isAffectedByPotions() { return !this.isDeadOrDying(); } public boolean attackable() { return true; } public void setRecordPlayingNearby(BlockPos p_21082_, boolean p_21083_) { } public boolean canPickUpLoot() { return false; } @Override public final EntityDimensions getDimensions(Pose p_21047_) { return p_21047_ == Pose.SLEEPING ? SLEEPING_DIMENSIONS : this.getDefaultDimensions(p_21047_).scale(this.getScale()); } protected EntityDimensions getDefaultDimensions(Pose p_334284_) { return this.getType().getDimensions().scale(this.getAgeScale()); } public ImmutableList getDismountPoses() { return ImmutableList.of(Pose.STANDING); } public AABB getLocalBoundsForPose(Pose p_21271_) { EntityDimensions entitydimensions = this.getDimensions(p_21271_); return new AABB( -entitydimensions.width() / 2.0F, 0.0, -entitydimensions.width() / 2.0F, entitydimensions.width() / 2.0F, entitydimensions.height(), entitydimensions.width() / 2.0F ); } protected boolean wouldNotSuffocateAtTargetPose(Pose p_297537_) { AABB aabb = this.getDimensions(p_297537_).makeBoundingBox(this.position()); return this.level().noBlockCollision(this, aabb); } @Override public boolean canUsePortal(boolean p_342370_) { return super.canUsePortal(p_342370_) && !this.isSleeping(); } public Optional getSleepingPos() { return this.entityData.get(SLEEPING_POS_ID); } public void setSleepingPos(BlockPos p_21251_) { this.entityData.set(SLEEPING_POS_ID, Optional.of(p_21251_)); } public void clearSleepingPos() { this.entityData.set(SLEEPING_POS_ID, Optional.empty()); } public boolean isSleeping() { return this.getSleepingPos().isPresent(); } public void startSleeping(BlockPos p_21141_) { if (this.isPassenger()) { this.stopRiding(); } BlockState blockstate = this.level().getBlockState(p_21141_); if (blockstate.getBlock() instanceof BedBlock) { this.level().setBlock(p_21141_, blockstate.setValue(BedBlock.OCCUPIED, true), 3); } this.setPose(Pose.SLEEPING); this.setPosToBed(p_21141_); this.setSleepingPos(p_21141_); this.setDeltaMovement(Vec3.ZERO); this.hasImpulse = true; } private void setPosToBed(BlockPos p_21081_) { this.setPos(p_21081_.getX() + 0.5, p_21081_.getY() + 0.6875, p_21081_.getZ() + 0.5); } private boolean checkBedExists() { return this.getSleepingPos().map(p_374931_ -> this.level().getBlockState(p_374931_).getBlock() instanceof BedBlock).orElse(false); } public void stopSleeping() { this.getSleepingPos().filter(this.level()::hasChunkAt).ifPresent(p_261435_ -> { BlockState blockstate = this.level().getBlockState(p_261435_); if (blockstate.getBlock() instanceof BedBlock) { Direction direction = blockstate.getValue(BedBlock.FACING); this.level().setBlock(p_261435_, blockstate.setValue(BedBlock.OCCUPIED, false), 3); Vec3 vec31 = BedBlock.findStandUpPosition(this.getType(), this.level(), p_261435_, direction, this.getYRot()).orElseGet(() -> { BlockPos blockpos = p_261435_.above(); return new Vec3(blockpos.getX() + 0.5, blockpos.getY() + 0.1, blockpos.getZ() + 0.5); }); Vec3 vec32 = Vec3.atBottomCenterOf(p_261435_).subtract(vec31).normalize(); float f = (float)Mth.wrapDegrees(Mth.atan2(vec32.z, vec32.x) * 180.0F / (float)Math.PI - 90.0); this.setPos(vec31.x, vec31.y, vec31.z); this.setYRot(f); this.setXRot(0.0F); } }); Vec3 vec3 = this.position(); this.setPose(Pose.STANDING); this.setPos(vec3.x, vec3.y, vec3.z); this.clearSleepingPos(); } @Nullable public Direction getBedOrientation() { BlockPos blockpos = this.getSleepingPos().orElse(null); return blockpos != null ? BedBlock.getBedOrientation(this.level(), blockpos) : null; } @Override public boolean isInWall() { return !this.isSleeping() && super.isInWall(); } public ItemStack getProjectile(ItemStack p_21272_) { return ItemStack.EMPTY; } private static byte entityEventForEquipmentBreak(EquipmentSlot p_21267_) { return switch (p_21267_) { case MAINHAND -> 47; case OFFHAND -> 48; case HEAD -> 49; case CHEST -> 50; case FEET -> 52; case LEGS -> 51; case BODY -> 65; case SADDLE -> 68; }; } public void onEquippedItemBroken(Item p_343772_, EquipmentSlot p_345353_) { this.level().broadcastEntityEvent(this, entityEventForEquipmentBreak(p_345353_)); this.stopLocationBasedEffects(this.getItemBySlot(p_345353_), p_345353_, this.attributes); } private void stopLocationBasedEffects(ItemStack p_369098_, EquipmentSlot p_365471_, AttributeMap p_363505_) { p_369098_.forEachModifier(p_365471_, (p_358882_, p_358883_) -> { AttributeInstance attributeinstance = p_363505_.getInstance(p_358882_); if (attributeinstance != null) { attributeinstance.removeModifier(p_358883_); } }); EnchantmentHelper.stopLocationBasedEffects(p_369098_, this, p_365471_); } public static EquipmentSlot getSlotForHand(InteractionHand p_333846_) { return p_333846_ == InteractionHand.MAIN_HAND ? EquipmentSlot.MAINHAND : EquipmentSlot.OFFHAND; } public final boolean canEquipWithDispenser(ItemStack p_362526_) { if (this.isAlive() && !this.isSpectator()) { Equippable equippable = p_362526_.get(DataComponents.EQUIPPABLE); if (equippable != null && equippable.dispensable()) { EquipmentSlot equipmentslot = equippable.slot(); return this.canUseSlot(equipmentslot) && equippable.canBeEquippedBy(this.getType()) ? this.getItemBySlot(equipmentslot).isEmpty() && this.canDispenserEquipIntoSlot(equipmentslot) : false; } else { return false; } } else { return false; } } protected boolean canDispenserEquipIntoSlot(EquipmentSlot p_362370_) { return true; } public final EquipmentSlot getEquipmentSlotForItem(ItemStack p_147234_) { Equippable equippable = p_147234_.get(DataComponents.EQUIPPABLE); return equippable != null && this.canUseSlot(equippable.slot()) ? equippable.slot() : EquipmentSlot.MAINHAND; } public final boolean isEquippableInSlot(ItemStack p_21138_, EquipmentSlot p_361200_) { Equippable equippable = p_21138_.get(DataComponents.EQUIPPABLE); return equippable == null ? p_361200_ == EquipmentSlot.MAINHAND && this.canUseSlot(EquipmentSlot.MAINHAND) : p_361200_ == equippable.slot() && this.canUseSlot(equippable.slot()) && equippable.canBeEquippedBy(this.getType()); } private static SlotAccess createEquipmentSlotAccess(LivingEntity p_147196_, EquipmentSlot p_147197_) { return p_147197_ != EquipmentSlot.HEAD && p_147197_ != EquipmentSlot.MAINHAND && p_147197_ != EquipmentSlot.OFFHAND ? SlotAccess.forEquipmentSlot(p_147196_, p_147197_, p_341262_ -> p_341262_.isEmpty() || p_147196_.getEquipmentSlotForItem(p_341262_) == p_147197_) : SlotAccess.forEquipmentSlot(p_147196_, p_147197_); } @Nullable private static EquipmentSlot getEquipmentSlot(int p_147212_) { if (p_147212_ == 100 + EquipmentSlot.HEAD.getIndex()) { return EquipmentSlot.HEAD; } else if (p_147212_ == 100 + EquipmentSlot.CHEST.getIndex()) { return EquipmentSlot.CHEST; } else if (p_147212_ == 100 + EquipmentSlot.LEGS.getIndex()) { return EquipmentSlot.LEGS; } else if (p_147212_ == 100 + EquipmentSlot.FEET.getIndex()) { return EquipmentSlot.FEET; } else if (p_147212_ == 98) { return EquipmentSlot.MAINHAND; } else if (p_147212_ == 99) { return EquipmentSlot.OFFHAND; } else if (p_147212_ == 105) { return EquipmentSlot.BODY; } else { return p_147212_ == 106 ? EquipmentSlot.SADDLE : null; } } @Override public SlotAccess getSlot(int p_147238_) { EquipmentSlot equipmentslot = getEquipmentSlot(p_147238_); return equipmentslot != null ? createEquipmentSlotAccess(this, equipmentslot) : super.getSlot(p_147238_); } @Override public boolean canFreeze() { if (this.isSpectator()) { return false; } else { for (EquipmentSlot equipmentslot : EquipmentSlotGroup.ARMOR) { if (this.getItemBySlot(equipmentslot).is(ItemTags.FREEZE_IMMUNE_WEARABLES)) { return false; } } return super.canFreeze(); } } @Override public boolean isCurrentlyGlowing() { return !this.level().isClientSide() && this.hasEffect(MobEffects.GLOWING) || super.isCurrentlyGlowing(); } @Override public float getVisualRotationYInDegrees() { return this.yBodyRot; } @Override public void recreateFromPacket(ClientboundAddEntityPacket p_217037_) { double d0 = p_217037_.getX(); double d1 = p_217037_.getY(); double d2 = p_217037_.getZ(); float f = p_217037_.getYRot(); float f1 = p_217037_.getXRot(); this.syncPacketPositionCodec(d0, d1, d2); this.yBodyRot = p_217037_.getYHeadRot(); this.yHeadRot = p_217037_.getYHeadRot(); this.yBodyRotO = this.yBodyRot; this.yHeadRotO = this.yHeadRot; this.setId(p_217037_.getId()); this.setUUID(p_217037_.getUUID()); this.absSnapTo(d0, d1, d2, f, f1); this.setDeltaMovement(p_217037_.getXa(), p_217037_.getYa(), p_217037_.getZa()); } public float getSecondsToDisableBlocking() { Weapon weapon = this.getWeaponItem().get(DataComponents.WEAPON); return weapon != null ? weapon.disableBlockingForSeconds() : 0.0F; } @Override public float maxUpStep() { float f = (float)this.getAttributeValue(Attributes.STEP_HEIGHT); return this.getControllingPassenger() instanceof Player ? Math.max(f, 1.0F) : f; } @Override public Vec3 getPassengerRidingPosition(Entity p_299288_) { return this.position().add(this.getPassengerAttachmentPoint(p_299288_, this.getDimensions(this.getPose()), this.getScale() * this.getAgeScale())); } protected void lerpHeadRotationStep(int p_297258_, double p_301409_) { this.yHeadRot = (float)Mth.rotLerp(1.0 / p_297258_, this.yHeadRot, p_301409_); } @Override public void igniteForTicks(int p_328356_) { super.igniteForTicks(Mth.ceil(p_328356_ * this.getAttributeValue(Attributes.BURNING_TIME))); } public boolean hasInfiniteMaterials() { return false; } public boolean isInvulnerableTo(ServerLevel p_361436_, DamageSource p_345519_) { return this.isInvulnerableToBase(p_345519_) || EnchantmentHelper.isImmuneToDamage(p_361436_, this, p_345519_); } public static boolean canGlideUsing(ItemStack p_369788_, EquipmentSlot p_365879_) { if (!p_369788_.has(DataComponents.GLIDER)) { return false; } else { Equippable equippable = p_369788_.get(DataComponents.EQUIPPABLE); return equippable != null && p_365879_ == equippable.slot() && !p_369788_.nextDamageWillBreak(); } } @VisibleForTesting public int getLastHurtByPlayerMemoryTime() { return this.lastHurtByPlayerMemoryTime; } public record Fallsounds(SoundEvent small, SoundEvent big) { } }