minecraft-src/net/minecraft/world/entity/player/Player.java
2025-07-04 03:45:38 +03:00

2185 lines
67 KiB
Java

package net.minecraft.world.entity.player;
import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.math.IntMath;
import com.mojang.authlib.GameProfile;
import com.mojang.datafixers.util.Either;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.function.Predicate;
import net.minecraft.Util;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.GlobalPos;
import net.minecraft.core.component.DataComponents;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.network.chat.ClickEvent;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.EntityDataSerializers;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
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.Stat;
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.util.Mth;
import net.minecraft.util.Unit;
import net.minecraft.world.Container;
import net.minecraft.world.Difficulty;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.effect.MobEffectUtil;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityAttachment;
import net.minecraft.world.entity.EntityAttachments;
import net.minecraft.world.entity.EntityDimensions;
import net.minecraft.world.entity.EntityEquipment;
import net.minecraft.world.entity.EntitySpawnReason;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.HumanoidArm;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.MoverType;
import net.minecraft.world.entity.Pose;
import net.minecraft.world.entity.SlotAccess;
import net.minecraft.world.entity.TamableAnimal;
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.entity.ai.attributes.AttributeSupplier.Builder;
import net.minecraft.world.entity.animal.Parrot;
import net.minecraft.world.entity.animal.horse.AbstractHorse;
import net.minecraft.world.entity.boss.EnderDragonPart;
import net.minecraft.world.entity.decoration.ArmorStand;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.monster.warden.WardenSpawnTracker;
import net.minecraft.world.entity.projectile.FishingHook;
import net.minecraft.world.entity.projectile.Projectile;
import net.minecraft.world.entity.projectile.ProjectileDeflection;
import net.minecraft.world.food.FoodData;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.ClickAction;
import net.minecraft.world.inventory.InventoryMenu;
import net.minecraft.world.inventory.PlayerEnderChestContainer;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemCooldowns;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.ProjectileWeaponItem;
import net.minecraft.world.item.component.BlocksAttacks;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.crafting.RecipeHolder;
import net.minecraft.world.item.enchantment.EnchantmentEffectComponents;
import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.item.equipment.Equippable;
import net.minecraft.world.item.trading.MerchantOffers;
import net.minecraft.world.level.BaseCommandBlock;
import net.minecraft.world.level.GameRules;
import net.minecraft.world.level.GameType;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.CommandBlockEntity;
import net.minecraft.world.level.block.entity.JigsawBlockEntity;
import net.minecraft.world.level.block.entity.SignBlockEntity;
import net.minecraft.world.level.block.entity.StructureBlockEntity;
import net.minecraft.world.level.block.entity.TestBlockEntity;
import net.minecraft.world.level.block.entity.TestInstanceBlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.pattern.BlockInWorld;
import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.level.gameevent.GameEvent.Context;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.scores.PlayerTeam;
import net.minecraft.world.scores.Scoreboard;
import net.minecraft.world.scores.Team;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class Player extends LivingEntity {
public static final HumanoidArm DEFAULT_MAIN_HAND = HumanoidArm.RIGHT;
public static final int DEFAULT_MODEL_CUSTOMIZATION = 0;
public static final int MAX_HEALTH = 20;
public static final int SLEEP_DURATION = 100;
public static final int WAKE_UP_DURATION = 10;
public static final int ENDER_SLOT_OFFSET = 200;
public static final int HELD_ITEM_SLOT = 499;
public static final int CRAFTING_SLOT_OFFSET = 500;
public static final float DEFAULT_BLOCK_INTERACTION_RANGE = 4.5F;
public static final float DEFAULT_ENTITY_INTERACTION_RANGE = 3.0F;
public static final float CROUCH_BB_HEIGHT = 1.5F;
public static final float SWIMMING_BB_WIDTH = 0.6F;
public static final float SWIMMING_BB_HEIGHT = 0.6F;
public static final float DEFAULT_EYE_HEIGHT = 1.62F;
private static final int CURRENT_IMPULSE_CONTEXT_RESET_GRACE_TIME_TICKS = 40;
public static final Vec3 DEFAULT_VEHICLE_ATTACHMENT = new Vec3(0.0, 0.6, 0.0);
public static final EntityDimensions STANDING_DIMENSIONS = EntityDimensions.scalable(0.6F, 1.8F)
.withEyeHeight(1.62F)
.withAttachments(EntityAttachments.builder().attach(EntityAttachment.VEHICLE, DEFAULT_VEHICLE_ATTACHMENT));
private static final Map<Pose, EntityDimensions> POSES = ImmutableMap.<Pose, EntityDimensions>builder()
.put(Pose.STANDING, STANDING_DIMENSIONS)
.put(Pose.SLEEPING, SLEEPING_DIMENSIONS)
.put(Pose.FALL_FLYING, EntityDimensions.scalable(0.6F, 0.6F).withEyeHeight(0.4F))
.put(Pose.SWIMMING, EntityDimensions.scalable(0.6F, 0.6F).withEyeHeight(0.4F))
.put(Pose.SPIN_ATTACK, EntityDimensions.scalable(0.6F, 0.6F).withEyeHeight(0.4F))
.put(
Pose.CROUCHING,
EntityDimensions.scalable(0.6F, 1.5F)
.withEyeHeight(1.27F)
.withAttachments(EntityAttachments.builder().attach(EntityAttachment.VEHICLE, DEFAULT_VEHICLE_ATTACHMENT))
)
.put(Pose.DYING, EntityDimensions.fixed(0.2F, 0.2F).withEyeHeight(1.62F))
.build();
private static final EntityDataAccessor<Float> DATA_PLAYER_ABSORPTION_ID = SynchedEntityData.defineId(Player.class, EntityDataSerializers.FLOAT);
private static final EntityDataAccessor<Integer> DATA_SCORE_ID = SynchedEntityData.defineId(Player.class, EntityDataSerializers.INT);
protected static final EntityDataAccessor<Byte> DATA_PLAYER_MODE_CUSTOMISATION = SynchedEntityData.defineId(Player.class, EntityDataSerializers.BYTE);
protected static final EntityDataAccessor<Byte> DATA_PLAYER_MAIN_HAND = SynchedEntityData.defineId(Player.class, EntityDataSerializers.BYTE);
protected static final EntityDataAccessor<CompoundTag> DATA_SHOULDER_LEFT = SynchedEntityData.defineId(Player.class, EntityDataSerializers.COMPOUND_TAG);
protected static final EntityDataAccessor<CompoundTag> DATA_SHOULDER_RIGHT = SynchedEntityData.defineId(Player.class, EntityDataSerializers.COMPOUND_TAG);
public static final int CLIENT_LOADED_TIMEOUT_TIME = 60;
private static final short DEFAULT_SLEEP_TIMER = 0;
private static final float DEFAULT_EXPERIENCE_PROGRESS = 0.0F;
private static final int DEFAULT_EXPERIENCE_LEVEL = 0;
private static final int DEFAULT_TOTAL_EXPERIENCE = 0;
private static final int NO_ENCHANTMENT_SEED = 0;
private static final int DEFAULT_SELECTED_SLOT = 0;
private static final int DEFAULT_SCORE = 0;
private static final boolean DEFAULT_IGNORE_FALL_DAMAGE_FROM_CURRENT_IMPULSE = false;
private static final int DEFAULT_CURRENT_IMPULSE_CONTEXT_RESET_GRACE_TIME = 0;
private long timeEntitySatOnShoulder;
final Inventory inventory;
protected PlayerEnderChestContainer enderChestInventory = new PlayerEnderChestContainer();
public final InventoryMenu inventoryMenu;
public AbstractContainerMenu containerMenu;
protected FoodData foodData = new FoodData();
protected int jumpTriggerTime;
private boolean clientLoaded = false;
protected int clientLoadedTimeoutTimer = 60;
public float oBob;
public float bob;
public int takeXpDelay;
public double xCloakO;
public double yCloakO;
public double zCloakO;
public double xCloak;
public double yCloak;
public double zCloak;
private int sleepCounter = 0;
protected boolean wasUnderwater;
private final Abilities abilities = new Abilities();
public int experienceLevel = 0;
public int totalExperience = 0;
public float experienceProgress = 0.0F;
protected int enchantmentSeed = 0;
protected final float defaultFlySpeed = 0.02F;
private int lastLevelUpTime;
/**
* The player's unique game profile
*/
private final GameProfile gameProfile;
private boolean reducedDebugInfo;
private ItemStack lastItemInMainHand = ItemStack.EMPTY;
private final ItemCooldowns cooldowns = this.createItemCooldowns();
private Optional<GlobalPos> lastDeathLocation = Optional.empty();
@Nullable
public FishingHook fishing;
protected float hurtDir;
@Nullable
public Vec3 currentImpulseImpactPos;
@Nullable
public Entity currentExplosionCause;
private boolean ignoreFallDamageFromCurrentImpulse = false;
private int currentImpulseContextResetGraceTime = 0;
public Player(Level level, BlockPos pos, float yRot, GameProfile gameProfile) {
super(EntityType.PLAYER, level);
this.setUUID(gameProfile.getId());
this.gameProfile = gameProfile;
this.inventory = new Inventory(this, this.equipment);
this.inventoryMenu = new InventoryMenu(this.inventory, !level.isClientSide, this);
this.containerMenu = this.inventoryMenu;
this.snapTo(pos.getX() + 0.5, pos.getY() + 1, pos.getZ() + 0.5, yRot, 0.0F);
}
@Override
protected EntityEquipment createEquipment() {
return new PlayerEquipment(this);
}
public boolean blockActionRestricted(Level level, BlockPos pos, GameType gameMode) {
if (!gameMode.isBlockPlacingRestricted()) {
return false;
} else if (gameMode == GameType.SPECTATOR) {
return true;
} else if (this.mayBuild()) {
return false;
} else {
ItemStack itemStack = this.getMainHandItem();
return itemStack.isEmpty() || !itemStack.canBreakBlockInAdventureMode(new BlockInWorld(level, pos, false));
}
}
public static Builder createAttributes() {
return LivingEntity.createLivingAttributes()
.add(Attributes.ATTACK_DAMAGE, 1.0)
.add(Attributes.MOVEMENT_SPEED, 0.1F)
.add(Attributes.ATTACK_SPEED)
.add(Attributes.LUCK)
.add(Attributes.BLOCK_INTERACTION_RANGE, 4.5)
.add(Attributes.ENTITY_INTERACTION_RANGE, 3.0)
.add(Attributes.BLOCK_BREAK_SPEED)
.add(Attributes.SUBMERGED_MINING_SPEED)
.add(Attributes.SNEAKING_SPEED)
.add(Attributes.MINING_EFFICIENCY)
.add(Attributes.SWEEPING_DAMAGE_RATIO);
}
@Override
protected void defineSynchedData(net.minecraft.network.syncher.SynchedEntityData.Builder builder) {
super.defineSynchedData(builder);
builder.define(DATA_PLAYER_ABSORPTION_ID, 0.0F);
builder.define(DATA_SCORE_ID, 0);
builder.define(DATA_PLAYER_MODE_CUSTOMISATION, (byte)0);
builder.define(DATA_PLAYER_MAIN_HAND, (byte)DEFAULT_MAIN_HAND.getId());
builder.define(DATA_SHOULDER_LEFT, new CompoundTag());
builder.define(DATA_SHOULDER_RIGHT, new CompoundTag());
}
@Override
public void tick() {
this.noPhysics = this.isSpectator();
if (this.isSpectator() || this.isPassenger()) {
this.setOnGround(false);
}
if (this.takeXpDelay > 0) {
this.takeXpDelay--;
}
if (this.isSleeping()) {
this.sleepCounter++;
if (this.sleepCounter > 100) {
this.sleepCounter = 100;
}
if (!this.level().isClientSide && this.level().isBrightOutside()) {
this.stopSleepInBed(false, true);
}
} else if (this.sleepCounter > 0) {
this.sleepCounter++;
if (this.sleepCounter >= 110) {
this.sleepCounter = 0;
}
}
this.updateIsUnderwater();
super.tick();
if (!this.level().isClientSide && this.containerMenu != null && !this.containerMenu.stillValid(this)) {
this.closeContainer();
this.containerMenu = this.inventoryMenu;
}
this.moveCloak();
if (this instanceof ServerPlayer serverPlayer) {
this.foodData.tick(serverPlayer);
this.awardStat(Stats.PLAY_TIME);
this.awardStat(Stats.TOTAL_WORLD_TIME);
if (this.isAlive()) {
this.awardStat(Stats.TIME_SINCE_DEATH);
}
if (this.isDiscrete()) {
this.awardStat(Stats.CROUCH_TIME);
}
if (!this.isSleeping()) {
this.awardStat(Stats.TIME_SINCE_REST);
}
}
int i = 29999999;
double d = Mth.clamp(this.getX(), -2.9999999E7, 2.9999999E7);
double e = Mth.clamp(this.getZ(), -2.9999999E7, 2.9999999E7);
if (d != this.getX() || e != this.getZ()) {
this.setPos(d, this.getY(), e);
}
this.attackStrengthTicker++;
ItemStack itemStack = this.getMainHandItem();
if (!ItemStack.matches(this.lastItemInMainHand, itemStack)) {
if (!ItemStack.isSameItem(this.lastItemInMainHand, itemStack)) {
this.resetAttackStrengthTicker();
}
this.lastItemInMainHand = itemStack.copy();
}
if (!this.isEyeInFluid(FluidTags.WATER) && this.isEquipped(Items.TURTLE_HELMET)) {
this.turtleHelmetTick();
}
this.cooldowns.tick();
this.updatePlayerPose();
if (this.currentImpulseContextResetGraceTime > 0) {
this.currentImpulseContextResetGraceTime--;
}
}
@Override
protected float getMaxHeadRotationRelativeToBody() {
return this.isBlocking() ? 15.0F : super.getMaxHeadRotationRelativeToBody();
}
public boolean isSecondaryUseActive() {
return this.isShiftKeyDown();
}
protected boolean wantsToStopRiding() {
return this.isShiftKeyDown();
}
protected boolean isStayingOnGroundSurface() {
return this.isShiftKeyDown();
}
protected boolean updateIsUnderwater() {
this.wasUnderwater = this.isEyeInFluid(FluidTags.WATER);
return this.wasUnderwater;
}
@Override
public void onAboveBubbleColumn(boolean downwards, BlockPos pos) {
if (!this.getAbilities().flying) {
super.onAboveBubbleColumn(downwards, pos);
}
}
@Override
public void onInsideBubbleColumn(boolean downwards) {
if (!this.getAbilities().flying) {
super.onInsideBubbleColumn(downwards);
}
}
private void turtleHelmetTick() {
this.addEffect(new MobEffectInstance(MobEffects.WATER_BREATHING, 200, 0, false, false, true));
}
private boolean isEquipped(Item item) {
for (EquipmentSlot equipmentSlot : EquipmentSlot.VALUES) {
ItemStack itemStack = this.getItemBySlot(equipmentSlot);
Equippable equippable = itemStack.get(DataComponents.EQUIPPABLE);
if (itemStack.is(item) && equippable != null && equippable.slot() == equipmentSlot) {
return true;
}
}
return false;
}
protected ItemCooldowns createItemCooldowns() {
return new ItemCooldowns();
}
private void moveCloak() {
this.xCloakO = this.xCloak;
this.yCloakO = this.yCloak;
this.zCloakO = this.zCloak;
double d = this.getX() - this.xCloak;
double e = this.getY() - this.yCloak;
double f = this.getZ() - this.zCloak;
double g = 10.0;
if (d > 10.0) {
this.xCloak = this.getX();
this.xCloakO = this.xCloak;
}
if (f > 10.0) {
this.zCloak = this.getZ();
this.zCloakO = this.zCloak;
}
if (e > 10.0) {
this.yCloak = this.getY();
this.yCloakO = this.yCloak;
}
if (d < -10.0) {
this.xCloak = this.getX();
this.xCloakO = this.xCloak;
}
if (f < -10.0) {
this.zCloak = this.getZ();
this.zCloakO = this.zCloak;
}
if (e < -10.0) {
this.yCloak = this.getY();
this.yCloakO = this.yCloak;
}
this.xCloak += d * 0.25;
this.zCloak += f * 0.25;
this.yCloak += e * 0.25;
}
protected void updatePlayerPose() {
if (this.canPlayerFitWithinBlocksAndEntitiesWhen(Pose.SWIMMING)) {
Pose pose = this.getDesiredPose();
Pose pose2;
if (this.isSpectator() || this.isPassenger() || this.canPlayerFitWithinBlocksAndEntitiesWhen(pose)) {
pose2 = pose;
} else if (this.canPlayerFitWithinBlocksAndEntitiesWhen(Pose.CROUCHING)) {
pose2 = Pose.CROUCHING;
} else {
pose2 = Pose.SWIMMING;
}
this.setPose(pose2);
}
}
private Pose getDesiredPose() {
if (this.isSleeping()) {
return Pose.SLEEPING;
} else if (this.isSwimming()) {
return Pose.SWIMMING;
} else if (this.isFallFlying()) {
return Pose.FALL_FLYING;
} else if (this.isAutoSpinAttack()) {
return Pose.SPIN_ATTACK;
} else {
return this.isShiftKeyDown() && !this.abilities.flying ? Pose.CROUCHING : Pose.STANDING;
}
}
protected boolean canPlayerFitWithinBlocksAndEntitiesWhen(Pose pose) {
return this.level().noCollision(this, this.getDimensions(pose).makeBoundingBox(this.position()).deflate(1.0E-7));
}
@Override
protected SoundEvent getSwimSound() {
return SoundEvents.PLAYER_SWIM;
}
@Override
protected SoundEvent getSwimSplashSound() {
return SoundEvents.PLAYER_SPLASH;
}
@Override
protected SoundEvent getSwimHighSpeedSplashSound() {
return SoundEvents.PLAYER_SPLASH_HIGH_SPEED;
}
@Override
public int getDimensionChangingDelay() {
return 10;
}
@Override
public void playSound(SoundEvent sound, float volume, float pitch) {
this.level().playSound(this, this.getX(), this.getY(), this.getZ(), sound, this.getSoundSource(), volume, pitch);
}
public void playNotifySound(SoundEvent sound, SoundSource source, float volume, float pitch) {
}
@Override
public SoundSource getSoundSource() {
return SoundSource.PLAYERS;
}
@Override
protected int getFireImmuneTicks() {
return 20;
}
@Override
public void handleEntityEvent(byte id) {
if (id == 9) {
this.completeUsingItem();
} else if (id == 23) {
this.reducedDebugInfo = false;
} else if (id == 22) {
this.reducedDebugInfo = true;
} else {
super.handleEntityEvent(id);
}
}
/**
* Sets the current crafting inventory back to the 2x2 square.
*/
protected void closeContainer() {
this.containerMenu = this.inventoryMenu;
}
protected void doCloseContainer() {
}
@Override
public void rideTick() {
if (!this.level().isClientSide && this.wantsToStopRiding() && this.isPassenger()) {
this.stopRiding();
this.setShiftKeyDown(false);
} else {
super.rideTick();
this.oBob = this.bob;
this.bob = 0.0F;
}
}
@Override
public void aiStep() {
if (this.jumpTriggerTime > 0) {
this.jumpTriggerTime--;
}
this.tickRegeneration();
this.inventory.tick();
this.oBob = this.bob;
if (this.abilities.flying && !this.isPassenger()) {
this.resetFallDistance();
}
super.aiStep();
this.updateSwingTime();
this.yHeadRot = this.getYRot();
this.setSpeed((float)this.getAttributeValue(Attributes.MOVEMENT_SPEED));
float f;
if (this.onGround() && !this.isDeadOrDying() && !this.isSwimming()) {
f = Math.min(0.1F, (float)this.getDeltaMovement().horizontalDistance());
} else {
f = 0.0F;
}
this.bob = this.bob + (f - this.bob) * 0.4F;
if (this.getHealth() > 0.0F && !this.isSpectator()) {
AABB aABB;
if (this.isPassenger() && !this.getVehicle().isRemoved()) {
aABB = this.getBoundingBox().minmax(this.getVehicle().getBoundingBox()).inflate(1.0, 0.0, 1.0);
} else {
aABB = this.getBoundingBox().inflate(1.0, 0.5, 1.0);
}
List<Entity> list = this.level().getEntities(this, aABB);
List<Entity> list2 = Lists.<Entity>newArrayList();
for (Entity entity : list) {
if (entity.getType() == EntityType.EXPERIENCE_ORB) {
list2.add(entity);
} else if (!entity.isRemoved()) {
this.touch(entity);
}
}
if (!list2.isEmpty()) {
this.touch(Util.getRandom(list2, this.random));
}
}
this.playShoulderEntityAmbientSound(this.getShoulderEntityLeft());
this.playShoulderEntityAmbientSound(this.getShoulderEntityRight());
if (!this.level().isClientSide && (this.fallDistance > 0.5 || this.isInWater()) || this.abilities.flying || this.isSleeping() || this.isInPowderSnow) {
this.removeEntitiesOnShoulder();
}
}
protected void tickRegeneration() {
}
private void playShoulderEntityAmbientSound(CompoundTag entityCompound) {
if (!entityCompound.isEmpty() && !entityCompound.getBooleanOr("Silent", false)) {
if (this.level().random.nextInt(200) == 0) {
EntityType<?> entityType = (EntityType<?>)entityCompound.read("id", EntityType.CODEC).orElse(null);
if (entityType == EntityType.PARROT && !Parrot.imitateNearbyMobs(this.level(), this)) {
this.level()
.playSound(
null,
this.getX(),
this.getY(),
this.getZ(),
Parrot.getAmbient(this.level(), this.level().random),
this.getSoundSource(),
1.0F,
Parrot.getPitch(this.level().random)
);
}
}
}
}
private void touch(Entity entity) {
entity.playerTouch(this);
}
public int getScore() {
return this.entityData.get(DATA_SCORE_ID);
}
/**
* Set player's score
*/
public void setScore(int score) {
this.entityData.set(DATA_SCORE_ID, score);
}
/**
* Add to player's score
*/
public void increaseScore(int score) {
int i = this.getScore();
this.entityData.set(DATA_SCORE_ID, i + score);
}
public void startAutoSpinAttack(int ticks, float damage, ItemStack itemStack) {
this.autoSpinAttackTicks = ticks;
this.autoSpinAttackDmg = damage;
this.autoSpinAttackItemStack = itemStack;
if (!this.level().isClientSide) {
this.removeEntitiesOnShoulder();
this.setLivingEntityFlag(4, true);
}
}
@NotNull
@Override
public ItemStack getWeaponItem() {
return this.isAutoSpinAttack() && this.autoSpinAttackItemStack != null ? this.autoSpinAttackItemStack : super.getWeaponItem();
}
@Override
public void die(DamageSource damageSource) {
super.die(damageSource);
this.reapplyPosition();
if (!this.isSpectator() && this.level() instanceof ServerLevel serverLevel) {
this.dropAllDeathLoot(serverLevel, damageSource);
}
if (damageSource != null) {
this.setDeltaMovement(
-Mth.cos((this.getHurtDir() + this.getYRot()) * (float) (Math.PI / 180.0)) * 0.1F,
0.1F,
-Mth.sin((this.getHurtDir() + this.getYRot()) * (float) (Math.PI / 180.0)) * 0.1F
);
} else {
this.setDeltaMovement(0.0, 0.1, 0.0);
}
this.awardStat(Stats.DEATHS);
this.resetStat(Stats.CUSTOM.get(Stats.TIME_SINCE_DEATH));
this.resetStat(Stats.CUSTOM.get(Stats.TIME_SINCE_REST));
this.clearFire();
this.setSharedFlagOnFire(false);
this.setLastDeathLocation(Optional.of(GlobalPos.of(this.level().dimension(), this.blockPosition())));
}
@Override
protected void dropEquipment(ServerLevel level) {
super.dropEquipment(level);
if (!level.getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY)) {
this.destroyVanishingCursedItems();
this.inventory.dropAll();
}
}
protected void destroyVanishingCursedItems() {
for (int i = 0; i < this.inventory.getContainerSize(); i++) {
ItemStack itemStack = this.inventory.getItem(i);
if (!itemStack.isEmpty() && EnchantmentHelper.has(itemStack, EnchantmentEffectComponents.PREVENT_EQUIPMENT_DROP)) {
this.inventory.removeItemNoUpdate(i);
}
}
}
@Override
protected SoundEvent getHurtSound(DamageSource damageSource) {
return damageSource.type().effects().sound();
}
@Override
protected SoundEvent getDeathSound() {
return SoundEvents.PLAYER_DEATH;
}
public void handleCreativeModeItemDrop(ItemStack stack) {
}
/**
* Drops an item into the world.
*/
@Nullable
public ItemEntity drop(ItemStack itemStack, boolean includeThrowerName) {
return this.drop(itemStack, false, includeThrowerName);
}
public float getDestroySpeed(BlockState state) {
float f = this.inventory.getSelectedItem().getDestroySpeed(state);
if (f > 1.0F) {
f += (float)this.getAttributeValue(Attributes.MINING_EFFICIENCY);
}
if (MobEffectUtil.hasDigSpeed(this)) {
f *= 1.0F + (MobEffectUtil.getDigSpeedAmplification(this) + 1) * 0.2F;
}
if (this.hasEffect(MobEffects.MINING_FATIGUE)) {
float g = switch (this.getEffect(MobEffects.MINING_FATIGUE).getAmplifier()) {
case 0 -> 0.3F;
case 1 -> 0.09F;
case 2 -> 0.0027F;
default -> 8.1E-4F;
};
f *= g;
}
f *= (float)this.getAttributeValue(Attributes.BLOCK_BREAK_SPEED);
if (this.isEyeInFluid(FluidTags.WATER)) {
f *= (float)this.getAttribute(Attributes.SUBMERGED_MINING_SPEED).getValue();
}
if (!this.onGround()) {
f /= 5.0F;
}
return f;
}
public boolean hasCorrectToolForDrops(BlockState state) {
return !state.requiresCorrectToolForDrops() || this.inventory.getSelectedItem().isCorrectToolForDrops(state);
}
@Override
public void readAdditionalSaveData(CompoundTag tag) {
super.readAdditionalSaveData(tag);
this.setUUID(this.gameProfile.getId());
ListTag listTag = tag.getListOrEmpty("Inventory");
this.inventory.load(listTag);
this.inventory.setSelectedSlot(tag.getIntOr("SelectedItemSlot", 0));
this.sleepCounter = tag.getShortOr("SleepTimer", (short)0);
this.experienceProgress = tag.getFloatOr("XpP", 0.0F);
this.experienceLevel = tag.getIntOr("XpLevel", 0);
this.totalExperience = tag.getIntOr("XpTotal", 0);
this.enchantmentSeed = tag.getIntOr("XpSeed", 0);
if (this.enchantmentSeed == 0) {
this.enchantmentSeed = this.random.nextInt();
}
this.setScore(tag.getIntOr("Score", 0));
this.foodData.readAdditionalSaveData(tag);
this.abilities.loadSaveData(tag);
this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(this.abilities.getWalkingSpeed());
tag.getList("EnderItems").ifPresent(listTagx -> this.enderChestInventory.fromTag(listTagx, this.registryAccess()));
this.setShoulderEntityLeft(tag.getCompoundOrEmpty("ShoulderEntityLeft"));
this.setShoulderEntityRight(tag.getCompoundOrEmpty("ShoulderEntityRight"));
this.setLastDeathLocation(tag.read("LastDeathLocation", GlobalPos.CODEC));
this.currentImpulseImpactPos = (Vec3)tag.read("current_explosion_impact_pos", Vec3.CODEC).orElse(null);
this.ignoreFallDamageFromCurrentImpulse = tag.getBooleanOr("ignore_fall_damage_from_current_explosion", false);
this.currentImpulseContextResetGraceTime = tag.getIntOr("current_impulse_context_reset_grace_time", 0);
}
@Override
public void addAdditionalSaveData(CompoundTag tag) {
super.addAdditionalSaveData(tag);
NbtUtils.addCurrentDataVersion(tag);
tag.put("Inventory", this.inventory.save(new ListTag()));
tag.putInt("SelectedItemSlot", this.inventory.getSelectedSlot());
tag.putShort("SleepTimer", (short)this.sleepCounter);
tag.putFloat("XpP", this.experienceProgress);
tag.putInt("XpLevel", this.experienceLevel);
tag.putInt("XpTotal", this.totalExperience);
tag.putInt("XpSeed", this.enchantmentSeed);
tag.putInt("Score", this.getScore());
this.foodData.addAdditionalSaveData(tag);
this.abilities.addSaveData(tag);
tag.put("EnderItems", this.enderChestInventory.createTag(this.registryAccess()));
if (!this.getShoulderEntityLeft().isEmpty()) {
tag.put("ShoulderEntityLeft", this.getShoulderEntityLeft());
}
if (!this.getShoulderEntityRight().isEmpty()) {
tag.put("ShoulderEntityRight", this.getShoulderEntityRight());
}
this.lastDeathLocation.ifPresent(globalPos -> tag.store("LastDeathLocation", GlobalPos.CODEC, globalPos));
tag.storeNullable("current_explosion_impact_pos", Vec3.CODEC, this.currentImpulseImpactPos);
tag.putBoolean("ignore_fall_damage_from_current_explosion", this.ignoreFallDamageFromCurrentImpulse);
tag.putInt("current_impulse_context_reset_grace_time", this.currentImpulseContextResetGraceTime);
}
@Override
public boolean isInvulnerableTo(ServerLevel level, DamageSource damageSource) {
if (super.isInvulnerableTo(level, damageSource)) {
return true;
} else if (damageSource.is(DamageTypeTags.IS_DROWNING)) {
return !level.getGameRules().getBoolean(GameRules.RULE_DROWNING_DAMAGE);
} else if (damageSource.is(DamageTypeTags.IS_FALL)) {
return !level.getGameRules().getBoolean(GameRules.RULE_FALL_DAMAGE);
} else if (damageSource.is(DamageTypeTags.IS_FIRE)) {
return !level.getGameRules().getBoolean(GameRules.RULE_FIRE_DAMAGE);
} else {
return damageSource.is(DamageTypeTags.IS_FREEZING) ? !level.getGameRules().getBoolean(GameRules.RULE_FREEZE_DAMAGE) : false;
}
}
@Override
public boolean hurtServer(ServerLevel level, DamageSource damageSource, float amount) {
if (this.isInvulnerableTo(level, damageSource)) {
return false;
} else if (this.abilities.invulnerable && !damageSource.is(DamageTypeTags.BYPASSES_INVULNERABILITY)) {
return false;
} else {
this.noActionTime = 0;
if (this.isDeadOrDying()) {
return false;
} else {
this.removeEntitiesOnShoulder();
if (damageSource.scalesWithDifficulty()) {
if (level.getDifficulty() == Difficulty.PEACEFUL) {
amount = 0.0F;
}
if (level.getDifficulty() == Difficulty.EASY) {
amount = Math.min(amount / 2.0F + 1.0F, amount);
}
if (level.getDifficulty() == Difficulty.HARD) {
amount = amount * 3.0F / 2.0F;
}
}
return amount == 0.0F ? false : super.hurtServer(level, damageSource, amount);
}
}
}
@Override
protected void blockUsingItem(ServerLevel level, LivingEntity entity) {
super.blockUsingItem(level, entity);
ItemStack itemStack = this.getItemBlockingWith();
BlocksAttacks blocksAttacks = itemStack != null ? itemStack.get(DataComponents.BLOCKS_ATTACKS) : null;
float f = entity.getSecondsToDisableBlocking();
if (f > 0.0F && blocksAttacks != null) {
blocksAttacks.disable(level, this, f, itemStack);
}
}
@Override
public boolean canBeSeenAsEnemy() {
return !this.getAbilities().invulnerable && super.canBeSeenAsEnemy();
}
public boolean canHarmPlayer(Player other) {
Team team = this.getTeam();
Team team2 = other.getTeam();
if (team == null) {
return true;
} else {
return !team.isAlliedTo(team2) ? true : team.isAllowFriendlyFire();
}
}
@Override
protected void hurtArmor(DamageSource damageSource, float damageAmount) {
this.doHurtEquipment(damageSource, damageAmount, new EquipmentSlot[]{EquipmentSlot.FEET, EquipmentSlot.LEGS, EquipmentSlot.CHEST, EquipmentSlot.HEAD});
}
@Override
protected void hurtHelmet(DamageSource damageSource, float damageAmount) {
this.doHurtEquipment(damageSource, damageAmount, new EquipmentSlot[]{EquipmentSlot.HEAD});
}
@Override
protected void actuallyHurt(ServerLevel level, DamageSource damageSource, float amount) {
if (!this.isInvulnerableTo(level, damageSource)) {
amount = this.getDamageAfterArmorAbsorb(damageSource, amount);
amount = this.getDamageAfterMagicAbsorb(damageSource, amount);
float var8 = Math.max(amount - this.getAbsorptionAmount(), 0.0F);
this.setAbsorptionAmount(this.getAbsorptionAmount() - (amount - var8));
float g = amount - var8;
if (g > 0.0F && g < 3.4028235E37F) {
this.awardStat(Stats.DAMAGE_ABSORBED, Math.round(g * 10.0F));
}
if (var8 != 0.0F) {
this.causeFoodExhaustion(damageSource.getFoodExhaustion());
this.getCombatTracker().recordDamage(damageSource, var8);
this.setHealth(this.getHealth() - var8);
if (var8 < 3.4028235E37F) {
this.awardStat(Stats.DAMAGE_TAKEN, Math.round(var8 * 10.0F));
}
this.gameEvent(GameEvent.ENTITY_DAMAGE);
}
}
}
public boolean isTextFilteringEnabled() {
return false;
}
public void openTextEdit(SignBlockEntity signEntity, boolean isFrontText) {
}
public void openMinecartCommandBlock(BaseCommandBlock commandEntity) {
}
public void openCommandBlock(CommandBlockEntity commandBlockEntity) {
}
public void openStructureBlock(StructureBlockEntity structureEntity) {
}
public void openTestBlock(TestBlockEntity testBlockEntity) {
}
public void openTestInstanceBlock(TestInstanceBlockEntity testInstanceBlockEntity) {
}
public void openJigsawBlock(JigsawBlockEntity jigsawBlockEntity) {
}
public void openHorseInventory(AbstractHorse horse, Container inventory) {
}
public OptionalInt openMenu(@Nullable MenuProvider menu) {
return OptionalInt.empty();
}
public void sendMerchantOffers(int containerId, MerchantOffers offers, int villagerLevel, int villagerXp, boolean showProgress, boolean canRestock) {
}
public void openItemGui(ItemStack stack, InteractionHand hand) {
}
public InteractionResult interactOn(Entity entityToInteractOn, InteractionHand hand) {
if (this.isSpectator()) {
if (entityToInteractOn instanceof MenuProvider) {
this.openMenu((MenuProvider)entityToInteractOn);
}
return InteractionResult.PASS;
} else {
ItemStack itemStack = this.getItemInHand(hand);
ItemStack itemStack2 = itemStack.copy();
InteractionResult interactionResult = entityToInteractOn.interact(this, hand);
if (interactionResult.consumesAction()) {
if (this.hasInfiniteMaterials() && itemStack == this.getItemInHand(hand) && itemStack.getCount() < itemStack2.getCount()) {
itemStack.setCount(itemStack2.getCount());
}
return interactionResult;
} else {
if (!itemStack.isEmpty() && entityToInteractOn instanceof LivingEntity) {
if (this.hasInfiniteMaterials()) {
itemStack = itemStack2;
}
InteractionResult interactionResult2 = itemStack.interactLivingEntity(this, (LivingEntity)entityToInteractOn, hand);
if (interactionResult2.consumesAction()) {
this.level().gameEvent(GameEvent.ENTITY_INTERACT, entityToInteractOn.position(), Context.of(this));
if (itemStack.isEmpty() && !this.hasInfiniteMaterials()) {
this.setItemInHand(hand, ItemStack.EMPTY);
}
return interactionResult2;
}
}
return InteractionResult.PASS;
}
}
}
@Override
public void removeVehicle() {
super.removeVehicle();
this.boardingCooldown = 0;
}
@Override
protected boolean isImmobile() {
return super.isImmobile() || this.isSleeping();
}
@Override
public boolean isAffectedByFluids() {
return !this.abilities.flying;
}
@Override
protected Vec3 maybeBackOffFromEdge(Vec3 vec, MoverType mover) {
float f = this.maxUpStep();
if (!this.abilities.flying
&& !(vec.y > 0.0)
&& (mover == MoverType.SELF || mover == MoverType.PLAYER)
&& this.isStayingOnGroundSurface()
&& this.isAboveGround(f)) {
double d = vec.x;
double e = vec.z;
double g = 0.05;
double h = Math.signum(d) * 0.05;
double i;
for (i = Math.signum(e) * 0.05; d != 0.0 && this.canFallAtLeast(d, 0.0, f); d -= h) {
if (Math.abs(d) <= 0.05) {
d = 0.0;
break;
}
}
while (e != 0.0 && this.canFallAtLeast(0.0, e, f)) {
if (Math.abs(e) <= 0.05) {
e = 0.0;
break;
}
e -= i;
}
while (d != 0.0 && e != 0.0 && this.canFallAtLeast(d, e, f)) {
if (Math.abs(d) <= 0.05) {
d = 0.0;
} else {
d -= h;
}
if (Math.abs(e) <= 0.05) {
e = 0.0;
} else {
e -= i;
}
}
return new Vec3(d, vec.y, e);
} else {
return vec;
}
}
private boolean isAboveGround(float maxUpStep) {
return this.onGround() || this.fallDistance < maxUpStep && !this.canFallAtLeast(0.0, 0.0, maxUpStep - this.fallDistance);
}
private boolean canFallAtLeast(double x, double z, double distance) {
AABB aABB = this.getBoundingBox();
return this.level()
.noCollision(
this, new AABB(aABB.minX + 1.0E-7 + x, aABB.minY - distance - 1.0E-7, aABB.minZ + 1.0E-7 + z, aABB.maxX - 1.0E-7 + x, aABB.minY, aABB.maxZ - 1.0E-7 + z)
);
}
/**
* Attacks for the player the targeted entity with the currently equipped item. The equipped item has hitEntity called on it. Args: targetEntity
*/
public void attack(Entity target) {
if (target.isAttackable()) {
if (!target.skipAttackInteraction(this)) {
float f = this.isAutoSpinAttack() ? this.autoSpinAttackDmg : (float)this.getAttributeValue(Attributes.ATTACK_DAMAGE);
ItemStack itemStack = this.getWeaponItem();
DamageSource damageSource = (DamageSource)Optional.ofNullable(itemStack.getItem().getDamageSource(this)).orElse(this.damageSources().playerAttack(this));
float g = this.getEnchantedDamage(target, f, damageSource) - f;
float h = this.getAttackStrengthScale(0.5F);
f *= 0.2F + h * h * 0.8F;
g *= h;
this.resetAttackStrengthTicker();
if (target.getType().is(EntityTypeTags.REDIRECTABLE_PROJECTILE)
&& target instanceof Projectile projectile
&& projectile.deflect(ProjectileDeflection.AIM_DEFLECT, this, this, true)) {
this.level().playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_NODAMAGE, this.getSoundSource());
} else {
if (f > 0.0F || g > 0.0F) {
boolean bl = h > 0.9F;
boolean bl2;
if (this.isSprinting() && bl) {
this.level().playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_KNOCKBACK, this.getSoundSource(), 1.0F, 1.0F);
bl2 = true;
} else {
bl2 = false;
}
f += itemStack.getItem().getAttackDamageBonus(target, f, damageSource);
boolean bl3 = bl
&& this.fallDistance > 0.0
&& !this.onGround()
&& !this.onClimbable()
&& !this.isInWater()
&& !this.hasEffect(MobEffects.BLINDNESS)
&& !this.isPassenger()
&& target instanceof LivingEntity
&& !this.isSprinting();
if (bl3) {
f *= 1.5F;
}
float i = f + g;
boolean bl4 = false;
if (bl && !bl3 && !bl2 && this.onGround()) {
double d = this.getKnownMovement().horizontalDistanceSqr();
double e = this.getSpeed() * 2.5;
if (d < Mth.square(e) && this.getItemInHand(InteractionHand.MAIN_HAND).is(ItemTags.SWORDS)) {
bl4 = true;
}
}
float j = 0.0F;
if (target instanceof LivingEntity livingEntity) {
j = livingEntity.getHealth();
}
Vec3 vec3 = target.getDeltaMovement();
boolean bl5 = target.hurtOrSimulate(damageSource, i);
if (bl5) {
float k = this.getKnockback(target, damageSource) + (bl2 ? 1.0F : 0.0F);
if (k > 0.0F) {
if (target instanceof LivingEntity livingEntity2) {
livingEntity2.knockback(k * 0.5F, Mth.sin(this.getYRot() * (float) (Math.PI / 180.0)), -Mth.cos(this.getYRot() * (float) (Math.PI / 180.0)));
} else {
target.push(-Mth.sin(this.getYRot() * (float) (Math.PI / 180.0)) * k * 0.5F, 0.1, Mth.cos(this.getYRot() * (float) (Math.PI / 180.0)) * k * 0.5F);
}
this.setDeltaMovement(this.getDeltaMovement().multiply(0.6, 1.0, 0.6));
this.setSprinting(false);
}
if (bl4) {
float l = 1.0F + (float)this.getAttributeValue(Attributes.SWEEPING_DAMAGE_RATIO) * f;
for (LivingEntity livingEntity3 : this.level().getEntitiesOfClass(LivingEntity.class, target.getBoundingBox().inflate(1.0, 0.25, 1.0))) {
if (livingEntity3 != this
&& livingEntity3 != target
&& !this.isAlliedTo(livingEntity3)
&& !(livingEntity3 instanceof ArmorStand armorStand && armorStand.isMarker())
&& this.distanceToSqr(livingEntity3) < 9.0) {
float m = this.getEnchantedDamage(livingEntity3, l, damageSource) * h;
if (this.level() instanceof ServerLevel serverLevel && livingEntity3.hurtServer(serverLevel, damageSource, m)) {
livingEntity3.knockback(0.4F, Mth.sin(this.getYRot() * (float) (Math.PI / 180.0)), -Mth.cos(this.getYRot() * (float) (Math.PI / 180.0)));
EnchantmentHelper.doPostAttackEffects(serverLevel, livingEntity3, damageSource);
}
}
}
this.level().playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_SWEEP, this.getSoundSource(), 1.0F, 1.0F);
this.sweepAttack();
}
if (target instanceof ServerPlayer && target.hurtMarked) {
((ServerPlayer)target).connection.send(new ClientboundSetEntityMotionPacket(target));
target.hurtMarked = false;
target.setDeltaMovement(vec3);
}
if (bl3) {
this.level().playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_CRIT, this.getSoundSource(), 1.0F, 1.0F);
this.crit(target);
}
if (!bl3 && !bl4) {
if (bl) {
this.level().playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_STRONG, this.getSoundSource(), 1.0F, 1.0F);
} else {
this.level().playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_WEAK, this.getSoundSource(), 1.0F, 1.0F);
}
}
if (g > 0.0F) {
this.magicCrit(target);
}
this.setLastHurtMob(target);
Entity entity = target;
if (target instanceof EnderDragonPart) {
entity = ((EnderDragonPart)target).parentMob;
}
boolean bl6 = false;
if (this.level() instanceof ServerLevel serverLevel2) {
if (entity instanceof LivingEntity livingEntity3x) {
bl6 = itemStack.hurtEnemy(livingEntity3x, this);
}
EnchantmentHelper.doPostAttackEffects(serverLevel2, target, damageSource);
}
if (!this.level().isClientSide && !itemStack.isEmpty() && entity instanceof LivingEntity) {
if (bl6) {
itemStack.postHurtEnemy((LivingEntity)entity, this);
}
if (itemStack.isEmpty()) {
if (itemStack == this.getMainHandItem()) {
this.setItemInHand(InteractionHand.MAIN_HAND, ItemStack.EMPTY);
} else {
this.setItemInHand(InteractionHand.OFF_HAND, ItemStack.EMPTY);
}
}
}
if (target instanceof LivingEntity) {
float n = j - ((LivingEntity)target).getHealth();
this.awardStat(Stats.DAMAGE_DEALT, Math.round(n * 10.0F));
if (this.level() instanceof ServerLevel && n > 2.0F) {
int o = (int)(n * 0.5);
((ServerLevel)this.level()).sendParticles(ParticleTypes.DAMAGE_INDICATOR, target.getX(), target.getY(0.5), target.getZ(), o, 0.1, 0.0, 0.1, 0.2);
}
}
this.causeFoodExhaustion(0.1F);
} else {
this.level().playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_NODAMAGE, this.getSoundSource(), 1.0F, 1.0F);
}
}
}
}
}
}
protected float getEnchantedDamage(Entity entity, float damage, DamageSource damageSource) {
return damage;
}
@Override
protected void doAutoAttackOnTouch(LivingEntity target) {
this.attack(target);
}
/**
* Called when the entity is dealt a critical hit.
*/
public void crit(Entity entityHit) {
}
public void magicCrit(Entity entityHit) {
}
public void sweepAttack() {
double d = -Mth.sin(this.getYRot() * (float) (Math.PI / 180.0));
double e = Mth.cos(this.getYRot() * (float) (Math.PI / 180.0));
if (this.level() instanceof ServerLevel) {
((ServerLevel)this.level()).sendParticles(ParticleTypes.SWEEP_ATTACK, this.getX() + d, this.getY(0.5), this.getZ() + e, 0, d, 0.0, e, 0.0);
}
}
public void respawn() {
}
@Override
public void remove(Entity.RemovalReason reason) {
super.remove(reason);
this.inventoryMenu.removed(this);
if (this.containerMenu != null && this.hasContainerOpen()) {
this.doCloseContainer();
}
}
@Override
public boolean isClientAuthoritative() {
return true;
}
@Override
protected boolean isLocalClientAuthoritative() {
return this.isLocalPlayer();
}
/**
* Returns whether this is a {@link net.minecraft.client.player.LocalPlayer}.
*/
public boolean isLocalPlayer() {
return false;
}
@Override
public boolean canSimulateMovement() {
return !this.level().isClientSide || this.isLocalPlayer();
}
@Override
public boolean isEffectiveAi() {
return !this.level().isClientSide || this.isLocalPlayer();
}
/**
* Returns the GameProfile for this player
*/
public GameProfile getGameProfile() {
return this.gameProfile;
}
public Inventory getInventory() {
return this.inventory;
}
public Abilities getAbilities() {
return this.abilities;
}
@Override
public boolean hasInfiniteMaterials() {
return this.abilities.instabuild;
}
public boolean preventsBlockDrops() {
return this.abilities.instabuild;
}
public void updateTutorialInventoryAction(ItemStack carried, ItemStack clicked, ClickAction action) {
}
public boolean hasContainerOpen() {
return this.containerMenu != this.inventoryMenu;
}
public boolean canDropItems() {
return true;
}
public Either<Player.BedSleepingProblem, Unit> startSleepInBed(BlockPos bedPos) {
this.startSleeping(bedPos);
this.sleepCounter = 0;
return Either.right(Unit.INSTANCE);
}
public void stopSleepInBed(boolean wakeImmediately, boolean updateLevelForSleepingPlayers) {
super.stopSleeping();
if (this.level() instanceof ServerLevel && updateLevelForSleepingPlayers) {
((ServerLevel)this.level()).updateSleepingPlayerList();
}
this.sleepCounter = wakeImmediately ? 0 : 100;
}
@Override
public void stopSleeping() {
this.stopSleepInBed(true, true);
}
/**
* Returns whether the player is asleep and the screen has fully faded.
*/
public boolean isSleepingLongEnough() {
return this.isSleeping() && this.sleepCounter >= 100;
}
public int getSleepTimer() {
return this.sleepCounter;
}
public void displayClientMessage(Component chatComponent, boolean actionBar) {
}
public void awardStat(ResourceLocation statKey) {
this.awardStat(Stats.CUSTOM.get(statKey));
}
public void awardStat(ResourceLocation stat, int increment) {
this.awardStat(Stats.CUSTOM.get(stat), increment);
}
/**
* Add a stat once
*/
public void awardStat(Stat<?> stat) {
this.awardStat(stat, 1);
}
/**
* Adds a value to a statistic field.
*/
public void awardStat(Stat<?> stat, int increment) {
}
public void resetStat(Stat<?> stat) {
}
public int awardRecipes(Collection<RecipeHolder<?>> recipes) {
return 0;
}
public void triggerRecipeCrafted(RecipeHolder<?> recipe, List<ItemStack> items) {
}
public void awardRecipesByKey(List<ResourceKey<Recipe<?>>> recipes) {
}
public int resetRecipes(Collection<RecipeHolder<?>> recipes) {
return 0;
}
@Override
public void travel(Vec3 travelVector) {
if (this.isPassenger()) {
super.travel(travelVector);
} else {
if (this.isSwimming()) {
double d = this.getLookAngle().y;
double e = d < -0.2 ? 0.085 : 0.06;
if (d <= 0.0 || this.jumping || !this.level().getFluidState(BlockPos.containing(this.getX(), this.getY() + 1.0 - 0.1, this.getZ())).isEmpty()) {
Vec3 vec3 = this.getDeltaMovement();
this.setDeltaMovement(vec3.add(0.0, (d - vec3.y) * e, 0.0));
}
}
if (this.getAbilities().flying) {
double d = this.getDeltaMovement().y;
super.travel(travelVector);
this.setDeltaMovement(this.getDeltaMovement().with(Direction.Axis.Y, d * 0.6));
} else {
super.travel(travelVector);
}
}
}
@Override
protected boolean canGlide() {
return !this.abilities.flying && super.canGlide();
}
@Override
public void updateSwimming() {
if (this.abilities.flying) {
this.setSwimming(false);
} else {
super.updateSwimming();
}
}
protected boolean freeAt(BlockPos pos) {
return !this.level().getBlockState(pos).isSuffocating(this.level(), pos);
}
@Override
public float getSpeed() {
return (float)this.getAttributeValue(Attributes.MOVEMENT_SPEED);
}
@Override
public boolean causeFallDamage(double fallDistance, float damageMultiplier, DamageSource damageSource) {
if (this.abilities.mayfly) {
return false;
} else {
if (fallDistance >= 2.0) {
this.awardStat(Stats.FALL_ONE_CM, (int)Math.round(fallDistance * 100.0));
}
boolean bl = this.currentImpulseImpactPos != null && this.ignoreFallDamageFromCurrentImpulse;
double d;
if (bl) {
d = Math.min(fallDistance, this.currentImpulseImpactPos.y - this.getY());
boolean bl2 = d <= 0.0;
if (bl2) {
this.resetCurrentImpulseContext();
} else {
this.tryResetCurrentImpulseContext();
}
} else {
d = fallDistance;
}
if (d > 0.0 && super.causeFallDamage(d, damageMultiplier, damageSource)) {
this.resetCurrentImpulseContext();
return true;
} else {
this.propagateFallToPassengers(fallDistance, damageMultiplier, damageSource);
return false;
}
}
}
public boolean tryToStartFallFlying() {
if (!this.isFallFlying() && this.canGlide() && !this.isInWater()) {
this.startFallFlying();
return true;
} else {
return false;
}
}
public void startFallFlying() {
this.setSharedFlag(7, true);
}
@Override
protected void doWaterSplashEffect() {
if (!this.isSpectator()) {
super.doWaterSplashEffect();
}
}
@Override
protected void playStepSound(BlockPos pos, BlockState state) {
if (this.isInWater()) {
this.waterSwimSound();
this.playMuffledStepSound(state);
} else {
BlockPos blockPos = this.getPrimaryStepSoundBlockPos(pos);
if (!pos.equals(blockPos)) {
BlockState blockState = this.level().getBlockState(blockPos);
if (blockState.is(BlockTags.COMBINATION_STEP_SOUND_BLOCKS)) {
this.playCombinationStepSounds(blockState, state);
} else {
super.playStepSound(blockPos, blockState);
}
} else {
super.playStepSound(pos, state);
}
}
}
@Override
public LivingEntity.Fallsounds getFallSounds() {
return new LivingEntity.Fallsounds(SoundEvents.PLAYER_SMALL_FALL, SoundEvents.PLAYER_BIG_FALL);
}
@Override
public boolean killedEntity(ServerLevel level, LivingEntity entity) {
this.awardStat(Stats.ENTITY_KILLED.get(entity.getType()));
return true;
}
@Override
public void makeStuckInBlock(BlockState state, Vec3 motionMultiplier) {
if (!this.abilities.flying) {
super.makeStuckInBlock(state, motionMultiplier);
}
this.tryResetCurrentImpulseContext();
}
public void giveExperiencePoints(int xpPoints) {
this.increaseScore(xpPoints);
this.experienceProgress = this.experienceProgress + (float)xpPoints / this.getXpNeededForNextLevel();
this.totalExperience = Mth.clamp(this.totalExperience + xpPoints, 0, Integer.MAX_VALUE);
while (this.experienceProgress < 0.0F) {
float f = this.experienceProgress * this.getXpNeededForNextLevel();
if (this.experienceLevel > 0) {
this.giveExperienceLevels(-1);
this.experienceProgress = 1.0F + f / this.getXpNeededForNextLevel();
} else {
this.giveExperienceLevels(-1);
this.experienceProgress = 0.0F;
}
}
while (this.experienceProgress >= 1.0F) {
this.experienceProgress = (this.experienceProgress - 1.0F) * this.getXpNeededForNextLevel();
this.giveExperienceLevels(1);
this.experienceProgress = this.experienceProgress / this.getXpNeededForNextLevel();
}
}
public int getEnchantmentSeed() {
return this.enchantmentSeed;
}
public void onEnchantmentPerformed(ItemStack enchantedItem, int levelCost) {
this.experienceLevel -= levelCost;
if (this.experienceLevel < 0) {
this.experienceLevel = 0;
this.experienceProgress = 0.0F;
this.totalExperience = 0;
}
this.enchantmentSeed = this.random.nextInt();
}
/**
* Add experience levels to this player.
*/
public void giveExperienceLevels(int levels) {
this.experienceLevel = IntMath.saturatedAdd(this.experienceLevel, levels);
if (this.experienceLevel < 0) {
this.experienceLevel = 0;
this.experienceProgress = 0.0F;
this.totalExperience = 0;
}
if (levels > 0 && this.experienceLevel % 5 == 0 && this.lastLevelUpTime < this.tickCount - 100.0F) {
float f = this.experienceLevel > 30 ? 1.0F : this.experienceLevel / 30.0F;
this.level().playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_LEVELUP, this.getSoundSource(), f * 0.75F, 1.0F);
this.lastLevelUpTime = this.tickCount;
}
}
/**
* This method returns the cap amount of experience that the experience bar can hold. With each level, the experience cap on the player's experience bar is raised by 10.
*/
public int getXpNeededForNextLevel() {
if (this.experienceLevel >= 30) {
return 112 + (this.experienceLevel - 30) * 9;
} else {
return this.experienceLevel >= 15 ? 37 + (this.experienceLevel - 15) * 5 : 7 + this.experienceLevel * 2;
}
}
/**
* Increases exhaustion level by the supplied amount.
*/
public void causeFoodExhaustion(float exhaustion) {
if (!this.abilities.invulnerable) {
if (!this.level().isClientSide) {
this.foodData.addExhaustion(exhaustion);
}
}
}
public Optional<WardenSpawnTracker> getWardenSpawnTracker() {
return Optional.empty();
}
/**
* Returns the player's FoodStats object.
*/
public FoodData getFoodData() {
return this.foodData;
}
public boolean canEat(boolean canAlwaysEat) {
return this.abilities.invulnerable || canAlwaysEat || this.foodData.needsFood();
}
/**
* Checks if the player's health is not full and not zero.
*/
public boolean isHurt() {
return this.getHealth() > 0.0F && this.getHealth() < this.getMaxHealth();
}
public boolean mayBuild() {
return this.abilities.mayBuild;
}
/**
* Returns whether this player can modify the block at a certain location with the given stack.
* <p>
* The position being queried is {@code pos.offset(facing.getOpposite())}.
*
* @return Whether this player may modify the queried location in the current world
* @see ItemStack#canPlaceOn(Block)
* @see ItemStack#canEditBlocks()
* @see PlayerCapabilities#allowEdit
*/
public boolean mayUseItemAt(BlockPos pos, Direction facing, ItemStack stack) {
if (this.abilities.mayBuild) {
return true;
} else {
BlockPos blockPos = pos.relative(facing.getOpposite());
BlockInWorld blockInWorld = new BlockInWorld(this.level(), blockPos, false);
return stack.canPlaceOnBlockInAdventureMode(blockInWorld);
}
}
@Override
protected int getBaseExperienceReward(ServerLevel level) {
return !level.getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY) && !this.isSpectator() ? Math.min(this.experienceLevel * 7, 100) : 0;
}
@Override
protected boolean isAlwaysExperienceDropper() {
return true;
}
@Override
public boolean shouldShowName() {
return true;
}
@Override
protected Entity.MovementEmission getMovementEmission() {
return this.abilities.flying || this.onGround() && this.isDiscrete() ? Entity.MovementEmission.NONE : Entity.MovementEmission.ALL;
}
/**
* Sends the player's abilities to the server (if there is one).
*/
public void onUpdateAbilities() {
}
@Override
public Component getName() {
return Component.literal(this.gameProfile.getName());
}
/**
* Returns the InventoryEnderChest of this player.
*/
public PlayerEnderChestContainer getEnderChestInventory() {
return this.enderChestInventory;
}
@Override
protected boolean doesEmitEquipEvent(EquipmentSlot slot) {
return slot.getType() == EquipmentSlot.Type.HUMANOID_ARMOR;
}
public boolean addItem(ItemStack stack) {
return this.inventory.add(stack);
}
public boolean setEntityOnShoulder(CompoundTag entityCompound) {
if (this.isPassenger() || !this.onGround() || this.isInWater() || this.isInPowderSnow) {
return false;
} else if (this.getShoulderEntityLeft().isEmpty()) {
this.setShoulderEntityLeft(entityCompound);
this.timeEntitySatOnShoulder = this.level().getGameTime();
return true;
} else if (this.getShoulderEntityRight().isEmpty()) {
this.setShoulderEntityRight(entityCompound);
this.timeEntitySatOnShoulder = this.level().getGameTime();
return true;
} else {
return false;
}
}
protected void removeEntitiesOnShoulder() {
if (this.timeEntitySatOnShoulder + 20L < this.level().getGameTime()) {
this.respawnEntityOnShoulder(this.getShoulderEntityLeft());
this.setShoulderEntityLeft(new CompoundTag());
this.respawnEntityOnShoulder(this.getShoulderEntityRight());
this.setShoulderEntityRight(new CompoundTag());
}
}
private void respawnEntityOnShoulder(CompoundTag entityCompound) {
if (!this.level().isClientSide && !entityCompound.isEmpty()) {
EntityType.create(entityCompound, this.level(), EntitySpawnReason.LOAD).ifPresent(entity -> {
if (entity instanceof TamableAnimal tamableAnimal) {
tamableAnimal.setOwner(this);
}
entity.setPos(this.getX(), this.getY() + 0.7F, this.getZ());
((ServerLevel)this.level()).addWithUUID(entity);
});
}
}
@Nullable
public abstract GameType gameMode();
@Override
public boolean isSpectator() {
return this.gameMode() == GameType.SPECTATOR;
}
@Override
public boolean canBeHitByProjectile() {
return !this.isSpectator() && super.canBeHitByProjectile();
}
@Override
public boolean isSwimming() {
return !this.abilities.flying && !this.isSpectator() && super.isSwimming();
}
public boolean isCreative() {
return this.gameMode() == GameType.CREATIVE;
}
@Override
public boolean isPushedByFluid() {
return !this.abilities.flying;
}
public Scoreboard getScoreboard() {
return this.level().getScoreboard();
}
@Override
public Component getDisplayName() {
MutableComponent mutableComponent = PlayerTeam.formatNameForTeam(this.getTeam(), this.getName());
return this.decorateDisplayNameComponent(mutableComponent);
}
private MutableComponent decorateDisplayNameComponent(MutableComponent displayName) {
String string = this.getGameProfile().getName();
return displayName.withStyle(
style -> style.withClickEvent(new ClickEvent.SuggestCommand("/tell " + string + " ")).withHoverEvent(this.createHoverEvent()).withInsertion(string)
);
}
@Override
public String getScoreboardName() {
return this.getGameProfile().getName();
}
@Override
protected void internalSetAbsorptionAmount(float absorptionAmount) {
this.getEntityData().set(DATA_PLAYER_ABSORPTION_ID, absorptionAmount);
}
@Override
public float getAbsorptionAmount() {
return this.getEntityData().get(DATA_PLAYER_ABSORPTION_ID);
}
public boolean isModelPartShown(PlayerModelPart part) {
return (this.getEntityData().get(DATA_PLAYER_MODE_CUSTOMISATION) & part.getMask()) == part.getMask();
}
@Override
public SlotAccess getSlot(int slot) {
if (slot == 499) {
return new SlotAccess() {
@Override
public ItemStack get() {
return Player.this.containerMenu.getCarried();
}
@Override
public boolean set(ItemStack carried) {
Player.this.containerMenu.setCarried(carried);
return true;
}
};
} else {
final int i = slot - 500;
if (i >= 0 && i < 4) {
return new SlotAccess() {
@Override
public ItemStack get() {
return Player.this.inventoryMenu.getCraftSlots().getItem(i);
}
@Override
public boolean set(ItemStack carried) {
Player.this.inventoryMenu.getCraftSlots().setItem(i, carried);
Player.this.inventoryMenu.slotsChanged(Player.this.inventory);
return true;
}
};
} else if (slot >= 0 && slot < this.inventory.getNonEquipmentItems().size()) {
return SlotAccess.forContainer(this.inventory, slot);
} else {
int j = slot - 200;
return j >= 0 && j < this.enderChestInventory.getContainerSize() ? SlotAccess.forContainer(this.enderChestInventory, j) : super.getSlot(slot);
}
}
}
/**
* Whether the "reducedDebugInfo" option is active for this player.
*/
public boolean isReducedDebugInfo() {
return this.reducedDebugInfo;
}
public void setReducedDebugInfo(boolean reducedDebugInfo) {
this.reducedDebugInfo = reducedDebugInfo;
}
@Override
public void setRemainingFireTicks(int remainingFireTicks) {
super.setRemainingFireTicks(this.abilities.invulnerable ? Math.min(remainingFireTicks, 1) : remainingFireTicks);
}
@Override
public HumanoidArm getMainArm() {
return this.entityData.get(DATA_PLAYER_MAIN_HAND) == 0 ? HumanoidArm.LEFT : HumanoidArm.RIGHT;
}
public void setMainArm(HumanoidArm hand) {
this.entityData.set(DATA_PLAYER_MAIN_HAND, (byte)(hand == HumanoidArm.LEFT ? 0 : 1));
}
public CompoundTag getShoulderEntityLeft() {
return this.entityData.get(DATA_SHOULDER_LEFT);
}
protected void setShoulderEntityLeft(CompoundTag entityCompound) {
this.entityData.set(DATA_SHOULDER_LEFT, entityCompound);
}
public CompoundTag getShoulderEntityRight() {
return this.entityData.get(DATA_SHOULDER_RIGHT);
}
protected void setShoulderEntityRight(CompoundTag entityCompound) {
this.entityData.set(DATA_SHOULDER_RIGHT, entityCompound);
}
public float getCurrentItemAttackStrengthDelay() {
return (float)(1.0 / this.getAttributeValue(Attributes.ATTACK_SPEED) * 20.0);
}
/**
* Returns the percentage of attack power available based on the cooldown (zero to one).
*/
public float getAttackStrengthScale(float adjustTicks) {
return Mth.clamp((this.attackStrengthTicker + adjustTicks) / this.getCurrentItemAttackStrengthDelay(), 0.0F, 1.0F);
}
public void resetAttackStrengthTicker() {
this.attackStrengthTicker = 0;
}
public ItemCooldowns getCooldowns() {
return this.cooldowns;
}
@Override
protected float getBlockSpeedFactor() {
return !this.abilities.flying && !this.isFallFlying() ? super.getBlockSpeedFactor() : 1.0F;
}
@Override
public float getLuck() {
return (float)this.getAttributeValue(Attributes.LUCK);
}
public boolean canUseGameMasterBlocks() {
return this.abilities.instabuild && this.getPermissionLevel() >= 2;
}
public int getPermissionLevel() {
return 0;
}
public boolean hasPermissions(int permissionLevel) {
return this.getPermissionLevel() >= permissionLevel;
}
@Override
public EntityDimensions getDefaultDimensions(Pose pose) {
return (EntityDimensions)POSES.getOrDefault(pose, STANDING_DIMENSIONS);
}
@Override
public ImmutableList<Pose> getDismountPoses() {
return ImmutableList.of(Pose.STANDING, Pose.CROUCHING, Pose.SWIMMING);
}
@Override
public ItemStack getProjectile(ItemStack weaponStack) {
if (!(weaponStack.getItem() instanceof ProjectileWeaponItem)) {
return ItemStack.EMPTY;
} else {
Predicate<ItemStack> predicate = ((ProjectileWeaponItem)weaponStack.getItem()).getSupportedHeldProjectiles();
ItemStack itemStack = ProjectileWeaponItem.getHeldProjectile(this, predicate);
if (!itemStack.isEmpty()) {
return itemStack;
} else {
predicate = ((ProjectileWeaponItem)weaponStack.getItem()).getAllSupportedProjectiles();
for (int i = 0; i < this.inventory.getContainerSize(); i++) {
ItemStack itemStack2 = this.inventory.getItem(i);
if (predicate.test(itemStack2)) {
return itemStack2;
}
}
return this.hasInfiniteMaterials() ? new ItemStack(Items.ARROW) : ItemStack.EMPTY;
}
}
}
@Override
public Vec3 getRopeHoldPosition(float partialTicks) {
double d = 0.22 * (this.getMainArm() == HumanoidArm.RIGHT ? -1.0 : 1.0);
float f = Mth.lerp(partialTicks * 0.5F, this.getXRot(), this.xRotO) * (float) (Math.PI / 180.0);
float g = Mth.lerp(partialTicks, this.yBodyRotO, this.yBodyRot) * (float) (Math.PI / 180.0);
if (this.isFallFlying() || this.isAutoSpinAttack()) {
Vec3 vec3 = this.getViewVector(partialTicks);
Vec3 vec32 = this.getDeltaMovement();
double e = vec32.horizontalDistanceSqr();
double h = vec3.horizontalDistanceSqr();
float k;
if (e > 0.0 && h > 0.0) {
double i = (vec32.x * vec3.x + vec32.z * vec3.z) / Math.sqrt(e * h);
double j = vec32.x * vec3.z - vec32.z * vec3.x;
k = (float)(Math.signum(j) * Math.acos(i));
} else {
k = 0.0F;
}
return this.getPosition(partialTicks).add(new Vec3(d, -0.11, 0.85).zRot(-k).xRot(-f).yRot(-g));
} else if (this.isVisuallySwimming()) {
return this.getPosition(partialTicks).add(new Vec3(d, 0.2, -0.15).xRot(-f).yRot(-g));
} else {
double l = this.getBoundingBox().getYsize() - 1.0;
double e = this.isCrouching() ? -0.2 : 0.07;
return this.getPosition(partialTicks).add(new Vec3(d, l, e).yRot(-g));
}
}
@Override
public boolean isAlwaysTicking() {
return true;
}
public boolean isScoping() {
return this.isUsingItem() && this.getUseItem().is(Items.SPYGLASS);
}
@Override
public boolean shouldBeSaved() {
return false;
}
public Optional<GlobalPos> getLastDeathLocation() {
return this.lastDeathLocation;
}
public void setLastDeathLocation(Optional<GlobalPos> lastDeathLocation) {
this.lastDeathLocation = lastDeathLocation;
}
@Override
public float getHurtDir() {
return this.hurtDir;
}
@Override
public void animateHurt(float yaw) {
super.animateHurt(yaw);
this.hurtDir = yaw;
}
@Override
public boolean canSprint() {
return true;
}
@Override
protected float getFlyingSpeed() {
if (this.abilities.flying && !this.isPassenger()) {
return this.isSprinting() ? this.abilities.getFlyingSpeed() * 2.0F : this.abilities.getFlyingSpeed();
} else {
return this.isSprinting() ? 0.025999999F : 0.02F;
}
}
public boolean hasClientLoaded() {
return this.clientLoaded || this.clientLoadedTimeoutTimer <= 0;
}
public void tickClientLoadTimeout() {
if (!this.clientLoaded) {
this.clientLoadedTimeoutTimer--;
}
}
public void setClientLoaded(boolean clientLoaded) {
this.clientLoaded = clientLoaded;
if (!this.clientLoaded) {
this.clientLoadedTimeoutTimer = 60;
}
}
public double blockInteractionRange() {
return this.getAttributeValue(Attributes.BLOCK_INTERACTION_RANGE);
}
public double entityInteractionRange() {
return this.getAttributeValue(Attributes.ENTITY_INTERACTION_RANGE);
}
public boolean canInteractWithEntity(Entity entity, double distance) {
return entity.isRemoved() ? false : this.canInteractWithEntity(entity.getBoundingBox(), distance);
}
public boolean canInteractWithEntity(AABB boundingBox, double distance) {
double d = this.entityInteractionRange() + distance;
return boundingBox.distanceToSqr(this.getEyePosition()) < d * d;
}
public boolean canInteractWithBlock(BlockPos pos, double distance) {
double d = this.blockInteractionRange() + distance;
return new AABB(pos).distanceToSqr(this.getEyePosition()) < d * d;
}
public void setIgnoreFallDamageFromCurrentImpulse(boolean ignoreFallDamageFromCurrentImpulse) {
this.ignoreFallDamageFromCurrentImpulse = ignoreFallDamageFromCurrentImpulse;
if (ignoreFallDamageFromCurrentImpulse) {
this.currentImpulseContextResetGraceTime = 40;
} else {
this.currentImpulseContextResetGraceTime = 0;
}
}
public boolean isIgnoringFallDamageFromCurrentImpulse() {
return this.ignoreFallDamageFromCurrentImpulse;
}
public void tryResetCurrentImpulseContext() {
if (this.currentImpulseContextResetGraceTime == 0) {
this.resetCurrentImpulseContext();
}
}
public void resetCurrentImpulseContext() {
this.currentImpulseContextResetGraceTime = 0;
this.currentExplosionCause = null;
this.currentImpulseImpactPos = null;
this.ignoreFallDamageFromCurrentImpulse = false;
}
public boolean shouldRotateWithMinecart() {
return false;
}
@Override
public boolean onClimbable() {
return this.abilities.flying ? false : super.onClimbable();
}
public String debugInfo() {
return MoreObjects.toStringHelper(this)
.add("name", this.getName().getString())
.add("id", this.getId())
.add("pos", this.position())
.add("mode", this.gameMode())
.add("permission", this.getPermissionLevel())
.toString();
}
public static enum BedSleepingProblem {
NOT_POSSIBLE_HERE,
NOT_POSSIBLE_NOW(Component.translatable("block.minecraft.bed.no_sleep")),
TOO_FAR_AWAY(Component.translatable("block.minecraft.bed.too_far_away")),
OBSTRUCTED(Component.translatable("block.minecraft.bed.obstructed")),
OTHER_PROBLEM,
NOT_SAFE(Component.translatable("block.minecraft.bed.not_safe"));
@Nullable
private final Component message;
private BedSleepingProblem() {
this.message = null;
}
private BedSleepingProblem(final Component message) {
this.message = message;
}
@Nullable
public Component getMessage() {
return this.message;
}
}
}