package net.minecraft.server.network;

import net.minecraft.world.level.block.state.AbstractStateHolder;
import org.apache.logging.log4j.LogManager;
import com.mojang.brigadier.suggestion.Suggestions;
import net.minecraft.network.protocol.game.ServerboundLockDifficultyPacket;
import net.minecraft.network.protocol.game.ServerboundChangeDifficultyPacket;
import net.minecraft.network.protocol.game.ServerboundCustomPayloadPacket;
import net.minecraft.network.protocol.game.ServerboundClientInformationPacket;
import net.minecraft.network.protocol.game.ServerboundPlayerAbilitiesPacket;
import net.minecraft.network.protocol.game.ServerboundKeepAlivePacket;
import net.minecraft.world.level.block.entity.SignBlockEntity;
import net.minecraft.network.protocol.game.ServerboundSignUpdatePacket;
import net.minecraft.network.protocol.game.ServerboundContainerAckPacket;
import net.minecraft.network.protocol.game.ServerboundSetCreativeModeSlotPacket;
import net.minecraft.network.protocol.game.ServerboundContainerButtonClickPacket;
import net.minecraft.world.inventory.RecipeBookMenu;
import net.minecraft.network.protocol.game.ServerboundPlaceRecipePacket;
import net.minecraft.network.protocol.game.ClientboundContainerAckPacket;
import net.minecraft.world.inventory.Slot;
import net.minecraft.core.NonNullList;
import net.minecraft.network.protocol.game.ServerboundContainerClickPacket;
import net.minecraft.network.protocol.game.ServerboundContainerClosePacket;
import net.minecraft.advancements.CriteriaTriggers;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.network.protocol.game.ServerboundClientCommandPacket;
import net.minecraft.world.entity.projectile.AbstractArrow;
import net.minecraft.world.entity.ExperienceOrb;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.network.protocol.game.ServerboundInteractPacket;
import net.minecraft.world.entity.animal.horse.AbstractHorse;
import net.minecraft.world.entity.PlayerRideableJumping;
import net.minecraft.network.protocol.game.ServerboundPlayerCommandPacket;
import net.minecraft.network.protocol.game.ServerboundSwingPacket;
import org.apache.commons.lang3.StringUtils;
import net.minecraft.network.protocol.game.ServerboundChatPacket;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.network.protocol.game.ServerboundSetCarriedItemPacket;
import net.minecraft.CrashReportCategory;
import net.minecraft.ReportedException;
import net.minecraft.CrashReport;
import net.minecraft.world.entity.player.ChatVisiblity;
import javax.annotation.Nullable;
import net.minecraft.world.entity.vehicle.Boat;
import net.minecraft.network.protocol.game.ServerboundPaddleBoatPacket;
import net.minecraft.network.protocol.game.ServerboundResourcePackPacket;
import java.util.Iterator;
import net.minecraft.network.protocol.game.ServerboundTeleportToEntityPacket;
import net.minecraft.network.protocol.game.ServerboundUseItemPacket;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket;
import net.minecraft.network.protocol.game.ClientboundChatPacket;
import net.minecraft.network.chat.ChatType;
import net.minecraft.ChatFormatting;
import net.minecraft.world.level.Level;
import net.minecraft.world.entity.player.Player;
import net.minecraft.network.protocol.game.ServerboundUseItemOnPacket;
import net.minecraft.world.InteractionHand;
import net.minecraft.network.protocol.game.ServerboundPlayerActionPacket;
import java.util.Set;
import net.minecraft.network.protocol.game.ClientboundPlayerPositionPacket;
import java.util.Collections;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.level.GameType;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.GameRules;
import net.minecraft.network.protocol.game.ServerboundBlockEntityTagQuery;
import net.minecraft.network.protocol.game.ClientboundTagQueryPacket;
import net.minecraft.network.protocol.game.ServerboundEntityTagQuery;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.nbt.Tag;
import net.minecraft.nbt.StringTag;
import net.minecraft.world.level.ItemLike;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.WritableBookItem;
import net.minecraft.network.protocol.game.ServerboundEditBookPacket;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.MerchantMenu;
import net.minecraft.network.protocol.game.ServerboundSelectTradePacket;
import net.minecraft.world.level.block.entity.JigsawBlockEntity;
import net.minecraft.network.protocol.game.ServerboundSetJigsawBlockPacket;
import net.minecraft.world.level.block.entity.StructureBlockEntity;
import net.minecraft.network.protocol.game.ServerboundSetStructureBlockPacket;
import net.minecraft.world.inventory.BeaconMenu;
import net.minecraft.network.protocol.game.ServerboundSetBeaconPacket;
import net.minecraft.SharedConstants;
import net.minecraft.world.inventory.AnvilMenu;
import net.minecraft.network.protocol.game.ServerboundRenameItemPacket;
import net.minecraft.network.protocol.game.ClientboundSetCarriedItemPacket;
import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket;
import net.minecraft.network.protocol.game.ServerboundPickItemPacket;
import net.minecraft.network.protocol.game.ServerboundSetCommandMinecartPacket;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BaseCommandBlock;
import net.minecraft.util.StringUtil;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.block.CommandBlock;
import net.minecraft.core.Direction;
import net.minecraft.world.level.block.entity.CommandBlockEntity;
import net.minecraft.network.protocol.game.ServerboundSetCommandBlockPacket;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.network.protocol.game.ClientboundCommandSuggestionsPacket;
import com.mojang.brigadier.ParseResults;
import com.mojang.brigadier.StringReader;
import net.minecraft.network.protocol.game.ServerboundCommandSuggestionPacket;
import net.minecraft.advancements.Advancement;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.network.protocol.game.ServerboundSeenAdvancementsPacket;
import net.minecraft.world.item.crafting.Recipe;
import java.util.function.Consumer;
import net.minecraft.network.protocol.game.ServerboundRecipeBookUpdatePacket;
import net.minecraft.network.protocol.game.ServerboundAcceptTeleportationPacket;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.MoverType;
import net.minecraft.network.protocol.game.ClientboundMoveVehiclePacket;
import net.minecraft.network.protocol.game.ServerboundMoveVehiclePacket;
import com.google.common.primitives.Floats;
import com.google.common.primitives.Doubles;
import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket;
import net.minecraft.network.protocol.PacketUtils;
import net.minecraft.network.protocol.game.ServerboundPlayerInputPacket;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import net.minecraft.network.protocol.game.ClientboundDisconnectPacket;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientboundKeepAlivePacket;
import net.minecraft.Util;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.network.PacketListener;
import it.unimi.dsi.fastutil.ints.Int2ShortOpenHashMap;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.entity.Entity;
import it.unimi.dsi.fastutil.ints.Int2ShortMap;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.MinecraftServer;
import net.minecraft.network.Connection;
import org.apache.logging.log4j.Logger;
import net.minecraft.network.protocol.game.ServerGamePacketListener;

public class ServerGamePacketListenerImpl implements ServerGamePacketListener {
    private static final Logger LOGGER;
    public final Connection connection;
    private final MinecraftServer server;
    public ServerPlayer player;
    private int tickCount;
    private long keepAliveTime;
    private boolean keepAlivePending;
    private long keepAliveChallenge;
    private int chatSpamTickCount;
    private int dropSpamTickCount;
    private final Int2ShortMap expectedAcks;
    private double firstGoodX;
    private double firstGoodY;
    private double firstGoodZ;
    private double lastGoodX;
    private double lastGoodY;
    private double lastGoodZ;
    private Entity lastVehicle;
    private double vehicleFirstGoodX;
    private double vehicleFirstGoodY;
    private double vehicleFirstGoodZ;
    private double vehicleLastGoodX;
    private double vehicleLastGoodY;
    private double vehicleLastGoodZ;
    private Vec3 awaitingPositionFromClient;
    private int awaitingTeleport;
    private int awaitingTeleportTime;
    private boolean clientIsFloating;
    private int aboveGroundTickCount;
    private boolean clientVehicleIsFloating;
    private int aboveGroundVehicleTickCount;
    private int receivedMovePacketCount;
    private int knownMovePacketCount;
    
    public ServerGamePacketListenerImpl(final MinecraftServer minecraftServer, final Connection kt, final ServerPlayer xe) {
        this.expectedAcks = (Int2ShortMap)new Int2ShortOpenHashMap();
        this.server = minecraftServer;
        (this.connection = kt).setListener(this);
        this.player = xe;
        xe.connection = this;
    }
    
    public void tick() {
        this.resetPosition();
        this.player.xo = this.player.getX();
        this.player.yo = this.player.getY();
        this.player.zo = this.player.getZ();
        this.player.doTick();
        this.player.absMoveTo(this.firstGoodX, this.firstGoodY, this.firstGoodZ, this.player.yRot, this.player.xRot);
        ++this.tickCount;
        this.knownMovePacketCount = this.receivedMovePacketCount;
        if (this.clientIsFloating) {
            if (++this.aboveGroundTickCount > 80) {
                ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked for floating too long!", this.player.getName().getString());
                this.disconnect(new TranslatableComponent("multiplayer.disconnect.flying", new Object[0]));
                return;
            }
        }
        else {
            this.clientIsFloating = false;
            this.aboveGroundTickCount = 0;
        }
        this.lastVehicle = this.player.getRootVehicle();
        if (this.lastVehicle == this.player || this.lastVehicle.getControllingPassenger() != this.player) {
            this.lastVehicle = null;
            this.clientVehicleIsFloating = false;
            this.aboveGroundVehicleTickCount = 0;
        }
        else {
            this.vehicleFirstGoodX = this.lastVehicle.getX();
            this.vehicleFirstGoodY = this.lastVehicle.getY();
            this.vehicleFirstGoodZ = this.lastVehicle.getZ();
            this.vehicleLastGoodX = this.lastVehicle.getX();
            this.vehicleLastGoodY = this.lastVehicle.getY();
            this.vehicleLastGoodZ = this.lastVehicle.getZ();
            if (this.clientVehicleIsFloating && this.player.getRootVehicle().getControllingPassenger() == this.player) {
                if (++this.aboveGroundVehicleTickCount > 80) {
                    ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked for floating a vehicle too long!", this.player.getName().getString());
                    this.disconnect(new TranslatableComponent("multiplayer.disconnect.flying", new Object[0]));
                    return;
                }
            }
            else {
                this.clientVehicleIsFloating = false;
                this.aboveGroundVehicleTickCount = 0;
            }
        }
        this.server.getProfiler().push("keepAlive");
        final long long2 = Util.getMillis();
        if (long2 - this.keepAliveTime >= 15000L) {
            if (this.keepAlivePending) {
                this.disconnect(new TranslatableComponent("disconnect.timeout", new Object[0]));
            }
            else {
                this.keepAlivePending = true;
                this.keepAliveTime = long2;
                this.keepAliveChallenge = long2;
                this.send(new ClientboundKeepAlivePacket(this.keepAliveChallenge));
            }
        }
        this.server.getProfiler().pop();
        if (this.chatSpamTickCount > 0) {
            --this.chatSpamTickCount;
        }
        if (this.dropSpamTickCount > 0) {
            --this.dropSpamTickCount;
        }
        if (this.player.getLastActionTime() > 0L && this.server.getPlayerIdleTimeout() > 0 && Util.getMillis() - this.player.getLastActionTime() > this.server.getPlayerIdleTimeout() * 1000 * 60) {
            this.disconnect(new TranslatableComponent("multiplayer.disconnect.idling", new Object[0]));
        }
    }
    
    public void resetPosition() {
        this.firstGoodX = this.player.getX();
        this.firstGoodY = this.player.getY();
        this.firstGoodZ = this.player.getZ();
        this.lastGoodX = this.player.getX();
        this.lastGoodY = this.player.getY();
        this.lastGoodZ = this.player.getZ();
    }
    
    @Override
    public Connection getConnection() {
        return this.connection;
    }
    
    private boolean isSingleplayerOwner() {
        return this.server.isSingleplayerOwner(this.player.getGameProfile());
    }
    
    public void disconnect(final Component lf) {
        this.connection.send(new ClientboundDisconnectPacket(lf), (future -> this.connection.disconnect(lf)));
        this.connection.setReadOnly();
        this.server.executeBlocking(this.connection::handleDisconnection);
    }
    
    @Override
    public void handlePlayerInput(final ServerboundPlayerInputPacket ql) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)ql, this, this.player.getLevel());
        this.player.setPlayerInput(ql.getXxa(), ql.getZza(), ql.isJumping(), ql.isShiftKeyDown());
    }
    
    private static boolean containsInvalidValues(final ServerboundMovePlayerPacket qd) {
        return !Doubles.isFinite(qd.getX(0.0)) || !Doubles.isFinite(qd.getY(0.0)) || !Doubles.isFinite(qd.getZ(0.0)) || !Floats.isFinite(qd.getXRot(0.0f)) || !Floats.isFinite(qd.getYRot(0.0f)) || (Math.abs(qd.getX(0.0)) > 3.0E7 || Math.abs(qd.getY(0.0)) > 3.0E7 || Math.abs(qd.getZ(0.0)) > 3.0E7);
    }
    
    private static boolean containsInvalidValues(final ServerboundMoveVehiclePacket qe) {
        return !Doubles.isFinite(qe.getX()) || !Doubles.isFinite(qe.getY()) || !Doubles.isFinite(qe.getZ()) || !Floats.isFinite(qe.getXRot()) || !Floats.isFinite(qe.getYRot());
    }
    
    @Override
    public void handleMoveVehicle(final ServerboundMoveVehiclePacket qe) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)qe, this, this.player.getLevel());
        if (containsInvalidValues(qe)) {
            this.disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_vehicle_movement", new Object[0]));
            return;
        }
        final Entity akq3 = this.player.getRootVehicle();
        if (akq3 != this.player && akq3.getControllingPassenger() == this.player && akq3 == this.lastVehicle) {
            final ServerLevel xd4 = this.player.getLevel();
            final double double5 = akq3.getX();
            final double double6 = akq3.getY();
            final double double7 = akq3.getZ();
            final double double8 = qe.getX();
            final double double9 = qe.getY();
            final double double10 = qe.getZ();
            final float float17 = qe.getYRot();
            final float float18 = qe.getXRot();
            double double11 = double8 - this.vehicleFirstGoodX;
            double double12 = double9 - this.vehicleFirstGoodY;
            double double13 = double10 - this.vehicleFirstGoodZ;
            final double double14 = akq3.getDeltaMovement().lengthSqr();
            double double15 = double11 * double11 + double12 * double12 + double13 * double13;
            if (double15 - double14 > 100.0 && !this.isSingleplayerOwner()) {
                ServerGamePacketListenerImpl.LOGGER.warn("{} (vehicle of {}) moved too quickly! {},{},{}", akq3.getName().getString(), this.player.getName().getString(), double11, double12, double13);
                this.connection.send(new ClientboundMoveVehiclePacket(akq3));
                return;
            }
            final boolean boolean29 = xd4.noCollision(akq3, akq3.getBoundingBox().deflate(0.0625));
            double11 = double8 - this.vehicleLastGoodX;
            double12 = double9 - this.vehicleLastGoodY - 1.0E-6;
            double13 = double10 - this.vehicleLastGoodZ;
            akq3.move(MoverType.PLAYER, new Vec3(double11, double12, double13));
            final double double16 = double12;
            double11 = double8 - akq3.getX();
            double12 = double9 - akq3.getY();
            if (double12 > -0.5 || double12 < 0.5) {
                double12 = 0.0;
            }
            double13 = double10 - akq3.getZ();
            double15 = double11 * double11 + double12 * double12 + double13 * double13;
            boolean boolean30 = false;
            if (double15 > 0.0625) {
                boolean30 = true;
                ServerGamePacketListenerImpl.LOGGER.warn("{} moved wrongly!", akq3.getName().getString());
            }
            akq3.absMoveTo(double8, double9, double10, float17, float18);
            final boolean boolean31 = xd4.noCollision(akq3, akq3.getBoundingBox().deflate(0.0625));
            if (boolean29 && (boolean30 || !boolean31)) {
                akq3.absMoveTo(double5, double6, double7, float17, float18);
                this.connection.send(new ClientboundMoveVehiclePacket(akq3));
                return;
            }
            this.player.getLevel().getChunkSource().move(this.player);
            this.player.checkMovementStatistics(this.player.getX() - double5, this.player.getY() - double6, this.player.getZ() - double7);
            this.clientVehicleIsFloating = (double16 >= -0.03125 && !this.server.isFlightAllowed() && !xd4.containsAnyBlocks(akq3.getBoundingBox().inflate(0.0625).expandTowards(0.0, -0.55, 0.0)));
            this.vehicleLastGoodX = akq3.getX();
            this.vehicleLastGoodY = akq3.getY();
            this.vehicleLastGoodZ = akq3.getZ();
        }
    }
    
    @Override
    public void handleAcceptTeleportPacket(final ServerboundAcceptTeleportationPacket pm) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)pm, this, this.player.getLevel());
        if (pm.getId() == this.awaitingTeleport) {
            this.player.absMoveTo(this.awaitingPositionFromClient.x, this.awaitingPositionFromClient.y, this.awaitingPositionFromClient.z, this.player.yRot, this.player.xRot);
            this.lastGoodX = this.awaitingPositionFromClient.x;
            this.lastGoodY = this.awaitingPositionFromClient.y;
            this.lastGoodZ = this.awaitingPositionFromClient.z;
            if (this.player.isChangingDimension()) {
                this.player.hasChangedDimension();
            }
            this.awaitingPositionFromClient = null;
        }
    }
    
    @Override
    public void handleRecipeBookUpdatePacket(final ServerboundRecipeBookUpdatePacket qm) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)qm, this, this.player.getLevel());
        if (qm.getPurpose() == ServerboundRecipeBookUpdatePacket.Purpose.SHOWN) {
            this.server.getRecipeManager().byKey(qm.getRecipe()).ifPresent(this.player.getRecipeBook()::removeHighlight);
        }
        else if (qm.getPurpose() == ServerboundRecipeBookUpdatePacket.Purpose.SETTINGS) {
            this.player.getRecipeBook().setGuiOpen(qm.isGuiOpen());
            this.player.getRecipeBook().setFilteringCraftable(qm.isFilteringCraftable());
            this.player.getRecipeBook().setFurnaceGuiOpen(qm.isFurnaceGuiOpen());
            this.player.getRecipeBook().setFurnaceFilteringCraftable(qm.isFurnaceFilteringCraftable());
            this.player.getRecipeBook().setBlastingFurnaceGuiOpen(qm.isBlastFurnaceGuiOpen());
            this.player.getRecipeBook().setBlastingFurnaceFilteringCraftable(qm.isBlastFurnaceFilteringCraftable());
            this.player.getRecipeBook().setSmokerGuiOpen(qm.isSmokerGuiOpen());
            this.player.getRecipeBook().setSmokerFilteringCraftable(qm.isSmokerFilteringCraftable());
        }
    }
    
    @Override
    public void handleSeenAdvancements(final ServerboundSeenAdvancementsPacket qp) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)qp, this, this.player.getLevel());
        if (qp.getAction() == ServerboundSeenAdvancementsPacket.Action.OPENED_TAB) {
            final ResourceLocation sm3 = qp.getTab();
            final Advancement u4 = this.server.getAdvancements().getAdvancement(sm3);
            if (u4 != null) {
                this.player.getAdvancements().setSelectedTab(u4);
            }
        }
    }
    
    @Override
    public void handleCustomCommandSuggestions(final ServerboundCommandSuggestionPacket ps) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)ps, this, this.player.getLevel());
        final StringReader stringReader3 = new StringReader(ps.getCommand());
        if (stringReader3.canRead() && stringReader3.peek() == '/') {
            stringReader3.skip();
        }
        final ParseResults<CommandSourceStack> parseResults4 = (ParseResults<CommandSourceStack>)this.server.getCommands().getDispatcher().parse(stringReader3, this.player.createCommandSourceStack());
        this.server.getCommands().getDispatcher().getCompletionSuggestions((ParseResults)parseResults4).thenAccept(suggestions -> this.connection.send(new ClientboundCommandSuggestionsPacket(ps.getId(), suggestions)));
    }
    
    @Override
    public void handleSetCommandBlock(final ServerboundSetCommandBlockPacket qt) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)qt, this, this.player.getLevel());
        if (!this.server.isCommandBlockEnabled()) {
            this.player.sendMessage(new TranslatableComponent("advMode.notEnabled", new Object[0]));
            return;
        }
        if (!this.player.canUseGameMasterBlocks()) {
            this.player.sendMessage(new TranslatableComponent("advMode.notAllowed", new Object[0]));
            return;
        }
        BaseCommandBlock bjc3 = null;
        CommandBlockEntity bwq4 = null;
        final BlockPos fk5 = qt.getPos();
        final BlockEntity bwl6 = this.player.level.getBlockEntity(fk5);
        if (bwl6 instanceof CommandBlockEntity) {
            bwq4 = (CommandBlockEntity)bwl6;
            bjc3 = bwq4.getCommandBlock();
        }
        final String string7 = qt.getCommand();
        final boolean boolean8 = qt.isTrackOutput();
        if (bjc3 != null) {
            final CommandBlockEntity.Mode a9 = bwq4.getMode();
            final Direction fp10 = this.player.level.getBlockState(fk5).<Direction>getValue((Property<Direction>)CommandBlock.FACING);
            switch (qt.getMode()) {
                case SEQUENCE: {
                    final BlockState byj11 = Blocks.CHAIN_COMMAND_BLOCK.defaultBlockState();
                    this.player.level.setBlock(fk5, (((AbstractStateHolder<O, BlockState>)byj11).setValue((Property<Comparable>)CommandBlock.FACING, fp10)).<Comparable, Boolean>setValue((Property<Comparable>)CommandBlock.CONDITIONAL, qt.isConditional()), 2);
                    break;
                }
                case AUTO: {
                    final BlockState byj11 = Blocks.REPEATING_COMMAND_BLOCK.defaultBlockState();
                    this.player.level.setBlock(fk5, (((AbstractStateHolder<O, BlockState>)byj11).setValue((Property<Comparable>)CommandBlock.FACING, fp10)).<Comparable, Boolean>setValue((Property<Comparable>)CommandBlock.CONDITIONAL, qt.isConditional()), 2);
                    break;
                }
                default: {
                    final BlockState byj11 = Blocks.COMMAND_BLOCK.defaultBlockState();
                    this.player.level.setBlock(fk5, (((AbstractStateHolder<O, BlockState>)byj11).setValue((Property<Comparable>)CommandBlock.FACING, fp10)).<Comparable, Boolean>setValue((Property<Comparable>)CommandBlock.CONDITIONAL, qt.isConditional()), 2);
                    break;
                }
            }
            bwl6.clearRemoved();
            this.player.level.setBlockEntity(fk5, bwl6);
            bjc3.setCommand(string7);
            bjc3.setTrackOutput(boolean8);
            if (!boolean8) {
                bjc3.setLastOutput(null);
            }
            bwq4.setAutomatic(qt.isAutomatic());
            if (a9 != qt.getMode()) {
                bwq4.onModeSwitch();
            }
            bjc3.onUpdated();
            if (!StringUtil.isNullOrEmpty(string7)) {
                this.player.sendMessage(new TranslatableComponent("advMode.setCommand.success", new Object[] { string7 }));
            }
        }
    }
    
    @Override
    public void handleSetCommandMinecart(final ServerboundSetCommandMinecartPacket qu) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)qu, this, this.player.getLevel());
        if (!this.server.isCommandBlockEnabled()) {
            this.player.sendMessage(new TranslatableComponent("advMode.notEnabled", new Object[0]));
            return;
        }
        if (!this.player.canUseGameMasterBlocks()) {
            this.player.sendMessage(new TranslatableComponent("advMode.notAllowed", new Object[0]));
            return;
        }
        final BaseCommandBlock bjc3 = qu.getCommandBlock(this.player.level);
        if (bjc3 != null) {
            bjc3.setCommand(qu.getCommand());
            bjc3.setTrackOutput(qu.isTrackOutput());
            if (!qu.isTrackOutput()) {
                bjc3.setLastOutput(null);
            }
            bjc3.onUpdated();
            this.player.sendMessage(new TranslatableComponent("advMode.setCommand.success", new Object[] { qu.getCommand() }));
        }
    }
    
    @Override
    public void handlePickItem(final ServerboundPickItemPacket qg) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)qg, this, this.player.getLevel());
        this.player.inventory.pickSlot(qg.getSlot());
        this.player.connection.send(new ClientboundContainerSetSlotPacket(-2, this.player.inventory.selected, this.player.inventory.getItem(this.player.inventory.selected)));
        this.player.connection.send(new ClientboundContainerSetSlotPacket(-2, qg.getSlot(), this.player.inventory.getItem(qg.getSlot())));
        this.player.connection.send(new ClientboundSetCarriedItemPacket(this.player.inventory.selected));
    }
    
    @Override
    public void handleRenameItem(final ServerboundRenameItemPacket qn) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)qn, this, this.player.getLevel());
        if (this.player.containerMenu instanceof AnvilMenu) {
            final AnvilMenu bap3 = (AnvilMenu)this.player.containerMenu;
            final String string4 = SharedConstants.filterText(qn.getName());
            if (string4.length() <= 35) {
                bap3.setItemName(string4);
            }
        }
    }
    
    @Override
    public void handleSetBeaconPacket(final ServerboundSetBeaconPacket qr) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)qr, this, this.player.getLevel());
        if (this.player.containerMenu instanceof BeaconMenu) {
            ((BeaconMenu)this.player.containerMenu).updateEffects(qr.getPrimary(), qr.getSecondary());
        }
    }
    
    @Override
    public void handleSetStructureBlock(final ServerboundSetStructureBlockPacket qx) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)qx, this, this.player.getLevel());
        if (!this.player.canUseGameMasterBlocks()) {
            return;
        }
        final BlockPos fk3 = qx.getPos();
        final BlockState byj4 = this.player.level.getBlockState(fk3);
        final BlockEntity bwl5 = this.player.level.getBlockEntity(fk3);
        if (bwl5 instanceof StructureBlockEntity) {
            final StructureBlockEntity bxl6 = (StructureBlockEntity)bwl5;
            bxl6.setMode(qx.getMode());
            bxl6.setStructureName(qx.getName());
            bxl6.setStructurePos(qx.getOffset());
            bxl6.setStructureSize(qx.getSize());
            bxl6.setMirror(qx.getMirror());
            bxl6.setRotation(qx.getRotation());
            bxl6.setMetaData(qx.getData());
            bxl6.setIgnoreEntities(qx.isIgnoreEntities());
            bxl6.setShowAir(qx.isShowAir());
            bxl6.setShowBoundingBox(qx.isShowBoundingBox());
            bxl6.setIntegrity(qx.getIntegrity());
            bxl6.setSeed(qx.getSeed());
            if (bxl6.hasStructureName()) {
                final String string7 = bxl6.getStructureName();
                if (qx.getUpdateType() == StructureBlockEntity.UpdateType.SAVE_AREA) {
                    if (bxl6.saveStructure()) {
                        this.player.displayClientMessage(new TranslatableComponent("structure_block.save_success", new Object[] { string7 }), false);
                    }
                    else {
                        this.player.displayClientMessage(new TranslatableComponent("structure_block.save_failure", new Object[] { string7 }), false);
                    }
                }
                else if (qx.getUpdateType() == StructureBlockEntity.UpdateType.LOAD_AREA) {
                    if (!bxl6.isStructureLoadable()) {
                        this.player.displayClientMessage(new TranslatableComponent("structure_block.load_not_found", new Object[] { string7 }), false);
                    }
                    else if (bxl6.loadStructure()) {
                        this.player.displayClientMessage(new TranslatableComponent("structure_block.load_success", new Object[] { string7 }), false);
                    }
                    else {
                        this.player.displayClientMessage(new TranslatableComponent("structure_block.load_prepare", new Object[] { string7 }), false);
                    }
                }
                else if (qx.getUpdateType() == StructureBlockEntity.UpdateType.SCAN_AREA) {
                    if (bxl6.detectSize()) {
                        this.player.displayClientMessage(new TranslatableComponent("structure_block.size_success", new Object[] { string7 }), false);
                    }
                    else {
                        this.player.displayClientMessage(new TranslatableComponent("structure_block.size_failure", new Object[0]), false);
                    }
                }
            }
            else {
                this.player.displayClientMessage(new TranslatableComponent("structure_block.invalid_structure_name", new Object[] { qx.getName() }), false);
            }
            bxl6.setChanged();
            this.player.level.sendBlockUpdated(fk3, byj4, byj4, 3);
        }
    }
    
    @Override
    public void handleSetJigsawBlock(final ServerboundSetJigsawBlockPacket qw) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)qw, this, this.player.getLevel());
        if (!this.player.canUseGameMasterBlocks()) {
            return;
        }
        final BlockPos fk3 = qw.getPos();
        final BlockState byj4 = this.player.level.getBlockState(fk3);
        final BlockEntity bwl5 = this.player.level.getBlockEntity(fk3);
        if (bwl5 instanceof JigsawBlockEntity) {
            final JigsawBlockEntity bxb6 = (JigsawBlockEntity)bwl5;
            bxb6.setAttachementType(qw.getAttachementType());
            bxb6.setTargetPool(qw.getTargetPool());
            bxb6.setFinalState(qw.getFinalState());
            bxb6.setChanged();
            this.player.level.sendBlockUpdated(fk3, byj4, byj4, 3);
        }
    }
    
    @Override
    public void handleSelectTrade(final ServerboundSelectTradePacket qq) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)qq, this, this.player.getLevel());
        final int integer3 = qq.getItem();
        final AbstractContainerMenu ban4 = this.player.containerMenu;
        if (ban4 instanceof MerchantMenu) {
            final MerchantMenu bbq5 = (MerchantMenu)ban4;
            bbq5.setSelectionHint(integer3);
            bbq5.tryMoveItems(integer3);
        }
    }
    
    @Override
    public void handleEditBook(final ServerboundEditBookPacket py) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)py, this, this.player.getLevel());
        final ItemStack ben3 = py.getBook();
        if (ben3.isEmpty()) {
            return;
        }
        if (!WritableBookItem.makeSureTagIsValid(ben3.getTag())) {
            return;
        }
        final ItemStack ben4 = this.player.getItemInHand(py.getHand());
        if (ben3.getItem() == Items.WRITABLE_BOOK && ben4.getItem() == Items.WRITABLE_BOOK) {
            if (py.isSigning()) {
                final ItemStack ben5 = new ItemStack(Items.WRITTEN_BOOK);
                final CompoundTag jt6 = ben4.getTag();
                if (jt6 != null) {
                    ben5.setTag(jt6.copy());
                }
                ben5.addTagElement("author", StringTag.valueOf(this.player.getName().getString()));
                ben5.addTagElement("title", StringTag.valueOf(ben3.getTag().getString("title")));
                final ListTag jz7 = ben3.getTag().getList("pages", 8);
                for (int integer8 = 0; integer8 < jz7.size(); ++integer8) {
                    String string9 = jz7.getString(integer8);
                    final Component lf10 = new TextComponent(string9);
                    string9 = Component.Serializer.toJson(lf10);
                    jz7.set(integer8, StringTag.valueOf(string9));
                }
                ben5.addTagElement("pages", jz7);
                this.player.setItemInHand(py.getHand(), ben5);
            }
            else {
                ben4.addTagElement("pages", ben3.getTag().getList("pages", 8));
            }
        }
    }
    
    @Override
    public void handleEntityTagQuery(final ServerboundEntityTagQuery pz) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)pz, this, this.player.getLevel());
        if (!this.player.hasPermissions(2)) {
            return;
        }
        final Entity akq3 = this.player.getLevel().getEntity(pz.getEntityId());
        if (akq3 != null) {
            final CompoundTag jt4 = akq3.saveWithoutId(new CompoundTag());
            this.player.connection.send(new ClientboundTagQueryPacket(pz.getTransactionId(), jt4));
        }
    }
    
    @Override
    public void handleBlockEntityTagQuery(final ServerboundBlockEntityTagQuery pn) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)pn, this, this.player.getLevel());
        if (!this.player.hasPermissions(2)) {
            return;
        }
        final BlockEntity bwl3 = this.player.getLevel().getBlockEntity(pn.getPos());
        final CompoundTag jt4 = (bwl3 != null) ? bwl3.save(new CompoundTag()) : null;
        this.player.connection.send(new ClientboundTagQueryPacket(pn.getTransactionId(), jt4));
    }
    
    @Override
    public void handleMovePlayer(final ServerboundMovePlayerPacket qd) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)qd, this, this.player.getLevel());
        if (containsInvalidValues(qd)) {
            this.disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_player_movement", new Object[0]));
            return;
        }
        final ServerLevel xd3 = this.server.getLevel(this.player.dimension);
        if (this.player.wonGame) {
            return;
        }
        if (this.tickCount == 0) {
            this.resetPosition();
        }
        if (this.awaitingPositionFromClient != null) {
            if (this.tickCount - this.awaitingTeleportTime > 20) {
                this.awaitingTeleportTime = this.tickCount;
                this.teleport(this.awaitingPositionFromClient.x, this.awaitingPositionFromClient.y, this.awaitingPositionFromClient.z, this.player.yRot, this.player.xRot);
            }
            return;
        }
        this.awaitingTeleportTime = this.tickCount;
        if (this.player.isPassenger()) {
            this.player.absMoveTo(this.player.getX(), this.player.getY(), this.player.getZ(), qd.getYRot(this.player.yRot), qd.getXRot(this.player.xRot));
            this.player.getLevel().getChunkSource().move(this.player);
            return;
        }
        final double double4 = this.player.getX();
        final double double5 = this.player.getY();
        final double double6 = this.player.getZ();
        final double double7 = this.player.getY();
        final double double8 = qd.getX(this.player.getX());
        final double double9 = qd.getY(this.player.getY());
        final double double10 = qd.getZ(this.player.getZ());
        final float float18 = qd.getYRot(this.player.yRot);
        final float float19 = qd.getXRot(this.player.xRot);
        double double11 = double8 - this.firstGoodX;
        double double12 = double9 - this.firstGoodY;
        double double13 = double10 - this.firstGoodZ;
        final double double14 = this.player.getDeltaMovement().lengthSqr();
        double double15 = double11 * double11 + double12 * double12 + double13 * double13;
        if (this.player.isSleeping()) {
            if (double15 > 1.0) {
                this.teleport(this.player.getX(), this.player.getY(), this.player.getZ(), qd.getYRot(this.player.yRot), qd.getXRot(this.player.xRot));
            }
            return;
        }
        ++this.receivedMovePacketCount;
        int integer30 = this.receivedMovePacketCount - this.knownMovePacketCount;
        if (integer30 > 5) {
            ServerGamePacketListenerImpl.LOGGER.debug("{} is sending move packets too frequently ({} packets since last tick)", this.player.getName().getString(), integer30);
            integer30 = 1;
        }
        if (!this.player.isChangingDimension()) {
            if (!this.player.getLevel().getGameRules().getBoolean(GameRules.RULE_DISABLE_ELYTRA_MOVEMENT_CHECK) || !this.player.isFallFlying()) {
                final float float20 = this.player.isFallFlying() ? 300.0f : 100.0f;
                if (double15 - double14 > float20 * integer30 && !this.isSingleplayerOwner()) {
                    ServerGamePacketListenerImpl.LOGGER.warn("{} moved too quickly! {},{},{}", this.player.getName().getString(), double11, double12, double13);
                    this.teleport(this.player.getX(), this.player.getY(), this.player.getZ(), this.player.yRot, this.player.xRot);
                    return;
                }
            }
        }
        final boolean boolean31 = this.isPlayerCollidingWithAnything(xd3);
        double11 = double8 - this.lastGoodX;
        double12 = double9 - this.lastGoodY;
        double13 = double10 - this.lastGoodZ;
        if (double12 > 0.0) {
            this.player.fallDistance = 0.0f;
        }
        if (this.player.onGround && !qd.isOnGround() && double12 > 0.0) {
            this.player.jumpFromGround();
        }
        this.player.move(MoverType.PLAYER, new Vec3(double11, double12, double13));
        this.player.onGround = qd.isOnGround();
        final double double16 = double12;
        double11 = double8 - this.player.getX();
        double12 = double9 - this.player.getY();
        if (double12 > -0.5 || double12 < 0.5) {
            double12 = 0.0;
        }
        double13 = double10 - this.player.getZ();
        double15 = double11 * double11 + double12 * double12 + double13 * double13;
        boolean boolean32 = false;
        if (!this.player.isChangingDimension() && double15 > 0.0625 && !this.player.isSleeping() && !this.player.gameMode.isCreative() && this.player.gameMode.getGameModeForPlayer() != GameType.SPECTATOR) {
            boolean32 = true;
            ServerGamePacketListenerImpl.LOGGER.warn("{} moved wrongly!", this.player.getName().getString());
        }
        this.player.absMoveTo(double8, double9, double10, float18, float19);
        this.player.checkMovementStatistics(this.player.getX() - double4, this.player.getY() - double5, this.player.getZ() - double6);
        if (!this.player.noPhysics && !this.player.isSleeping()) {
            final boolean boolean33 = this.isPlayerCollidingWithAnything(xd3);
            if (boolean31 && (boolean32 || !boolean33)) {
                this.teleport(double4, double5, double6, float18, float19);
                return;
            }
        }
        this.clientIsFloating = (double16 >= -0.03125 && this.player.gameMode.getGameModeForPlayer() != GameType.SPECTATOR && !this.server.isFlightAllowed() && !this.player.abilities.mayfly && !this.player.hasEffect(MobEffects.LEVITATION) && !this.player.isFallFlying() && !xd3.containsAnyBlocks(this.player.getBoundingBox().inflate(0.0625).expandTowards(0.0, -0.55, 0.0)));
        this.player.onGround = qd.isOnGround();
        this.player.getLevel().getChunkSource().move(this.player);
        this.player.doCheckFallDamage(this.player.getY() - double7, qd.isOnGround());
        this.lastGoodX = this.player.getX();
        this.lastGoodY = this.player.getY();
        this.lastGoodZ = this.player.getZ();
    }
    
    private boolean isPlayerCollidingWithAnything(final LevelReader bjz) {
        return bjz.noCollision(this.player, this.player.getBoundingBox().deflate(9.999999747378752E-6));
    }
    
    public void teleport(final double double1, final double double2, final double double3, final float float4, final float float5) {
        this.teleport(double1, double2, double3, float4, float5, Collections.<ClientboundPlayerPositionPacket.RelativeArgument>emptySet());
    }
    
    public void teleport(final double double1, final double double2, final double double3, final float float4, final float float5, final Set<ClientboundPlayerPositionPacket.RelativeArgument> set) {
        final double double4 = set.contains(ClientboundPlayerPositionPacket.RelativeArgument.X) ? this.player.getX() : 0.0;
        final double double5 = set.contains(ClientboundPlayerPositionPacket.RelativeArgument.Y) ? this.player.getY() : 0.0;
        final double double6 = set.contains(ClientboundPlayerPositionPacket.RelativeArgument.Z) ? this.player.getZ() : 0.0;
        final float float6 = set.contains(ClientboundPlayerPositionPacket.RelativeArgument.Y_ROT) ? this.player.yRot : 0.0f;
        final float float7 = set.contains(ClientboundPlayerPositionPacket.RelativeArgument.X_ROT) ? this.player.xRot : 0.0f;
        this.awaitingPositionFromClient = new Vec3(double1, double2, double3);
        if (++this.awaitingTeleport == Integer.MAX_VALUE) {
            this.awaitingTeleport = 0;
        }
        this.awaitingTeleportTime = this.tickCount;
        this.player.absMoveTo(double1, double2, double3, float4, float5);
        this.player.connection.send(new ClientboundPlayerPositionPacket(double1 - double4, double2 - double5, double3 - double6, float4 - float6, float5 - float7, set, this.awaitingTeleport));
    }
    
    @Override
    public void handlePlayerAction(final ServerboundPlayerActionPacket qj) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)qj, this, this.player.getLevel());
        final BlockPos fk3 = qj.getPos();
        this.player.resetLastActionTime();
        final ServerboundPlayerActionPacket.Action a4 = qj.getAction();
        switch (a4) {
            case SWAP_HELD_ITEMS: {
                if (!this.player.isSpectator()) {
                    final ItemStack ben5 = this.player.getItemInHand(InteractionHand.OFF_HAND);
                    this.player.setItemInHand(InteractionHand.OFF_HAND, this.player.getItemInHand(InteractionHand.MAIN_HAND));
                    this.player.setItemInHand(InteractionHand.MAIN_HAND, ben5);
                }
            }
            case DROP_ITEM: {
                if (!this.player.isSpectator()) {
                    this.player.drop(false);
                }
            }
            case DROP_ALL_ITEMS: {
                if (!this.player.isSpectator()) {
                    this.player.drop(true);
                }
            }
            case RELEASE_USE_ITEM: {
                this.player.releaseUsingItem();
            }
            case START_DESTROY_BLOCK:
            case ABORT_DESTROY_BLOCK:
            case STOP_DESTROY_BLOCK: {
                this.player.gameMode.handleBlockBreakAction(fk3, a4, qj.getDirection(), this.server.getMaxBuildHeight());
            }
            default: {
                throw new IllegalArgumentException("Invalid player action");
            }
        }
    }
    
    @Override
    public void handleUseItemOn(final ServerboundUseItemOnPacket rb) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)rb, this, this.player.getLevel());
        final ServerLevel xd3 = this.server.getLevel(this.player.dimension);
        final InteractionHand ajk4 = rb.getHand();
        final ItemStack ben5 = this.player.getItemInHand(ajk4);
        final BlockHitResult cvg6 = rb.getHitResult();
        final BlockPos fk7 = cvg6.getBlockPos();
        final Direction fp8 = cvg6.getDirection();
        this.player.resetLastActionTime();
        if (fk7.getY() < this.server.getMaxBuildHeight() - 1 || (fp8 != Direction.UP && fk7.getY() < this.server.getMaxBuildHeight())) {
            if (this.awaitingPositionFromClient == null && this.player.distanceToSqr(fk7.getX() + 0.5, fk7.getY() + 0.5, fk7.getZ() + 0.5) < 64.0 && xd3.mayInteract(this.player, fk7)) {
                final InteractionResult ajl9 = this.player.gameMode.useItemOn(this.player, xd3, ben5, ajk4, cvg6);
                if (ajl9.shouldSwing()) {
                    this.player.swing(ajk4, true);
                }
            }
        }
        else {
            final Component lf9 = new TranslatableComponent("build.tooHigh", new Object[] { this.server.getMaxBuildHeight() }).withStyle(ChatFormatting.RED);
            this.player.connection.send(new ClientboundChatPacket(lf9, ChatType.GAME_INFO));
        }
        this.player.connection.send(new ClientboundBlockUpdatePacket(xd3, fk7));
        this.player.connection.send(new ClientboundBlockUpdatePacket(xd3, fk7.relative(fp8)));
    }
    
    @Override
    public void handleUseItem(final ServerboundUseItemPacket rc) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)rc, this, this.player.getLevel());
        final ServerLevel xd3 = this.server.getLevel(this.player.dimension);
        final InteractionHand ajk4 = rc.getHand();
        final ItemStack ben5 = this.player.getItemInHand(ajk4);
        this.player.resetLastActionTime();
        if (ben5.isEmpty()) {
            return;
        }
        this.player.gameMode.useItem(this.player, xd3, ben5, ajk4);
    }
    
    @Override
    public void handleTeleportToEntityPacket(final ServerboundTeleportToEntityPacket ra) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)ra, this, this.player.getLevel());
        if (this.player.isSpectator()) {
            for (final ServerLevel xd4 : this.server.getAllLevels()) {
                final Entity akq5 = ra.getEntity(xd4);
                if (akq5 != null) {
                    this.player.teleportTo(xd4, akq5.getX(), akq5.getY(), akq5.getZ(), akq5.yRot, akq5.xRot);
                }
            }
        }
    }
    
    @Override
    public void handleResourcePackResponse(final ServerboundResourcePackPacket qo) {
    }
    
    @Override
    public void handlePaddleBoat(final ServerboundPaddleBoatPacket qf) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)qf, this, this.player.getLevel());
        final Entity akq3 = this.player.getVehicle();
        if (akq3 instanceof Boat) {
            ((Boat)akq3).setPaddleState(qf.getLeft(), qf.getRight());
        }
    }
    
    @Override
    public void onDisconnect(final Component lf) {
        ServerGamePacketListenerImpl.LOGGER.info("{} lost connection: {}", this.player.getName().getString(), lf.getString());
        this.server.invalidateStatus();
        this.server.getPlayerList().broadcastMessage(new TranslatableComponent("multiplayer.player.left", new Object[] { this.player.getDisplayName() }).withStyle(ChatFormatting.YELLOW));
        this.player.disconnect();
        this.server.getPlayerList().remove(this.player);
        if (this.isSingleplayerOwner()) {
            ServerGamePacketListenerImpl.LOGGER.info("Stopping singleplayer server as player logged out");
            this.server.halt(false);
        }
    }
    
    public void send(final Packet<?> lt) {
        this.send(lt, null);
    }
    
    public void send(final Packet<?> lt, @Nullable final GenericFutureListener<? extends Future<? super Void>> genericFutureListener) {
        if (lt instanceof ClientboundChatPacket) {
            final ClientboundChatPacket mm4 = (ClientboundChatPacket)lt;
            final ChatVisiblity ayh5 = this.player.getChatVisibility();
            if (ayh5 == ChatVisiblity.HIDDEN && mm4.getType() != ChatType.GAME_INFO) {
                return;
            }
            if (ayh5 == ChatVisiblity.SYSTEM && !mm4.isSystem()) {
                return;
            }
        }
        try {
            this.connection.send(lt, genericFutureListener);
        }
        catch (Throwable throwable4) {
            final CrashReport h5 = CrashReport.forThrowable(throwable4, "Sending packet");
            final CrashReportCategory i6 = h5.addCategory("Packet being sent");
            i6.setDetail("Packet class", () -> lt.getClass().getCanonicalName());
            throw new ReportedException(h5);
        }
    }
    
    @Override
    public void handleSetCarriedItem(final ServerboundSetCarriedItemPacket qs) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)qs, this, this.player.getLevel());
        if (qs.getSlot() < 0 || qs.getSlot() >= Inventory.getSelectionSize()) {
            ServerGamePacketListenerImpl.LOGGER.warn("{} tried to set an invalid carried item", this.player.getName().getString());
            return;
        }
        this.player.inventory.selected = qs.getSlot();
        this.player.resetLastActionTime();
    }
    
    @Override
    public void handleChat(final ServerboundChatPacket pp) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)pp, this, this.player.getLevel());
        if (this.player.getChatVisibility() == ChatVisiblity.HIDDEN) {
            this.send(new ClientboundChatPacket(new TranslatableComponent("chat.cannotSend", new Object[0]).withStyle(ChatFormatting.RED)));
            return;
        }
        this.player.resetLastActionTime();
        String string3 = pp.getMessage();
        string3 = StringUtils.normalizeSpace(string3);
        for (int integer4 = 0; integer4 < string3.length(); ++integer4) {
            if (!SharedConstants.isAllowedChatCharacter(string3.charAt(integer4))) {
                this.disconnect(new TranslatableComponent("multiplayer.disconnect.illegal_characters", new Object[0]));
                return;
            }
        }
        if (string3.startsWith("/")) {
            this.handleCommand(string3);
        }
        else {
            final Component lf4 = new TranslatableComponent("chat.type.text", new Object[] { this.player.getDisplayName(), string3 });
            this.server.getPlayerList().broadcastMessage(lf4, false);
        }
        this.chatSpamTickCount += 20;
        if (this.chatSpamTickCount > 200 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) {
            this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]));
        }
    }
    
    private void handleCommand(final String string) {
        this.server.getCommands().performCommand(this.player.createCommandSourceStack(), string);
    }
    
    @Override
    public void handleAnimate(final ServerboundSwingPacket qz) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)qz, this, this.player.getLevel());
        this.player.resetLastActionTime();
        this.player.swing(qz.getHand());
    }
    
    @Override
    public void handlePlayerCommand(final ServerboundPlayerCommandPacket qk) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)qk, this, this.player.getLevel());
        this.player.resetLastActionTime();
        switch (qk.getAction()) {
            case PRESS_SHIFT_KEY: {
                this.player.setShiftKeyDown(true);
                break;
            }
            case RELEASE_SHIFT_KEY: {
                this.player.setShiftKeyDown(false);
                break;
            }
            case START_SPRINTING: {
                this.player.setSprinting(true);
                break;
            }
            case STOP_SPRINTING: {
                this.player.setSprinting(false);
                break;
            }
            case STOP_SLEEPING: {
                if (this.player.isSleeping()) {
                    this.player.stopSleepInBed(false, true);
                    this.awaitingPositionFromClient = this.player.position();
                    break;
                }
                break;
            }
            case START_RIDING_JUMP: {
                if (this.player.getVehicle() instanceof PlayerRideableJumping) {
                    final PlayerRideableJumping ali3 = (PlayerRideableJumping)this.player.getVehicle();
                    final int integer4 = qk.getData();
                    if (ali3.canJump() && integer4 > 0) {
                        ali3.handleStartJump(integer4);
                    }
                    break;
                }
                break;
            }
            case STOP_RIDING_JUMP: {
                if (this.player.getVehicle() instanceof PlayerRideableJumping) {
                    final PlayerRideableJumping ali3 = (PlayerRideableJumping)this.player.getVehicle();
                    ali3.handleStopJump();
                    break;
                }
                break;
            }
            case OPEN_INVENTORY: {
                if (this.player.getVehicle() instanceof AbstractHorse) {
                    ((AbstractHorse)this.player.getVehicle()).openInventory(this.player);
                    break;
                }
                break;
            }
            case START_FALL_FLYING: {
                if (!this.player.tryToStartFallFlying()) {
                    this.player.stopFallFlying();
                    break;
                }
                break;
            }
            default: {
                throw new IllegalArgumentException("Invalid client command!");
            }
        }
    }
    
    @Override
    public void handleInteract(final ServerboundInteractPacket qa) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)qa, this, this.player.getLevel());
        final ServerLevel xd3 = this.server.getLevel(this.player.dimension);
        final Entity akq4 = qa.getTarget(xd3);
        this.player.resetLastActionTime();
        if (akq4 != null) {
            final boolean boolean5 = this.player.canSee(akq4);
            double double6 = 36.0;
            if (!boolean5) {
                double6 = 9.0;
            }
            if (this.player.distanceToSqr(akq4) < double6) {
                if (qa.getAction() == ServerboundInteractPacket.Action.INTERACT) {
                    final InteractionHand ajk8 = qa.getHand();
                    this.player.interactOn(akq4, ajk8);
                }
                else if (qa.getAction() == ServerboundInteractPacket.Action.INTERACT_AT) {
                    final InteractionHand ajk8 = qa.getHand();
                    final InteractionResult ajl9 = akq4.interactAt(this.player, qa.getLocation(), ajk8);
                    if (ajl9.shouldSwing()) {
                        this.player.swing(ajk8, true);
                    }
                }
                else if (qa.getAction() == ServerboundInteractPacket.Action.ATTACK) {
                    if (akq4 instanceof ItemEntity || akq4 instanceof ExperienceOrb || akq4 instanceof AbstractArrow || akq4 == this.player) {
                        this.disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_entity_attacked", new Object[0]));
                        this.server.warn("Player " + this.player.getName().getString() + " tried to attack an invalid entity");
                        return;
                    }
                    this.player.attack(akq4);
                }
            }
        }
    }
    
    @Override
    public void handleClientCommand(final ServerboundClientCommandPacket pq) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)pq, this, this.player.getLevel());
        this.player.resetLastActionTime();
        final ServerboundClientCommandPacket.Action a3 = pq.getAction();
        switch (a3) {
            case PERFORM_RESPAWN: {
                if (this.player.wonGame) {
                    this.player.wonGame = false;
                    this.player = this.server.getPlayerList().respawn(this.player, DimensionType.OVERWORLD, true);
                    CriteriaTriggers.CHANGED_DIMENSION.trigger(this.player, DimensionType.THE_END, DimensionType.OVERWORLD);
                    break;
                }
                if (this.player.getHealth() > 0.0f) {
                    return;
                }
                this.player = this.server.getPlayerList().respawn(this.player, DimensionType.OVERWORLD, false);
                if (this.server.isHardcore()) {
                    this.player.setGameMode(GameType.SPECTATOR);
                    this.player.getLevel().getGameRules().<GameRules.BooleanValue>getRule(GameRules.RULE_SPECTATORSGENERATECHUNKS).set(false, this.server);
                    break;
                }
                break;
            }
            case REQUEST_STATS: {
                this.player.getStats().sendStats(this.player);
                break;
            }
        }
    }
    
    @Override
    public void handleContainerClose(final ServerboundContainerClosePacket pw) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)pw, this, this.player.getLevel());
        this.player.doCloseContainer();
    }
    
    @Override
    public void handleContainerClick(final ServerboundContainerClickPacket pv) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)pv, this, this.player.getLevel());
        this.player.resetLastActionTime();
        if (this.player.containerMenu.containerId == pv.getContainerId() && this.player.containerMenu.isSynched(this.player)) {
            if (this.player.isSpectator()) {
                final NonNullList<ItemStack> fy3 = NonNullList.<ItemStack>create();
                for (int integer4 = 0; integer4 < this.player.containerMenu.slots.size(); ++integer4) {
                    fy3.add(this.player.containerMenu.slots.get(integer4).getItem());
                }
                this.player.refreshContainer(this.player.containerMenu, fy3);
            }
            else {
                final ItemStack ben3 = this.player.containerMenu.clicked(pv.getSlotNum(), pv.getButtonNum(), pv.getClickType(), this.player);
                if (ItemStack.matches(pv.getItem(), ben3)) {
                    this.player.connection.send(new ClientboundContainerAckPacket(pv.getContainerId(), pv.getUid(), true));
                    this.player.ignoreSlotUpdateHack = true;
                    this.player.containerMenu.broadcastChanges();
                    this.player.broadcastCarriedItem();
                    this.player.ignoreSlotUpdateHack = false;
                }
                else {
                    this.expectedAcks.put(this.player.containerMenu.containerId, pv.getUid());
                    this.player.connection.send(new ClientboundContainerAckPacket(pv.getContainerId(), pv.getUid(), false));
                    this.player.containerMenu.setSynched(this.player, false);
                    final NonNullList<ItemStack> fy4 = NonNullList.<ItemStack>create();
                    for (int integer5 = 0; integer5 < this.player.containerMenu.slots.size(); ++integer5) {
                        final ItemStack ben4 = this.player.containerMenu.slots.get(integer5).getItem();
                        fy4.add(ben4.isEmpty() ? ItemStack.EMPTY : ben4);
                    }
                    this.player.refreshContainer(this.player.containerMenu, fy4);
                }
            }
        }
    }
    
    @Override
    public void handlePlaceRecipe(final ServerboundPlaceRecipePacket qh) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)qh, this, this.player.getLevel());
        this.player.resetLastActionTime();
        if (this.player.isSpectator() || this.player.containerMenu.containerId != qh.getContainerId() || !this.player.containerMenu.isSynched(this.player) || !(this.player.containerMenu instanceof RecipeBookMenu)) {
            return;
        }
        this.server.getRecipeManager().byKey(qh.getRecipe()).ifPresent(bgw -> ((RecipeBookMenu)this.player.containerMenu).handlePlacement(qh.isShiftDown(), bgw, this.player));
    }
    
    @Override
    public void handleContainerButtonClick(final ServerboundContainerButtonClickPacket pu) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)pu, this, this.player.getLevel());
        this.player.resetLastActionTime();
        if (this.player.containerMenu.containerId == pu.getContainerId() && this.player.containerMenu.isSynched(this.player) && !this.player.isSpectator()) {
            this.player.containerMenu.clickMenuButton(this.player, pu.getButtonId());
            this.player.containerMenu.broadcastChanges();
        }
    }
    
    @Override
    public void handleSetCreativeModeSlot(final ServerboundSetCreativeModeSlotPacket qv) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)qv, this, this.player.getLevel());
        if (this.player.gameMode.isCreative()) {
            final boolean boolean3 = qv.getSlotNum() < 0;
            final ItemStack ben4 = qv.getItem();
            final CompoundTag jt5 = ben4.getTagElement("BlockEntityTag");
            if (!ben4.isEmpty() && jt5 != null && jt5.contains("x") && jt5.contains("y") && jt5.contains("z")) {
                final BlockPos fk6 = new BlockPos(jt5.getInt("x"), jt5.getInt("y"), jt5.getInt("z"));
                final BlockEntity bwl7 = this.player.level.getBlockEntity(fk6);
                if (bwl7 != null) {
                    final CompoundTag jt6 = bwl7.save(new CompoundTag());
                    jt6.remove("x");
                    jt6.remove("y");
                    jt6.remove("z");
                    ben4.addTagElement("BlockEntityTag", jt6);
                }
            }
            final boolean boolean4 = qv.getSlotNum() >= 1 && qv.getSlotNum() <= 45;
            final boolean boolean5 = ben4.isEmpty() || (ben4.getDamageValue() >= 0 && ben4.getCount() <= 64 && !ben4.isEmpty());
            if (boolean4 && boolean5) {
                if (ben4.isEmpty()) {
                    this.player.inventoryMenu.setItem(qv.getSlotNum(), ItemStack.EMPTY);
                }
                else {
                    this.player.inventoryMenu.setItem(qv.getSlotNum(), ben4);
                }
                this.player.inventoryMenu.setSynched(this.player, true);
                this.player.inventoryMenu.broadcastChanges();
            }
            else if (boolean3 && boolean5 && this.dropSpamTickCount < 200) {
                this.dropSpamTickCount += 20;
                this.player.drop(ben4, true);
            }
        }
    }
    
    @Override
    public void handleContainerAck(final ServerboundContainerAckPacket pt) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)pt, this, this.player.getLevel());
        final int integer3 = this.player.containerMenu.containerId;
        if (integer3 == pt.getContainerId() && this.expectedAcks.getOrDefault(integer3, (short)(pt.getUid() + 1)) == pt.getUid() && !this.player.containerMenu.isSynched(this.player) && !this.player.isSpectator()) {
            this.player.containerMenu.setSynched(this.player, true);
        }
    }
    
    @Override
    public void handleSignUpdate(final ServerboundSignUpdatePacket qy) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)qy, this, this.player.getLevel());
        this.player.resetLastActionTime();
        final ServerLevel xd3 = this.server.getLevel(this.player.dimension);
        final BlockPos fk4 = qy.getPos();
        if (xd3.hasChunkAt(fk4)) {
            final BlockState byj5 = xd3.getBlockState(fk4);
            final BlockEntity bwl6 = xd3.getBlockEntity(fk4);
            if (!(bwl6 instanceof SignBlockEntity)) {
                return;
            }
            final SignBlockEntity bxh7 = (SignBlockEntity)bwl6;
            if (!bxh7.isEditable() || bxh7.getPlayerWhoMayEdit() != this.player) {
                this.server.warn("Player " + this.player.getName().getString() + " just tried to change non-editable sign");
                return;
            }
            final String[] arr8 = qy.getLines();
            for (int integer9 = 0; integer9 < arr8.length; ++integer9) {
                bxh7.setMessage(integer9, new TextComponent(ChatFormatting.stripFormatting(arr8[integer9])));
            }
            bxh7.setChanged();
            xd3.sendBlockUpdated(fk4, byj5, byj5, 3);
        }
    }
    
    @Override
    public void handleKeepAlive(final ServerboundKeepAlivePacket qb) {
        if (this.keepAlivePending && qb.getId() == this.keepAliveChallenge) {
            final int integer3 = (int)(Util.getMillis() - this.keepAliveTime);
            this.player.latency = (this.player.latency * 3 + integer3) / 4;
            this.keepAlivePending = false;
        }
        else if (!this.isSingleplayerOwner()) {
            this.disconnect(new TranslatableComponent("disconnect.timeout", new Object[0]));
        }
    }
    
    @Override
    public void handlePlayerAbilities(final ServerboundPlayerAbilitiesPacket qi) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)qi, this, this.player.getLevel());
        this.player.abilities.flying = (qi.isFlying() && this.player.abilities.mayfly);
    }
    
    @Override
    public void handleClientInformation(final ServerboundClientInformationPacket pr) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)pr, this, this.player.getLevel());
        this.player.updateOptions(pr);
    }
    
    @Override
    public void handleCustomPayload(final ServerboundCustomPayloadPacket px) {
    }
    
    @Override
    public void handleChangeDifficulty(final ServerboundChangeDifficultyPacket po) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)po, this, this.player.getLevel());
        if (!this.player.hasPermissions(2) && !this.isSingleplayerOwner()) {
            return;
        }
        this.server.setDifficulty(po.getDifficulty(), false);
    }
    
    @Override
    public void handleLockDifficulty(final ServerboundLockDifficultyPacket qc) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)qc, this, this.player.getLevel());
        if (!this.player.hasPermissions(2) && !this.isSingleplayerOwner()) {
            return;
        }
        this.server.setDifficultyLocked(qc.isLocked());
    }
    
    static {
        LOGGER = LogManager.getLogger();
    }
}
