package net.minecraft.client.player;

import java.util.stream.Stream;
import net.minecraft.client.resources.sounds.UnderwaterAmbientSoundInstances;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.Vec2;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.entity.MoverType;
import net.minecraft.world.effect.MobEffectInstance;
import javax.annotation.Nullable;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.client.resources.sounds.SimpleSoundInstance;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.tags.Tag;
import net.minecraft.tags.FluidTags;
import net.minecraft.world.item.ElytraItem;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.Pose;
import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.world.item.Item;
import net.minecraft.client.gui.screens.inventory.BookEditScreen;
import net.minecraft.world.item.Items;
import net.minecraft.client.gui.screens.inventory.JigsawBlockEditScreen;
import net.minecraft.world.level.block.entity.JigsawBlockEntity;
import net.minecraft.client.gui.screens.inventory.StructureBlockEditScreen;
import net.minecraft.world.level.block.entity.StructureBlockEntity;
import net.minecraft.client.gui.screens.inventory.CommandBlockEditScreen;
import net.minecraft.world.level.block.entity.CommandBlockEntity;
import net.minecraft.client.gui.screens.inventory.MinecartCommandBlockEditScreen;
import net.minecraft.world.level.BaseCommandBlock;
import net.minecraft.client.gui.screens.inventory.SignEditScreen;
import net.minecraft.world.level.block.entity.SignBlockEntity;
import net.minecraft.world.entity.PlayerRideableJumping;
import net.minecraft.client.resources.sounds.ElytraOnPlayerSoundInstance;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.sounds.SoundSource;
import net.minecraft.sounds.SoundEvent;
import java.util.UUID;
import net.minecraft.world.phys.AABB;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.game.ServerboundRecipeBookUpdatePacket;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.util.Mth;
import net.minecraft.network.protocol.game.ServerboundPlayerAbilitiesPacket;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.protocol.game.ServerboundContainerClosePacket;
import net.minecraft.network.protocol.game.ServerboundClientCommandPacket;
import net.minecraft.network.protocol.game.ServerboundSwingPacket;
import net.minecraft.network.protocol.game.ServerboundChatPacket;
import net.minecraft.world.item.ItemStack;
import net.minecraft.core.Direction;
import net.minecraft.network.protocol.game.ServerboundPlayerActionPacket;
import net.minecraft.world.phys.Vec3;
import net.minecraft.network.protocol.game.ServerboundPlayerCommandPacket;
import java.util.Iterator;
import net.minecraft.network.protocol.game.ServerboundMoveVehiclePacket;
import net.minecraft.network.protocol.game.ServerboundPlayerInputPacket;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.vehicle.Boat;
import net.minecraft.client.resources.sounds.SoundInstance;
import net.minecraft.world.entity.player.Player;
import net.minecraft.client.resources.sounds.RidingMinecartSoundInstance;
import net.minecraft.world.entity.vehicle.AbstractMinecart;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.client.resources.sounds.BiomeAmbientSoundsHandler;
import net.minecraft.client.resources.sounds.BubbleColumnAmbientSoundHandler;
import net.minecraft.client.resources.sounds.UnderwaterAmbientSoundHandler;
import com.google.common.collect.Lists;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.world.InteractionHand;
import net.minecraft.client.Minecraft;
import net.minecraft.client.resources.sounds.AmbientSoundHandler;
import java.util.List;
import net.minecraft.client.ClientRecipeBook;
import net.minecraft.stats.StatsCounter;
import net.minecraft.client.multiplayer.ClientPacketListener;

public class LocalPlayer extends AbstractClientPlayer {
    public final ClientPacketListener connection;
    private final StatsCounter stats;
    private final ClientRecipeBook recipeBook;
    private final List<AmbientSoundHandler> ambientSoundHandlers;
    private int permissionLevel;
    private double xLast;
    private double yLast1;
    private double zLast;
    private float yRotLast;
    private float xRotLast;
    private boolean lastOnGround;
    private boolean crouching;
    private boolean wasShiftKeyDown;
    private boolean wasSprinting;
    private int positionReminder;
    private boolean flashOnSetHealth;
    private String serverBrand;
    public Input input;
    protected final Minecraft minecraft;
    protected int sprintTriggerTime;
    public int sprintTime;
    public float yBob;
    public float xBob;
    public float yBobO;
    public float xBobO;
    private int jumpRidingTicks;
    private float jumpRidingScale;
    public float portalTime;
    public float oPortalTime;
    private boolean startedUsingItem;
    private InteractionHand usingItemHand;
    private boolean handsBusy;
    private boolean autoJumpEnabled;
    private int autoJumpTime;
    private boolean wasFallFlying;
    private int waterVisionTime;
    private boolean showDeathScreen;
    
    public LocalPlayer(final Minecraft dlx, final ClientLevel dym, final ClientPacketListener dyn, final StatsCounter acv, final ClientRecipeBook dlk, final boolean boolean6, final boolean boolean7) {
        super(dym, dyn.getLocalGameProfile());
        this.ambientSoundHandlers = Lists.newArrayList();
        this.permissionLevel = 0;
        this.autoJumpEnabled = true;
        this.showDeathScreen = true;
        this.minecraft = dlx;
        this.connection = dyn;
        this.stats = acv;
        this.recipeBook = dlk;
        this.wasShiftKeyDown = boolean6;
        this.wasSprinting = boolean7;
        this.ambientSoundHandlers.add(new UnderwaterAmbientSoundHandler(this, dlx.getSoundManager()));
        this.ambientSoundHandlers.add(new BubbleColumnAmbientSoundHandler(this));
        this.ambientSoundHandlers.add(new BiomeAmbientSoundsHandler(this, dlx.getSoundManager(), dym.getBiomeManager()));
    }
    
    @Override
    public boolean hurt(final DamageSource anw, final float float2) {
        return false;
    }
    
    @Override
    public void heal(final float float1) {
    }
    
    @Override
    public boolean startRiding(final Entity aom, final boolean boolean2) {
        if (!super.startRiding(aom, boolean2)) {
            return false;
        }
        if (aom instanceof AbstractMinecart) {
            this.minecraft.getSoundManager().play(new RidingMinecartSoundInstance(this, (AbstractMinecart)aom));
        }
        if (aom instanceof Boat) {
            this.yRotO = aom.yRot;
            this.yRot = aom.yRot;
            this.setYHeadRot(aom.yRot);
        }
        return true;
    }
    
    @Override
    public void removeVehicle() {
        super.removeVehicle();
        this.handsBusy = false;
    }
    
    @Override
    public float getViewXRot(final float float1) {
        return this.xRot;
    }
    
    @Override
    public float getViewYRot(final float float1) {
        if (this.isPassenger()) {
            return super.getViewYRot(float1);
        }
        return this.yRot;
    }
    
    @Override
    public void tick() {
        if (!this.level.hasChunkAt(new BlockPos(this.getX(), 0.0, this.getZ()))) {
            return;
        }
        super.tick();
        if (this.isPassenger()) {
            this.connection.send(new ServerboundMovePlayerPacket.Rot(this.yRot, this.xRot, this.onGround));
            this.connection.send(new ServerboundPlayerInputPacket(this.xxa, this.zza, this.input.jumping, this.input.shiftKeyDown));
            final Entity aom2 = this.getRootVehicle();
            if (aom2 != this && aom2.isControlledByLocalInstance()) {
                this.connection.send(new ServerboundMoveVehiclePacket(aom2));
            }
        }
        else {
            this.sendPosition();
        }
        for (final AmbientSoundHandler enx3 : this.ambientSoundHandlers) {
            enx3.tick();
        }
    }
    
    public float getCurrentMood() {
        for (final AmbientSoundHandler enx3 : this.ambientSoundHandlers) {
            if (enx3 instanceof BiomeAmbientSoundsHandler) {
                return ((BiomeAmbientSoundsHandler)enx3).getMoodiness();
            }
        }
        return 0.0f;
    }
    
    private void sendPosition() {
        final boolean boolean2 = this.isSprinting();
        if (boolean2 != this.wasSprinting) {
            final ServerboundPlayerCommandPacket.Action a3 = boolean2 ? ServerboundPlayerCommandPacket.Action.START_SPRINTING : ServerboundPlayerCommandPacket.Action.STOP_SPRINTING;
            this.connection.send(new ServerboundPlayerCommandPacket(this, a3));
            this.wasSprinting = boolean2;
        }
        final boolean boolean3 = this.isShiftKeyDown();
        if (boolean3 != this.wasShiftKeyDown) {
            final ServerboundPlayerCommandPacket.Action a4 = boolean3 ? ServerboundPlayerCommandPacket.Action.PRESS_SHIFT_KEY : ServerboundPlayerCommandPacket.Action.RELEASE_SHIFT_KEY;
            this.connection.send(new ServerboundPlayerCommandPacket(this, a4));
            this.wasShiftKeyDown = boolean3;
        }
        if (this.isControlledCamera()) {
            final double double4 = this.getX() - this.xLast;
            final double double5 = this.getY() - this.yLast1;
            final double double6 = this.getZ() - this.zLast;
            final double double7 = this.yRot - this.yRotLast;
            final double double8 = this.xRot - this.xRotLast;
            ++this.positionReminder;
            boolean boolean4 = double4 * double4 + double5 * double5 + double6 * double6 > 9.0E-4 || this.positionReminder >= 20;
            final boolean boolean5 = double7 != 0.0 || double8 != 0.0;
            if (this.isPassenger()) {
                final Vec3 dem16 = this.getDeltaMovement();
                this.connection.send(new ServerboundMovePlayerPacket.PosRot(dem16.x, -999.0, dem16.z, this.yRot, this.xRot, this.onGround));
                boolean4 = false;
            }
            else if (boolean4 && boolean5) {
                this.connection.send(new ServerboundMovePlayerPacket.PosRot(this.getX(), this.getY(), this.getZ(), this.yRot, this.xRot, this.onGround));
            }
            else if (boolean4) {
                this.connection.send(new ServerboundMovePlayerPacket.Pos(this.getX(), this.getY(), this.getZ(), this.onGround));
            }
            else if (boolean5) {
                this.connection.send(new ServerboundMovePlayerPacket.Rot(this.yRot, this.xRot, this.onGround));
            }
            else if (this.lastOnGround != this.onGround) {
                this.connection.send(new ServerboundMovePlayerPacket(this.onGround));
            }
            if (boolean4) {
                this.xLast = this.getX();
                this.yLast1 = this.getY();
                this.zLast = this.getZ();
                this.positionReminder = 0;
            }
            if (boolean5) {
                this.yRotLast = this.yRot;
                this.xRotLast = this.xRot;
            }
            this.lastOnGround = this.onGround;
            this.autoJumpEnabled = this.minecraft.options.autoJump;
        }
    }
    
    @Override
    public boolean drop(final boolean boolean1) {
        final ServerboundPlayerActionPacket.Action a3 = boolean1 ? ServerboundPlayerActionPacket.Action.DROP_ALL_ITEMS : ServerboundPlayerActionPacket.Action.DROP_ITEM;
        this.connection.send(new ServerboundPlayerActionPacket(a3, BlockPos.ZERO, Direction.DOWN));
        return this.inventory.removeItem(this.inventory.selected, (boolean1 && !this.inventory.getSelected().isEmpty()) ? this.inventory.getSelected().getCount() : 1) != ItemStack.EMPTY;
    }
    
    public void chat(final String string) {
        this.connection.send(new ServerboundChatPacket(string));
    }
    
    @Override
    public void swing(final InteractionHand anf) {
        super.swing(anf);
        this.connection.send(new ServerboundSwingPacket(anf));
    }
    
    @Override
    public void respawn() {
        this.connection.send(new ServerboundClientCommandPacket(ServerboundClientCommandPacket.Action.PERFORM_RESPAWN));
    }
    
    @Override
    protected void actuallyHurt(final DamageSource anw, final float float2) {
        if (this.isInvulnerableTo(anw)) {
            return;
        }
        this.setHealth(this.getHealth() - float2);
    }
    
    public void closeContainer() {
        this.connection.send(new ServerboundContainerClosePacket(this.containerMenu.containerId));
        this.clientSideCloseContainer();
    }
    
    public void clientSideCloseContainer() {
        this.inventory.setCarried(ItemStack.EMPTY);
        super.closeContainer();
        this.minecraft.setScreen(null);
    }
    
    public void hurtTo(final float float1) {
        if (this.flashOnSetHealth) {
            final float float2 = this.getHealth() - float1;
            if (float2 <= 0.0f) {
                this.setHealth(float1);
                if (float2 < 0.0f) {
                    this.invulnerableTime = 10;
                }
            }
            else {
                this.lastHurt = float2;
                this.setHealth(this.getHealth());
                this.invulnerableTime = 20;
                this.actuallyHurt(DamageSource.GENERIC, float2);
                this.hurtDuration = 10;
                this.hurtTime = this.hurtDuration;
            }
        }
        else {
            this.setHealth(float1);
            this.flashOnSetHealth = true;
        }
    }
    
    @Override
    public void onUpdateAbilities() {
        this.connection.send(new ServerboundPlayerAbilitiesPacket(this.abilities));
    }
    
    @Override
    public boolean isLocalPlayer() {
        return true;
    }
    
    @Override
    public boolean isSuppressingSlidingDownLadder() {
        return !this.abilities.flying && super.isSuppressingSlidingDownLadder();
    }
    
    @Override
    public boolean canSpawnSprintParticle() {
        return !this.abilities.flying && super.canSpawnSprintParticle();
    }
    
    @Override
    public boolean canSpawnSoulSpeedParticle() {
        return !this.abilities.flying && super.canSpawnSoulSpeedParticle();
    }
    
    protected void sendRidingJump() {
        this.connection.send(new ServerboundPlayerCommandPacket(this, ServerboundPlayerCommandPacket.Action.START_RIDING_JUMP, Mth.floor(this.getJumpRidingScale() * 100.0f)));
    }
    
    public void sendOpenInventory() {
        this.connection.send(new ServerboundPlayerCommandPacket(this, ServerboundPlayerCommandPacket.Action.OPEN_INVENTORY));
    }
    
    public void setServerBrand(final String string) {
        this.serverBrand = string;
    }
    
    public String getServerBrand() {
        return this.serverBrand;
    }
    
    public StatsCounter getStats() {
        return this.stats;
    }
    
    public ClientRecipeBook getRecipeBook() {
        return this.recipeBook;
    }
    
    public void removeRecipeHighlight(final Recipe<?> bmu) {
        if (this.recipeBook.willHighlight(bmu)) {
            this.recipeBook.removeHighlight(bmu);
            this.connection.send(new ServerboundRecipeBookUpdatePacket(bmu));
        }
    }
    
    @Override
    protected int getPermissionLevel() {
        return this.permissionLevel;
    }
    
    public void setPermissionLevel(final int integer) {
        this.permissionLevel = integer;
    }
    
    @Override
    public void displayClientMessage(final Component mr, final boolean boolean2) {
        if (boolean2) {
            this.minecraft.gui.setOverlayMessage(mr, false);
        }
        else {
            this.minecraft.gui.getChat().addMessage(mr);
        }
    }
    
    @Override
    protected void checkInBlock(final double double1, final double double2, final double double3) {
        final BlockPos fu8 = new BlockPos(double1, double2, double3);
        if (this.blocked(fu8)) {
            final double double4 = double1 - fu8.getX();
            final double double5 = double3 - fu8.getZ();
            Direction fz13 = null;
            double double6 = 9999.0;
            if (!this.blocked(fu8.west()) && double4 < double6) {
                double6 = double4;
                fz13 = Direction.WEST;
            }
            if (!this.blocked(fu8.east()) && 1.0 - double4 < double6) {
                double6 = 1.0 - double4;
                fz13 = Direction.EAST;
            }
            if (!this.blocked(fu8.north()) && double5 < double6) {
                double6 = double5;
                fz13 = Direction.NORTH;
            }
            if (!this.blocked(fu8.south()) && 1.0 - double5 < double6) {
                double6 = 1.0 - double5;
                fz13 = Direction.SOUTH;
            }
            if (fz13 != null) {
                final Vec3 dem16 = this.getDeltaMovement();
                switch (fz13) {
                    case WEST: {
                        this.setDeltaMovement(-0.1, dem16.y, dem16.z);
                        break;
                    }
                    case EAST: {
                        this.setDeltaMovement(0.1, dem16.y, dem16.z);
                        break;
                    }
                    case NORTH: {
                        this.setDeltaMovement(dem16.x, dem16.y, -0.1);
                        break;
                    }
                    case SOUTH: {
                        this.setDeltaMovement(dem16.x, dem16.y, 0.1);
                        break;
                    }
                }
            }
        }
    }
    
    private boolean blocked(final BlockPos fu) {
        final AABB deg3 = this.getBoundingBox();
        final BlockPos.MutableBlockPos a4 = fu.mutable();
        for (int integer5 = Mth.floor(deg3.minY); integer5 < Mth.ceil(deg3.maxY); ++integer5) {
            a4.setY(integer5);
            if (!this.freeAt(a4)) {
                return true;
            }
        }
        return false;
    }
    
    @Override
    public void setSprinting(final boolean boolean1) {
        super.setSprinting(boolean1);
        this.sprintTime = 0;
    }
    
    public void setExperienceValues(final float float1, final int integer2, final int integer3) {
        this.experienceProgress = float1;
        this.totalExperience = integer2;
        this.experienceLevel = integer3;
    }
    
    @Override
    public void sendMessage(final Component mr, final UUID uUID) {
        this.minecraft.gui.getChat().addMessage(mr);
    }
    
    @Override
    public void handleEntityEvent(final byte byte1) {
        if (byte1 >= 24 && byte1 <= 28) {
            this.setPermissionLevel(byte1 - 24);
        }
        else {
            super.handleEntityEvent(byte1);
        }
    }
    
    public void setShowDeathScreen(final boolean boolean1) {
        this.showDeathScreen = boolean1;
    }
    
    public boolean shouldShowDeathScreen() {
        return this.showDeathScreen;
    }
    
    @Override
    public void playSound(final SoundEvent ack, final float float2, final float float3) {
        this.level.playLocalSound(this.getX(), this.getY(), this.getZ(), ack, this.getSoundSource(), float2, float3, false);
    }
    
    @Override
    public void playNotifySound(final SoundEvent ack, final SoundSource acm, final float float3, final float float4) {
        this.level.playLocalSound(this.getX(), this.getY(), this.getZ(), ack, acm, float3, float4, false);
    }
    
    @Override
    public boolean isEffectiveAi() {
        return true;
    }
    
    @Override
    public void startUsingItem(final InteractionHand anf) {
        final ItemStack bki3 = this.getItemInHand(anf);
        if (bki3.isEmpty() || this.isUsingItem()) {
            return;
        }
        super.startUsingItem(anf);
        this.startedUsingItem = true;
        this.usingItemHand = anf;
    }
    
    @Override
    public boolean isUsingItem() {
        return this.startedUsingItem;
    }
    
    @Override
    public void stopUsingItem() {
        super.stopUsingItem();
        this.startedUsingItem = false;
    }
    
    @Override
    public InteractionHand getUsedItemHand() {
        return this.usingItemHand;
    }
    
    @Override
    public void onSyncedDataUpdated(final EntityDataAccessor<?> tq) {
        super.onSyncedDataUpdated(tq);
        if (LocalPlayer.DATA_LIVING_ENTITY_FLAGS.equals(tq)) {
            final boolean boolean3 = (this.entityData.<Byte>get(LocalPlayer.DATA_LIVING_ENTITY_FLAGS) & 0x1) > 0;
            final InteractionHand anf4 = ((this.entityData.<Byte>get(LocalPlayer.DATA_LIVING_ENTITY_FLAGS) & 0x2) > 0) ? InteractionHand.OFF_HAND : InteractionHand.MAIN_HAND;
            if (boolean3 && !this.startedUsingItem) {
                this.startUsingItem(anf4);
            }
            else if (!boolean3 && this.startedUsingItem) {
                this.stopUsingItem();
            }
        }
        if (LocalPlayer.DATA_SHARED_FLAGS_ID.equals(tq) && this.isFallFlying() && !this.wasFallFlying) {
            this.minecraft.getSoundManager().play(new ElytraOnPlayerSoundInstance(this));
        }
    }
    
    public boolean isRidingJumpable() {
        final Entity aom2 = this.getVehicle();
        return this.isPassenger() && aom2 instanceof PlayerRideableJumping && ((PlayerRideableJumping)aom2).canJump();
    }
    
    public float getJumpRidingScale() {
        return this.jumpRidingScale;
    }
    
    @Override
    public void openTextEdit(final SignBlockEntity ceh) {
        this.minecraft.setScreen(new SignEditScreen(ceh));
    }
    
    @Override
    public void openMinecartCommandBlock(final BaseCommandBlock bpc) {
        this.minecraft.setScreen(new MinecartCommandBlockEditScreen(bpc));
    }
    
    @Override
    public void openCommandBlock(final CommandBlockEntity cdq) {
        this.minecraft.setScreen(new CommandBlockEditScreen(cdq));
    }
    
    @Override
    public void openStructureBlock(final StructureBlockEntity cel) {
        this.minecraft.setScreen(new StructureBlockEditScreen(cel));
    }
    
    @Override
    public void openJigsawBlock(final JigsawBlockEntity ceb) {
        this.minecraft.setScreen(new JigsawBlockEditScreen(ceb));
    }
    
    @Override
    public void openItemGui(final ItemStack bki, final InteractionHand anf) {
        final Item bke4 = bki.getItem();
        if (bke4 == Items.WRITABLE_BOOK) {
            this.minecraft.setScreen(new BookEditScreen(this, bki, anf));
        }
    }
    
    @Override
    public void crit(final Entity aom) {
        this.minecraft.particleEngine.createTrackingEmitter(aom, ParticleTypes.CRIT);
    }
    
    @Override
    public void magicCrit(final Entity aom) {
        this.minecraft.particleEngine.createTrackingEmitter(aom, ParticleTypes.ENCHANTED_HIT);
    }
    
    @Override
    public boolean isShiftKeyDown() {
        return this.input != null && this.input.shiftKeyDown;
    }
    
    @Override
    public boolean isCrouching() {
        return this.crouching;
    }
    
    public boolean isMovingSlowly() {
        return this.isCrouching() || this.isVisuallyCrawling();
    }
    
    public void serverAiStep() {
        super.serverAiStep();
        if (this.isControlledCamera()) {
            this.xxa = this.input.leftImpulse;
            this.zza = this.input.forwardImpulse;
            this.jumping = this.input.jumping;
            this.yBobO = this.yBob;
            this.xBobO = this.xBob;
            this.xBob += (float)((this.xRot - this.xBob) * 0.5);
            this.yBob += (float)((this.yRot - this.yBob) * 0.5);
        }
    }
    
    protected boolean isControlledCamera() {
        return this.minecraft.getCameraEntity() == this;
    }
    
    @Override
    public void aiStep() {
        ++this.sprintTime;
        if (this.sprintTriggerTime > 0) {
            --this.sprintTriggerTime;
        }
        this.handleNetherPortalClient();
        final boolean boolean2 = this.input.jumping;
        final boolean boolean3 = this.input.shiftKeyDown;
        final boolean boolean4 = this.hasEnoughImpulseToStartSprinting();
        this.crouching = (!this.abilities.flying && !this.isSwimming() && this.canEnterPose(Pose.CROUCHING) && (this.isShiftKeyDown() || (!this.isSleeping() && !this.canEnterPose(Pose.STANDING))));
        this.input.tick(this.isMovingSlowly());
        this.minecraft.getTutorial().onInput(this.input);
        if (this.isUsingItem() && !this.isPassenger()) {
            final Input input = this.input;
            input.leftImpulse *= 0.2f;
            final Input input2 = this.input;
            input2.forwardImpulse *= 0.2f;
            this.sprintTriggerTime = 0;
        }
        boolean boolean5 = false;
        if (this.autoJumpTime > 0) {
            --this.autoJumpTime;
            boolean5 = true;
            this.input.jumping = true;
        }
        if (!this.noPhysics) {
            this.checkInBlock(this.getX() - this.getBbWidth() * 0.35, this.getY() + 0.5, this.getZ() + this.getBbWidth() * 0.35);
            this.checkInBlock(this.getX() - this.getBbWidth() * 0.35, this.getY() + 0.5, this.getZ() - this.getBbWidth() * 0.35);
            this.checkInBlock(this.getX() + this.getBbWidth() * 0.35, this.getY() + 0.5, this.getZ() - this.getBbWidth() * 0.35);
            this.checkInBlock(this.getX() + this.getBbWidth() * 0.35, this.getY() + 0.5, this.getZ() + this.getBbWidth() * 0.35);
        }
        if (boolean3) {
            this.sprintTriggerTime = 0;
        }
        final boolean boolean6 = this.getFoodData().getFoodLevel() > 6.0f || this.abilities.mayfly;
        if ((this.onGround || this.isUnderWater()) && !boolean3 && !boolean4 && this.hasEnoughImpulseToStartSprinting() && !this.isSprinting() && boolean6 && !this.isUsingItem() && !this.hasEffect(MobEffects.BLINDNESS)) {
            if (this.sprintTriggerTime > 0 || this.minecraft.options.keySprint.isDown()) {
                this.setSprinting(true);
            }
            else {
                this.sprintTriggerTime = 7;
            }
        }
        if (!this.isSprinting() && (!this.isInWater() || this.isUnderWater()) && this.hasEnoughImpulseToStartSprinting() && boolean6 && !this.isUsingItem() && !this.hasEffect(MobEffects.BLINDNESS) && this.minecraft.options.keySprint.isDown()) {
            this.setSprinting(true);
        }
        if (this.isSprinting()) {
            final boolean boolean7 = !this.input.hasForwardImpulse() || !boolean6;
            final boolean boolean8 = boolean7 || this.horizontalCollision || (this.isInWater() && !this.isUnderWater());
            if (this.isSwimming()) {
                if ((!this.onGround && !this.input.shiftKeyDown && boolean7) || !this.isInWater()) {
                    this.setSprinting(false);
                }
            }
            else if (boolean8) {
                this.setSprinting(false);
            }
        }
        boolean boolean7 = false;
        if (this.abilities.mayfly) {
            if (this.minecraft.gameMode.isAlwaysFlying()) {
                if (!this.abilities.flying) {
                    this.abilities.flying = true;
                    boolean7 = true;
                    this.onUpdateAbilities();
                }
            }
            else if (!boolean2 && this.input.jumping && !boolean5) {
                if (this.jumpTriggerTime == 0) {
                    this.jumpTriggerTime = 7;
                }
                else if (!this.isSwimming()) {
                    this.abilities.flying = !this.abilities.flying;
                    boolean7 = true;
                    this.onUpdateAbilities();
                    this.jumpTriggerTime = 0;
                }
            }
        }
        if (this.input.jumping && !boolean7 && !boolean2 && !this.abilities.flying && !this.isPassenger() && !this.onClimbable()) {
            final ItemStack bki8 = this.getItemBySlot(EquipmentSlot.CHEST);
            if (bki8.getItem() == Items.ELYTRA && ElytraItem.isFlyEnabled(bki8) && this.tryToStartFallFlying()) {
                this.connection.send(new ServerboundPlayerCommandPacket(this, ServerboundPlayerCommandPacket.Action.START_FALL_FLYING));
            }
        }
        this.wasFallFlying = this.isFallFlying();
        if (this.isInWater() && this.input.shiftKeyDown && this.isAffectedByFluids()) {
            this.goDownInWater();
        }
        if (this.isEyeInFluid(FluidTags.WATER)) {
            final int integer8 = this.isSpectator() ? 10 : 1;
            this.waterVisionTime = Mth.clamp(this.waterVisionTime + integer8, 0, 600);
        }
        else if (this.waterVisionTime > 0) {
            this.isEyeInFluid(FluidTags.WATER);
            this.waterVisionTime = Mth.clamp(this.waterVisionTime - 10, 0, 600);
        }
        if (this.abilities.flying && this.isControlledCamera()) {
            int integer8 = 0;
            if (this.input.shiftKeyDown) {
                --integer8;
            }
            if (this.input.jumping) {
                ++integer8;
            }
            if (integer8 != 0) {
                this.setDeltaMovement(this.getDeltaMovement().add(0.0, integer8 * this.abilities.getFlyingSpeed() * 3.0f, 0.0));
            }
        }
        if (this.isRidingJumpable()) {
            final PlayerRideableJumping api8 = (PlayerRideableJumping)this.getVehicle();
            if (this.jumpRidingTicks < 0) {
                ++this.jumpRidingTicks;
                if (this.jumpRidingTicks == 0) {
                    this.jumpRidingScale = 0.0f;
                }
            }
            if (boolean2 && !this.input.jumping) {
                this.jumpRidingTicks = -10;
                api8.onPlayerJump(Mth.floor(this.getJumpRidingScale() * 100.0f));
                this.sendRidingJump();
            }
            else if (!boolean2 && this.input.jumping) {
                this.jumpRidingTicks = 0;
                this.jumpRidingScale = 0.0f;
            }
            else if (boolean2) {
                ++this.jumpRidingTicks;
                if (this.jumpRidingTicks < 10) {
                    this.jumpRidingScale = this.jumpRidingTicks * 0.1f;
                }
                else {
                    this.jumpRidingScale = 0.8f + 2.0f / (this.jumpRidingTicks - 9) * 0.1f;
                }
            }
        }
        else {
            this.jumpRidingScale = 0.0f;
        }
        super.aiStep();
        if (this.onGround && this.abilities.flying && !this.minecraft.gameMode.isAlwaysFlying()) {
            this.abilities.flying = false;
            this.onUpdateAbilities();
        }
    }
    
    private void handleNetherPortalClient() {
        this.oPortalTime = this.portalTime;
        if (this.isInsidePortal) {
            if (this.minecraft.screen != null && !this.minecraft.screen.isPauseScreen()) {
                if (this.minecraft.screen instanceof AbstractContainerScreen) {
                    this.closeContainer();
                }
                this.minecraft.setScreen(null);
            }
            if (this.portalTime == 0.0f) {
                this.minecraft.getSoundManager().play(SimpleSoundInstance.forLocalAmbience(SoundEvents.PORTAL_TRIGGER, this.random.nextFloat() * 0.4f + 0.8f, 0.25f));
            }
            this.portalTime += 0.0125f;
            if (this.portalTime >= 1.0f) {
                this.portalTime = 1.0f;
            }
            this.isInsidePortal = false;
        }
        else if (this.hasEffect(MobEffects.CONFUSION) && this.getEffect(MobEffects.CONFUSION).getDuration() > 60) {
            this.portalTime += 0.006666667f;
            if (this.portalTime > 1.0f) {
                this.portalTime = 1.0f;
            }
        }
        else {
            if (this.portalTime > 0.0f) {
                this.portalTime -= 0.05f;
            }
            if (this.portalTime < 0.0f) {
                this.portalTime = 0.0f;
            }
        }
        this.processDimensionDelay();
    }
    
    @Override
    public void rideTick() {
        super.rideTick();
        this.handsBusy = false;
        if (this.getVehicle() instanceof Boat) {
            final Boat bft2 = (Boat)this.getVehicle();
            bft2.setInput(this.input.left, this.input.right, this.input.up, this.input.down);
            this.handsBusy |= (this.input.left || this.input.right || this.input.up || this.input.down);
        }
    }
    
    public boolean isHandsBusy() {
        return this.handsBusy;
    }
    
    @Nullable
    @Override
    public MobEffectInstance removeEffectNoUpdate(@Nullable final MobEffect aoe) {
        if (aoe == MobEffects.CONFUSION) {
            this.oPortalTime = 0.0f;
            this.portalTime = 0.0f;
        }
        return super.removeEffectNoUpdate(aoe);
    }
    
    @Override
    public void move(final MoverType apd, final Vec3 dem) {
        final double double4 = this.getX();
        final double double5 = this.getZ();
        super.move(apd, dem);
        this.updateAutoJump((float)(this.getX() - double4), (float)(this.getZ() - double5));
    }
    
    public boolean isAutoJumpEnabled() {
        return this.autoJumpEnabled;
    }
    
    protected void updateAutoJump(final float float1, final float float2) {
        if (!this.canAutoJump()) {
            return;
        }
        final Vec3 dem4 = this.position();
        final Vec3 dem5 = dem4.add(float1, 0.0, float2);
        Vec3 dem6 = new Vec3(float1, 0.0, float2);
        final float float3 = this.getSpeed();
        float float4 = (float)dem6.lengthSqr();
        if (float4 <= 0.001f) {
            final Vec2 del9 = this.input.getMoveVector();
            final float float5 = float3 * del9.x;
            final float float6 = float3 * del9.y;
            final float float7 = Mth.sin(this.yRot * 0.017453292f);
            final float float8 = Mth.cos(this.yRot * 0.017453292f);
            dem6 = new Vec3(float5 * float8 - float6 * float7, dem6.y, float6 * float8 + float5 * float7);
            float4 = (float)dem6.lengthSqr();
            if (float4 <= 0.001f) {
                return;
            }
        }
        final float float9 = Mth.fastInvSqrt(float4);
        final Vec3 dem7 = dem6.scale(float9);
        final Vec3 dem8 = this.getForward();
        final float float7 = (float)(dem8.x * dem7.x + dem8.z * dem7.z);
        if (float7 < -0.15f) {
            return;
        }
        final CollisionContext der13 = CollisionContext.of(this);
        BlockPos fu14 = new BlockPos(this.getX(), this.getBoundingBox().maxY, this.getZ());
        final BlockState cfj15 = this.level.getBlockState(fu14);
        if (!cfj15.getCollisionShape(this.level, fu14, der13).isEmpty()) {
            return;
        }
        fu14 = fu14.above();
        final BlockState cfj16 = this.level.getBlockState(fu14);
        if (!cfj16.getCollisionShape(this.level, fu14, der13).isEmpty()) {
            return;
        }
        final float float10 = 7.0f;
        float float11 = 1.2f;
        if (this.hasEffect(MobEffects.JUMP)) {
            float11 += (this.getEffect(MobEffects.JUMP).getAmplifier() + 1) * 0.75f;
        }
        final float float12 = Math.max(float3 * 7.0f, 1.0f / float9);
        Vec3 dem9 = dem4;
        Vec3 dem10 = dem5.add(dem7.scale(float12));
        final float float13 = this.getBbWidth();
        final float float14 = this.getBbHeight();
        final AABB deg24 = new AABB(dem9, dem10.add(0.0, float14, 0.0)).inflate(float13, 0.0, float13);
        dem9 = dem9.add(0.0, 0.5099999904632568, 0.0);
        dem10 = dem10.add(0.0, 0.5099999904632568, 0.0);
        final Vec3 dem11 = dem7.cross(new Vec3(0.0, 1.0, 0.0));
        final Vec3 dem12 = dem11.scale(float13 * 0.5f);
        final Vec3 dem13 = dem9.subtract(dem12);
        final Vec3 dem14 = dem10.subtract(dem12);
        final Vec3 dem15 = dem9.add(dem12);
        final Vec3 dem16 = dem10.add(dem12);
        final Iterator<AABB> iterator31 = this.level.getCollisions(this, deg24, aom -> true).flatMap(dfg -> dfg.toAabbs().stream()).iterator();
        float float15 = Float.MIN_VALUE;
        while (iterator31.hasNext()) {
            final AABB deg25 = iterator31.next();
            if (!deg25.intersects(dem13, dem14) && !deg25.intersects(dem15, dem16)) {
                continue;
            }
            float15 = (float)deg25.maxY;
            final Vec3 dem17 = deg25.getCenter();
            final BlockPos fu15 = new BlockPos(dem17);
            for (int integer37 = 1; integer37 < float11; ++integer37) {
                final BlockPos fu16 = fu15.above(integer37);
                final BlockState cfj17 = this.level.getBlockState(fu16);
                final VoxelShape dfg2;
                if (!(dfg2 = cfj17.getCollisionShape(this.level, fu16, der13)).isEmpty()) {
                    float15 = (float)dfg2.max(Direction.Axis.Y) + fu16.getY();
                    if (float15 - this.getY() > float11) {
                        return;
                    }
                }
                if (integer37 > 1) {
                    fu14 = fu14.above();
                    final BlockState cfj18 = this.level.getBlockState(fu14);
                    if (!cfj18.getCollisionShape(this.level, fu14, der13).isEmpty()) {
                        return;
                    }
                }
            }
            break;
        }
        if (float15 == Float.MIN_VALUE) {
            return;
        }
        final float float16 = (float)(float15 - this.getY());
        if (float16 <= 0.5f || float16 > float11) {
            return;
        }
        this.autoJumpTime = 1;
    }
    
    private boolean canAutoJump() {
        return this.isAutoJumpEnabled() && this.autoJumpTime <= 0 && this.onGround && !this.isStayingOnGroundSurface() && !this.isPassenger() && this.isMoving() && this.getBlockJumpFactor() >= 1.0;
    }
    
    private boolean isMoving() {
        final Vec2 del2 = this.input.getMoveVector();
        return del2.x != 0.0f || del2.y != 0.0f;
    }
    
    private boolean hasEnoughImpulseToStartSprinting() {
        final double double2 = 0.8;
        return this.isUnderWater() ? this.input.hasForwardImpulse() : (this.input.forwardImpulse >= 0.8);
    }
    
    public float getWaterVision() {
        if (!this.isEyeInFluid(FluidTags.WATER)) {
            return 0.0f;
        }
        final float float2 = 600.0f;
        final float float3 = 100.0f;
        if (this.waterVisionTime >= 600.0f) {
            return 1.0f;
        }
        final float float4 = Mth.clamp(this.waterVisionTime / 100.0f, 0.0f, 1.0f);
        final float float5 = (this.waterVisionTime < 100.0f) ? 0.0f : Mth.clamp((this.waterVisionTime - 100.0f) / 500.0f, 0.0f, 1.0f);
        return float4 * 0.6f + float5 * 0.39999998f;
    }
    
    @Override
    public boolean isUnderWater() {
        return this.wasUnderwater;
    }
    
    @Override
    protected boolean updateIsUnderwater() {
        final boolean boolean2 = this.wasUnderwater;
        final boolean boolean3 = super.updateIsUnderwater();
        if (this.isSpectator()) {
            return this.wasUnderwater;
        }
        if (!boolean2 && boolean3) {
            this.level.playLocalSound(this.getX(), this.getY(), this.getZ(), SoundEvents.AMBIENT_UNDERWATER_ENTER, SoundSource.AMBIENT, 1.0f, 1.0f, false);
            this.minecraft.getSoundManager().play(new UnderwaterAmbientSoundInstances.UnderwaterAmbientSoundInstance(this));
        }
        if (boolean2 && !boolean3) {
            this.level.playLocalSound(this.getX(), this.getY(), this.getZ(), SoundEvents.AMBIENT_UNDERWATER_EXIT, SoundSource.AMBIENT, 1.0f, 1.0f, false);
        }
        return this.wasUnderwater;
    }
}
