package net.minecraft.server.network;

import net.minecraft.world.level.block.state.StateHolder;
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.network.protocol.game.ServerboundClientCommandPacket;
import net.minecraft.advancements.CriteriaTriggers;
import net.minecraft.world.entity.projectile.AbstractArrow;
import net.minecraft.world.entity.ExperienceOrb;
import net.minecraft.world.entity.item.ItemEntity;
import java.util.Optional;
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.item.Item;
import net.minecraft.world.item.BucketItem;
import net.minecraft.world.item.BlockItem;
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.phys.shapes.VoxelShape;
import java.util.stream.Stream;
import net.minecraft.world.phys.shapes.BooleanOp;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.GameType;
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.network.protocol.game.ServerboundJigsawGeneratePacket;
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.world.level.block.state.BlockBehaviour;
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 me, final ServerPlayer ze) {
        this.expectedAcks = (Int2ShortMap)new Int2ShortOpenHashMap();
        this.server = minecraftServer;
        (this.connection = me).setListener(this);
        this.player = ze;
        ze.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 && !this.player.isSleeping()) {
            if (++this.aboveGroundTickCount > 80) {
                ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked for floating too long!", this.player.getName().getString());
                this.disconnect(new TranslatableComponent("multiplayer.disconnect.flying"));
                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"));
                    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"));
            }
            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"));
        }
    }
    
    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 mr) {
        this.connection.send(new ClientboundDisconnectPacket(mr), (future -> this.connection.disconnect(mr)));
        this.connection.setReadOnly();
        this.server.executeBlocking(this.connection::handleDisconnection);
    }
    
    @Override
    public void handlePlayerInput(final ServerboundPlayerInputPacket sa) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)sa, this, this.player.getLevel());
        this.player.setPlayerInput(sa.getXxa(), sa.getZza(), sa.isJumping(), sa.isShiftKeyDown());
    }
    
    private static boolean containsInvalidValues(final ServerboundMovePlayerPacket rs) {
        return !Doubles.isFinite(rs.getX(0.0)) || !Doubles.isFinite(rs.getY(0.0)) || !Doubles.isFinite(rs.getZ(0.0)) || !Floats.isFinite(rs.getXRot(0.0f)) || !Floats.isFinite(rs.getYRot(0.0f)) || (Math.abs(rs.getX(0.0)) > 3.0E7 || Math.abs(rs.getY(0.0)) > 3.0E7 || Math.abs(rs.getZ(0.0)) > 3.0E7);
    }
    
    private static boolean containsInvalidValues(final ServerboundMoveVehiclePacket rt) {
        return !Doubles.isFinite(rt.getX()) || !Doubles.isFinite(rt.getY()) || !Doubles.isFinite(rt.getZ()) || !Floats.isFinite(rt.getXRot()) || !Floats.isFinite(rt.getYRot());
    }
    
    @Override
    public void handleMoveVehicle(final ServerboundMoveVehiclePacket rt) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)rt, this, this.player.getLevel());
        if (containsInvalidValues(rt)) {
            this.disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_vehicle_movement"));
            return;
        }
        final Entity aom3 = this.player.getRootVehicle();
        if (aom3 != this.player && aom3.getControllingPassenger() == this.player && aom3 == this.lastVehicle) {
            final ServerLevel zd4 = this.player.getLevel();
            final double double5 = aom3.getX();
            final double double6 = aom3.getY();
            final double double7 = aom3.getZ();
            final double double8 = rt.getX();
            final double double9 = rt.getY();
            final double double10 = rt.getZ();
            final float float17 = rt.getYRot();
            final float float18 = rt.getXRot();
            double double11 = double8 - this.vehicleFirstGoodX;
            double double12 = double9 - this.vehicleFirstGoodY;
            double double13 = double10 - this.vehicleFirstGoodZ;
            final double double14 = aom3.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! {},{},{}", aom3.getName().getString(), this.player.getName().getString(), double11, double12, double13);
                this.connection.send(new ClientboundMoveVehiclePacket(aom3));
                return;
            }
            final boolean boolean29 = zd4.noCollision(aom3, aom3.getBoundingBox().deflate(0.0625));
            double11 = double8 - this.vehicleLastGoodX;
            double12 = double9 - this.vehicleLastGoodY - 1.0E-6;
            double13 = double10 - this.vehicleLastGoodZ;
            aom3.move(MoverType.PLAYER, new Vec3(double11, double12, double13));
            final double double16 = double12;
            double11 = double8 - aom3.getX();
            double12 = double9 - aom3.getY();
            if (double12 > -0.5 || double12 < 0.5) {
                double12 = 0.0;
            }
            double13 = double10 - aom3.getZ();
            double15 = double11 * double11 + double12 * double12 + double13 * double13;
            boolean boolean30 = false;
            if (double15 > 0.0625) {
                boolean30 = true;
                ServerGamePacketListenerImpl.LOGGER.warn("{} (vehicle of {}) moved wrongly! {}", aom3.getName().getString(), this.player.getName().getString(), Math.sqrt(double15));
            }
            aom3.absMoveTo(double8, double9, double10, float17, float18);
            final boolean boolean31 = zd4.noCollision(aom3, aom3.getBoundingBox().deflate(0.0625));
            if (boolean29 && (boolean30 || !boolean31)) {
                aom3.absMoveTo(double5, double6, double7, float17, float18);
                this.connection.send(new ClientboundMoveVehiclePacket(aom3));
                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() && this.noBlocksAround(aom3));
            this.vehicleLastGoodX = aom3.getX();
            this.vehicleLastGoodY = aom3.getY();
            this.vehicleLastGoodZ = aom3.getZ();
        }
    }
    
    private boolean noBlocksAround(final Entity aom) {
        return aom.level.getBlockStates(aom.getBoundingBox().inflate(0.0625).expandTowards(0.0, -0.55, 0.0)).allMatch(BlockBehaviour.BlockStateBase::isAir);
    }
    
    @Override
    public void handleAcceptTeleportPacket(final ServerboundAcceptTeleportationPacket ra) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)ra, this, this.player.getLevel());
        if (ra.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 sb) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)sb, this, this.player.getLevel());
        if (sb.getPurpose() == ServerboundRecipeBookUpdatePacket.Purpose.SHOWN) {
            this.server.getRecipeManager().byKey(sb.getRecipe()).ifPresent(this.player.getRecipeBook()::removeHighlight);
        }
        else if (sb.getPurpose() == ServerboundRecipeBookUpdatePacket.Purpose.SETTINGS) {
            this.player.getRecipeBook().setGuiOpen(sb.isGuiOpen());
            this.player.getRecipeBook().setFilteringCraftable(sb.isFilteringCraftable());
            this.player.getRecipeBook().setFurnaceGuiOpen(sb.isFurnaceGuiOpen());
            this.player.getRecipeBook().setFurnaceFilteringCraftable(sb.isFurnaceFilteringCraftable());
            this.player.getRecipeBook().setBlastingFurnaceGuiOpen(sb.isBlastFurnaceGuiOpen());
            this.player.getRecipeBook().setBlastingFurnaceFilteringCraftable(sb.isBlastFurnaceFilteringCraftable());
            this.player.getRecipeBook().setSmokerGuiOpen(sb.isSmokerGuiOpen());
            this.player.getRecipeBook().setSmokerFilteringCraftable(sb.isSmokerFilteringCraftable());
        }
    }
    
    @Override
    public void handleSeenAdvancements(final ServerboundSeenAdvancementsPacket se) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)se, this, this.player.getLevel());
        if (se.getAction() == ServerboundSeenAdvancementsPacket.Action.OPENED_TAB) {
            final ResourceLocation uh3 = se.getTab();
            final Advancement w4 = this.server.getAdvancements().getAdvancement(uh3);
            if (w4 != null) {
                this.player.getAdvancements().setSelectedTab(w4);
            }
        }
    }
    
    @Override
    public void handleCustomCommandSuggestions(final ServerboundCommandSuggestionPacket rg) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)rg, this, this.player.getLevel());
        final StringReader stringReader3 = new StringReader(rg.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(rg.getId(), suggestions)));
    }
    
    @Override
    public void handleSetCommandBlock(final ServerboundSetCommandBlockPacket si) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)si, this, this.player.getLevel());
        if (!this.server.isCommandBlockEnabled()) {
            this.player.sendMessage(new TranslatableComponent("advMode.notEnabled"), Util.NIL_UUID);
            return;
        }
        if (!this.player.canUseGameMasterBlocks()) {
            this.player.sendMessage(new TranslatableComponent("advMode.notAllowed"), Util.NIL_UUID);
            return;
        }
        BaseCommandBlock bpc3 = null;
        CommandBlockEntity cdq4 = null;
        final BlockPos fu5 = si.getPos();
        final BlockEntity cdl6 = this.player.level.getBlockEntity(fu5);
        if (cdl6 instanceof CommandBlockEntity) {
            cdq4 = (CommandBlockEntity)cdl6;
            bpc3 = cdq4.getCommandBlock();
        }
        final String string7 = si.getCommand();
        final boolean boolean8 = si.isTrackOutput();
        if (bpc3 != null) {
            final CommandBlockEntity.Mode a9 = cdq4.getMode();
            final Direction fz10 = this.player.level.getBlockState(fu5).<Direction>getValue((Property<Direction>)CommandBlock.FACING);
            switch (si.getMode()) {
                case SEQUENCE: {
                    final BlockState cfj11 = Blocks.CHAIN_COMMAND_BLOCK.defaultBlockState();
                    this.player.level.setBlock(fu5, (((StateHolder<O, BlockState>)cfj11).setValue((Property<Comparable>)CommandBlock.FACING, fz10)).<Comparable, Boolean>setValue((Property<Comparable>)CommandBlock.CONDITIONAL, si.isConditional()), 2);
                    break;
                }
                case AUTO: {
                    final BlockState cfj11 = Blocks.REPEATING_COMMAND_BLOCK.defaultBlockState();
                    this.player.level.setBlock(fu5, (((StateHolder<O, BlockState>)cfj11).setValue((Property<Comparable>)CommandBlock.FACING, fz10)).<Comparable, Boolean>setValue((Property<Comparable>)CommandBlock.CONDITIONAL, si.isConditional()), 2);
                    break;
                }
                default: {
                    final BlockState cfj11 = Blocks.COMMAND_BLOCK.defaultBlockState();
                    this.player.level.setBlock(fu5, (((StateHolder<O, BlockState>)cfj11).setValue((Property<Comparable>)CommandBlock.FACING, fz10)).<Comparable, Boolean>setValue((Property<Comparable>)CommandBlock.CONDITIONAL, si.isConditional()), 2);
                    break;
                }
            }
            cdl6.clearRemoved();
            this.player.level.setBlockEntity(fu5, cdl6);
            bpc3.setCommand(string7);
            bpc3.setTrackOutput(boolean8);
            if (!boolean8) {
                bpc3.setLastOutput(null);
            }
            cdq4.setAutomatic(si.isAutomatic());
            if (a9 != si.getMode()) {
                cdq4.onModeSwitch();
            }
            bpc3.onUpdated();
            if (!StringUtil.isNullOrEmpty(string7)) {
                this.player.sendMessage(new TranslatableComponent("advMode.setCommand.success", new Object[] { string7 }), Util.NIL_UUID);
            }
        }
    }
    
    @Override
    public void handleSetCommandMinecart(final ServerboundSetCommandMinecartPacket sj) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)sj, this, this.player.getLevel());
        if (!this.server.isCommandBlockEnabled()) {
            this.player.sendMessage(new TranslatableComponent("advMode.notEnabled"), Util.NIL_UUID);
            return;
        }
        if (!this.player.canUseGameMasterBlocks()) {
            this.player.sendMessage(new TranslatableComponent("advMode.notAllowed"), Util.NIL_UUID);
            return;
        }
        final BaseCommandBlock bpc3 = sj.getCommandBlock(this.player.level);
        if (bpc3 != null) {
            bpc3.setCommand(sj.getCommand());
            bpc3.setTrackOutput(sj.isTrackOutput());
            if (!sj.isTrackOutput()) {
                bpc3.setLastOutput(null);
            }
            bpc3.onUpdated();
            this.player.sendMessage(new TranslatableComponent("advMode.setCommand.success", new Object[] { sj.getCommand() }), Util.NIL_UUID);
        }
    }
    
    @Override
    public void handlePickItem(final ServerboundPickItemPacket rv) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)rv, this, this.player.getLevel());
        this.player.inventory.pickSlot(rv.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, rv.getSlot(), this.player.inventory.getItem(rv.getSlot())));
        this.player.connection.send(new ClientboundSetCarriedItemPacket(this.player.inventory.selected));
    }
    
    @Override
    public void handleRenameItem(final ServerboundRenameItemPacket sc) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)sc, this, this.player.getLevel());
        if (this.player.containerMenu instanceof AnvilMenu) {
            final AnvilMenu bgk3 = (AnvilMenu)this.player.containerMenu;
            final String string4 = SharedConstants.filterText(sc.getName());
            if (string4.length() <= 35) {
                bgk3.setItemName(string4);
            }
        }
    }
    
    @Override
    public void handleSetBeaconPacket(final ServerboundSetBeaconPacket sg) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)sg, this, this.player.getLevel());
        if (this.player.containerMenu instanceof BeaconMenu) {
            ((BeaconMenu)this.player.containerMenu).updateEffects(sg.getPrimary(), sg.getSecondary());
        }
    }
    
    @Override
    public void handleSetStructureBlock(final ServerboundSetStructureBlockPacket sm) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)sm, this, this.player.getLevel());
        if (!this.player.canUseGameMasterBlocks()) {
            return;
        }
        final BlockPos fu3 = sm.getPos();
        final BlockState cfj4 = this.player.level.getBlockState(fu3);
        final BlockEntity cdl5 = this.player.level.getBlockEntity(fu3);
        if (cdl5 instanceof StructureBlockEntity) {
            final StructureBlockEntity cel6 = (StructureBlockEntity)cdl5;
            cel6.setMode(sm.getMode());
            cel6.setStructureName(sm.getName());
            cel6.setStructurePos(sm.getOffset());
            cel6.setStructureSize(sm.getSize());
            cel6.setMirror(sm.getMirror());
            cel6.setRotation(sm.getRotation());
            cel6.setMetaData(sm.getData());
            cel6.setIgnoreEntities(sm.isIgnoreEntities());
            cel6.setShowAir(sm.isShowAir());
            cel6.setShowBoundingBox(sm.isShowBoundingBox());
            cel6.setIntegrity(sm.getIntegrity());
            cel6.setSeed(sm.getSeed());
            if (cel6.hasStructureName()) {
                final String string7 = cel6.getStructureName();
                if (sm.getUpdateType() == StructureBlockEntity.UpdateType.SAVE_AREA) {
                    if (cel6.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 (sm.getUpdateType() == StructureBlockEntity.UpdateType.LOAD_AREA) {
                    if (!cel6.isStructureLoadable()) {
                        this.player.displayClientMessage(new TranslatableComponent("structure_block.load_not_found", new Object[] { string7 }), false);
                    }
                    else if (cel6.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 (sm.getUpdateType() == StructureBlockEntity.UpdateType.SCAN_AREA) {
                    if (cel6.detectSize()) {
                        this.player.displayClientMessage(new TranslatableComponent("structure_block.size_success", new Object[] { string7 }), false);
                    }
                    else {
                        this.player.displayClientMessage(new TranslatableComponent("structure_block.size_failure"), false);
                    }
                }
            }
            else {
                this.player.displayClientMessage(new TranslatableComponent("structure_block.invalid_structure_name", new Object[] { sm.getName() }), false);
            }
            cel6.setChanged();
            this.player.level.sendBlockUpdated(fu3, cfj4, cfj4, 3);
        }
    }
    
    @Override
    public void handleSetJigsawBlock(final ServerboundSetJigsawBlockPacket sl) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)sl, this, this.player.getLevel());
        if (!this.player.canUseGameMasterBlocks()) {
            return;
        }
        final BlockPos fu3 = sl.getPos();
        final BlockState cfj4 = this.player.level.getBlockState(fu3);
        final BlockEntity cdl5 = this.player.level.getBlockEntity(fu3);
        if (cdl5 instanceof JigsawBlockEntity) {
            final JigsawBlockEntity ceb6 = (JigsawBlockEntity)cdl5;
            ceb6.setName(sl.getName());
            ceb6.setTarget(sl.getTarget());
            ceb6.setPool(sl.getPool());
            ceb6.setFinalState(sl.getFinalState());
            ceb6.setJoint(sl.getJoint());
            ceb6.setChanged();
            this.player.level.sendBlockUpdated(fu3, cfj4, cfj4, 3);
        }
    }
    
    @Override
    public void handleJigsawGenerate(final ServerboundJigsawGeneratePacket rp) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)rp, this, this.player.getLevel());
        if (!this.player.canUseGameMasterBlocks()) {
            return;
        }
        final BlockPos fu3 = rp.getPos();
        final BlockEntity cdl4 = this.player.level.getBlockEntity(fu3);
        if (cdl4 instanceof JigsawBlockEntity) {
            final JigsawBlockEntity ceb5 = (JigsawBlockEntity)cdl4;
            ceb5.generate(this.player.getLevel(), rp.levels(), rp.keepJigsaws());
        }
    }
    
    @Override
    public void handleSelectTrade(final ServerboundSelectTradePacket sf) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)sf, this, this.player.getLevel());
        final int integer3 = sf.getItem();
        final AbstractContainerMenu bgi4 = this.player.containerMenu;
        if (bgi4 instanceof MerchantMenu) {
            final MerchantMenu bhm5 = (MerchantMenu)bgi4;
            bhm5.setSelectionHint(integer3);
            bhm5.tryMoveItems(integer3);
        }
    }
    
    @Override
    public void handleEditBook(final ServerboundEditBookPacket rm) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)rm, this, this.player.getLevel());
        final ItemStack bki3 = rm.getBook();
        if (bki3.isEmpty()) {
            return;
        }
        if (!WritableBookItem.makeSureTagIsValid(bki3.getTag())) {
            return;
        }
        final ItemStack bki4 = this.player.getItemInHand(rm.getHand());
        if (bki3.getItem() == Items.WRITABLE_BOOK && bki4.getItem() == Items.WRITABLE_BOOK) {
            if (rm.isSigning()) {
                final ItemStack bki5 = new ItemStack(Items.WRITTEN_BOOK);
                final CompoundTag le6 = bki4.getTag();
                if (le6 != null) {
                    bki5.setTag(le6.copy());
                }
                bki5.addTagElement("author", StringTag.valueOf(this.player.getName().getString()));
                bki5.addTagElement("title", StringTag.valueOf(bki3.getTag().getString("title")));
                final ListTag lk7 = bki3.getTag().getList("pages", 8);
                for (int integer8 = 0; integer8 < lk7.size(); ++integer8) {
                    String string9 = lk7.getString(integer8);
                    final Component mr10 = new TextComponent(string9);
                    string9 = Component.Serializer.toJson(mr10);
                    lk7.set(integer8, StringTag.valueOf(string9));
                }
                bki5.addTagElement("pages", lk7);
                this.player.setItemInHand(rm.getHand(), bki5);
            }
            else {
                bki4.addTagElement("pages", bki3.getTag().getList("pages", 8));
            }
        }
    }
    
    @Override
    public void handleEntityTagQuery(final ServerboundEntityTagQuery rn) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)rn, this, this.player.getLevel());
        if (!this.player.hasPermissions(2)) {
            return;
        }
        final Entity aom3 = this.player.getLevel().getEntity(rn.getEntityId());
        if (aom3 != null) {
            final CompoundTag le4 = aom3.saveWithoutId(new CompoundTag());
            this.player.connection.send(new ClientboundTagQueryPacket(rn.getTransactionId(), le4));
        }
    }
    
    @Override
    public void handleBlockEntityTagQuery(final ServerboundBlockEntityTagQuery rb) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)rb, this, this.player.getLevel());
        if (!this.player.hasPermissions(2)) {
            return;
        }
        final BlockEntity cdl3 = this.player.getLevel().getBlockEntity(rb.getPos());
        final CompoundTag le4 = (cdl3 != null) ? cdl3.save(new CompoundTag()) : null;
        this.player.connection.send(new ClientboundTagQueryPacket(rb.getTransactionId(), le4));
    }
    
    @Override
    public void handleMovePlayer(final ServerboundMovePlayerPacket rs) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)rs, this, this.player.getLevel());
        if (containsInvalidValues(rs)) {
            this.disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_player_movement"));
            return;
        }
        final ServerLevel zd3 = this.player.getLevel();
        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(), rs.getYRot(this.player.yRot), rs.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 = rs.getX(this.player.getX());
        final double double9 = rs.getY(this.player.getY());
        final double double10 = rs.getZ(this.player.getZ());
        final float float18 = rs.getYRot(this.player.yRot);
        final float float19 = rs.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(), rs.getYRot(this.player.yRot), rs.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 AABB deg31 = this.player.getBoundingBox();
        double11 = double8 - this.lastGoodX;
        double12 = double9 - this.lastGoodY;
        double13 = double10 - this.lastGoodZ;
        final boolean boolean32 = double12 > 0.0;
        if (this.player.isOnGround() && !rs.isOnGround() && boolean32) {
            this.player.jumpFromGround();
        }
        this.player.move(MoverType.PLAYER, new Vec3(double11, double12, double13));
        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 boolean33 = false;
        if (!this.player.isChangingDimension() && double15 > 0.0625 && !this.player.isSleeping() && !this.player.gameMode.isCreative() && this.player.gameMode.getGameModeForPlayer() != GameType.SPECTATOR) {
            boolean33 = true;
            ServerGamePacketListenerImpl.LOGGER.warn("{} moved wrongly!", this.player.getName().getString());
        }
        this.player.absMoveTo(double8, double9, double10, float18, float19);
        if (!this.player.noPhysics && !this.player.isSleeping() && ((boolean33 && zd3.noCollision(this.player, deg31)) || this.isPlayerCollidingWithAnythingNew(zd3, deg31))) {
            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() && this.noBlocksAround(this.player));
        this.player.getLevel().getChunkSource().move(this.player);
        this.player.doCheckFallDamage(this.player.getY() - double7, rs.isOnGround());
        this.player.setOnGround(rs.isOnGround());
        if (boolean32) {
            this.player.fallDistance = 0.0f;
        }
        this.player.checkMovementStatistics(this.player.getX() - double4, this.player.getY() - double5, this.player.getZ() - double6);
        this.lastGoodX = this.player.getX();
        this.lastGoodY = this.player.getY();
        this.lastGoodZ = this.player.getZ();
    }
    
    private boolean isPlayerCollidingWithAnythingNew(final LevelReader bqd, final AABB deg) {
        final Stream<VoxelShape> stream4 = bqd.getCollisions(this.player, this.player.getBoundingBox().deflate(9.999999747378752E-6), aom -> true);
        final VoxelShape dfg3 = Shapes.create(deg.deflate(9.999999747378752E-6));
        return stream4.anyMatch(dfg2 -> !Shapes.joinIsNotEmpty(dfg2, dfg3, BooleanOp.AND));
    }
    
    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 ry) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)ry, this, this.player.getLevel());
        final BlockPos fu3 = ry.getPos();
        this.player.resetLastActionTime();
        final ServerboundPlayerActionPacket.Action a4 = ry.getAction();
        switch (a4) {
            case SWAP_ITEM_WITH_OFFHAND: {
                if (!this.player.isSpectator()) {
                    final ItemStack bki5 = this.player.getItemInHand(InteractionHand.OFF_HAND);
                    this.player.setItemInHand(InteractionHand.OFF_HAND, this.player.getItemInHand(InteractionHand.MAIN_HAND));
                    this.player.setItemInHand(InteractionHand.MAIN_HAND, bki5);
                    this.player.stopUsingItem();
                }
            }
            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(fu3, a4, ry.getDirection(), this.server.getMaxBuildHeight());
            }
            default: {
                throw new IllegalArgumentException("Invalid player action");
            }
        }
    }
    
    private static boolean wasBlockPlacementAttempt(final ServerPlayer ze, final ItemStack bki) {
        if (bki.isEmpty()) {
            return false;
        }
        final Item bke3 = bki.getItem();
        return (bke3 instanceof BlockItem || bke3 instanceof BucketItem) && !ze.getCooldowns().isOnCooldown(bke3);
    }
    
    @Override
    public void handleUseItemOn(final ServerboundUseItemOnPacket sq) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)sq, this, this.player.getLevel());
        final ServerLevel zd3 = this.player.getLevel();
        final InteractionHand anf4 = sq.getHand();
        final ItemStack bki5 = this.player.getItemInHand(anf4);
        final BlockHitResult deh6 = sq.getHitResult();
        final BlockPos fu7 = deh6.getBlockPos();
        final Direction fz8 = deh6.getDirection();
        this.player.resetLastActionTime();
        if (fu7.getY() < this.server.getMaxBuildHeight()) {
            if (this.awaitingPositionFromClient == null && this.player.distanceToSqr(fu7.getX() + 0.5, fu7.getY() + 0.5, fu7.getZ() + 0.5) < 64.0 && zd3.mayInteract(this.player, fu7)) {
                final InteractionResult ang9 = this.player.gameMode.useItemOn(this.player, zd3, bki5, anf4, deh6);
                if (fz8 == Direction.UP && !ang9.consumesAction() && fu7.getY() >= this.server.getMaxBuildHeight() - 1 && wasBlockPlacementAttempt(this.player, bki5)) {
                    final Component mr10 = new TranslatableComponent("build.tooHigh", new Object[] { this.server.getMaxBuildHeight() }).withStyle(ChatFormatting.RED);
                    this.player.connection.send(new ClientboundChatPacket(mr10, ChatType.GAME_INFO, Util.NIL_UUID));
                }
                else if (ang9.shouldSwing()) {
                    this.player.swing(anf4, true);
                }
            }
        }
        else {
            final Component mr11 = new TranslatableComponent("build.tooHigh", new Object[] { this.server.getMaxBuildHeight() }).withStyle(ChatFormatting.RED);
            this.player.connection.send(new ClientboundChatPacket(mr11, ChatType.GAME_INFO, Util.NIL_UUID));
        }
        this.player.connection.send(new ClientboundBlockUpdatePacket(zd3, fu7));
        this.player.connection.send(new ClientboundBlockUpdatePacket(zd3, fu7.relative(fz8)));
    }
    
    @Override
    public void handleUseItem(final ServerboundUseItemPacket sr) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)sr, this, this.player.getLevel());
        final ServerLevel zd3 = this.player.getLevel();
        final InteractionHand anf4 = sr.getHand();
        final ItemStack bki5 = this.player.getItemInHand(anf4);
        this.player.resetLastActionTime();
        if (bki5.isEmpty()) {
            return;
        }
        final InteractionResult ang6 = this.player.gameMode.useItem(this.player, zd3, bki5, anf4);
        if (ang6.shouldSwing()) {
            this.player.swing(anf4, true);
        }
    }
    
    @Override
    public void handleTeleportToEntityPacket(final ServerboundTeleportToEntityPacket sp) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)sp, this, this.player.getLevel());
        if (this.player.isSpectator()) {
            for (final ServerLevel zd4 : this.server.getAllLevels()) {
                final Entity aom5 = sp.getEntity(zd4);
                if (aom5 != null) {
                    this.player.teleportTo(zd4, aom5.getX(), aom5.getY(), aom5.getZ(), aom5.yRot, aom5.xRot);
                }
            }
        }
    }
    
    @Override
    public void handleResourcePackResponse(final ServerboundResourcePackPacket sd) {
    }
    
    @Override
    public void handlePaddleBoat(final ServerboundPaddleBoatPacket ru) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)ru, this, this.player.getLevel());
        final Entity aom3 = this.player.getVehicle();
        if (aom3 instanceof Boat) {
            ((Boat)aom3).setPaddleState(ru.getLeft(), ru.getRight());
        }
    }
    
    @Override
    public void onDisconnect(final Component mr) {
        ServerGamePacketListenerImpl.LOGGER.info("{} lost connection: {}", this.player.getName().getString(), mr.getString());
        this.server.invalidateStatus();
        this.server.getPlayerList().broadcastMessage(new TranslatableComponent("multiplayer.player.left", new Object[] { this.player.getDisplayName() }).withStyle(ChatFormatting.YELLOW), ChatType.SYSTEM, Util.NIL_UUID);
        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<?> ni) {
        this.send(ni, null);
    }
    
    public void send(final Packet<?> ni, @Nullable final GenericFutureListener<? extends Future<? super Void>> genericFutureListener) {
        if (ni instanceof ClientboundChatPacket) {
            final ClientboundChatPacket oa4 = (ClientboundChatPacket)ni;
            final ChatVisiblity bea5 = this.player.getChatVisibility();
            if (bea5 == ChatVisiblity.HIDDEN && oa4.getType() != ChatType.GAME_INFO) {
                return;
            }
            if (bea5 == ChatVisiblity.SYSTEM && !oa4.isSystem()) {
                return;
            }
        }
        try {
            this.connection.send(ni, genericFutureListener);
        }
        catch (Throwable throwable4) {
            final CrashReport j5 = CrashReport.forThrowable(throwable4, "Sending packet");
            final CrashReportCategory k6 = j5.addCategory("Packet being sent");
            k6.setDetail("Packet class", () -> ni.getClass().getCanonicalName());
            throw new ReportedException(j5);
        }
    }
    
    @Override
    public void handleSetCarriedItem(final ServerboundSetCarriedItemPacket sh) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)sh, this, this.player.getLevel());
        if (sh.getSlot() < 0 || sh.getSlot() >= Inventory.getSelectionSize()) {
            ServerGamePacketListenerImpl.LOGGER.warn("{} tried to set an invalid carried item", this.player.getName().getString());
            return;
        }
        if (this.player.inventory.selected != sh.getSlot() && this.player.getUsedItemHand() == InteractionHand.MAIN_HAND) {
            this.player.stopUsingItem();
        }
        this.player.inventory.selected = sh.getSlot();
        this.player.resetLastActionTime();
    }
    
    @Override
    public void handleChat(final ServerboundChatPacket rd) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)rd, this, this.player.getLevel());
        if (this.player.getChatVisibility() == ChatVisiblity.HIDDEN) {
            this.send(new ClientboundChatPacket(new TranslatableComponent("chat.cannotSend").withStyle(ChatFormatting.RED), ChatType.SYSTEM, Util.NIL_UUID));
            return;
        }
        this.player.resetLastActionTime();
        final String string3 = StringUtils.normalizeSpace(rd.getMessage());
        for (int integer4 = 0; integer4 < string3.length(); ++integer4) {
            if (!SharedConstants.isAllowedChatCharacter(string3.charAt(integer4))) {
                this.disconnect(new TranslatableComponent("multiplayer.disconnect.illegal_characters"));
                return;
            }
        }
        if (string3.startsWith("/")) {
            this.handleCommand(string3);
        }
        else {
            final Component mr4 = new TranslatableComponent("chat.type.text", new Object[] { this.player.getDisplayName(), string3 });
            this.server.getPlayerList().broadcastMessage(mr4, ChatType.CHAT, this.player.getUUID());
        }
        this.chatSpamTickCount += 20;
        if (this.chatSpamTickCount > 200 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) {
            this.disconnect(new TranslatableComponent("disconnect.spam"));
        }
    }
    
    private void handleCommand(final String string) {
        this.server.getCommands().performCommand(this.player.createCommandSourceStack(), string);
    }
    
    @Override
    public void handleAnimate(final ServerboundSwingPacket so) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)so, this, this.player.getLevel());
        this.player.resetLastActionTime();
        this.player.swing(so.getHand());
    }
    
    @Override
    public void handlePlayerCommand(final ServerboundPlayerCommandPacket rz) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)rz, this, this.player.getLevel());
        this.player.resetLastActionTime();
        switch (rz.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 api3 = (PlayerRideableJumping)this.player.getVehicle();
                    final int integer4 = rz.getData();
                    if (api3.canJump() && integer4 > 0) {
                        api3.handleStartJump(integer4);
                    }
                    break;
                }
                break;
            }
            case STOP_RIDING_JUMP: {
                if (this.player.getVehicle() instanceof PlayerRideableJumping) {
                    final PlayerRideableJumping api3 = (PlayerRideableJumping)this.player.getVehicle();
                    api3.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 ro) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)ro, this, this.player.getLevel());
        final ServerLevel zd3 = this.player.getLevel();
        final Entity aom4 = ro.getTarget(zd3);
        this.player.resetLastActionTime();
        this.player.setShiftKeyDown(ro.isUsingSecondaryAction());
        if (aom4 != null) {
            final double double5 = 36.0;
            if (this.player.distanceToSqr(aom4) < 36.0) {
                final InteractionHand anf7 = ro.getHand();
                Optional<InteractionResult> optional8 = Optional.<InteractionResult>empty();
                if (ro.getAction() == ServerboundInteractPacket.Action.INTERACT) {
                    optional8 = Optional.<InteractionResult>of(this.player.interactOn(aom4, anf7));
                }
                else if (ro.getAction() == ServerboundInteractPacket.Action.INTERACT_AT) {
                    optional8 = Optional.<InteractionResult>of(aom4.interactAt(this.player, ro.getLocation(), anf7));
                }
                else if (ro.getAction() == ServerboundInteractPacket.Action.ATTACK) {
                    if (aom4 instanceof ItemEntity || aom4 instanceof ExperienceOrb || aom4 instanceof AbstractArrow || aom4 == this.player) {
                        this.disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_entity_attacked"));
                        ServerGamePacketListenerImpl.LOGGER.warn("Player {} tried to attack an invalid entity", this.player.getName().getString());
                        return;
                    }
                    this.player.attack(aom4);
                }
                if (optional8.isPresent() && optional8.get().consumesAction()) {
                    CriteriaTriggers.PLAYER_INTERACTED_WITH_ENTITY.trigger(this.player, this.player.getItemInHand(anf7), aom4);
                    if (optional8.get().shouldSwing()) {
                        this.player.swing(anf7, true);
                    }
                }
            }
        }
    }
    
    @Override
    public void handleClientCommand(final ServerboundClientCommandPacket re) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)re, this, this.player.getLevel());
        this.player.resetLastActionTime();
        final ServerboundClientCommandPacket.Action a3 = re.getAction();
        switch (a3) {
            case PERFORM_RESPAWN: {
                if (this.player.wonGame) {
                    this.player.wonGame = false;
                    this.player = this.server.getPlayerList().respawn(this.player, true);
                    CriteriaTriggers.CHANGED_DIMENSION.trigger(this.player, Level.END, Level.OVERWORLD);
                    break;
                }
                if (this.player.getHealth() > 0.0f) {
                    return;
                }
                this.player = this.server.getPlayerList().respawn(this.player, 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 rk) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)rk, this, this.player.getLevel());
        this.player.doCloseContainer();
    }
    
    @Override
    public void handleContainerClick(final ServerboundContainerClickPacket rj) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)rj, this, this.player.getLevel());
        this.player.resetLastActionTime();
        if (this.player.containerMenu.containerId == rj.getContainerId() && this.player.containerMenu.isSynched(this.player)) {
            if (this.player.isSpectator()) {
                final NonNullList<ItemStack> gi3 = NonNullList.<ItemStack>create();
                for (int integer4 = 0; integer4 < this.player.containerMenu.slots.size(); ++integer4) {
                    gi3.add(this.player.containerMenu.slots.get(integer4).getItem());
                }
                this.player.refreshContainer(this.player.containerMenu, gi3);
            }
            else {
                final ItemStack bki3 = this.player.containerMenu.clicked(rj.getSlotNum(), rj.getButtonNum(), rj.getClickType(), this.player);
                if (ItemStack.matches(rj.getItem(), bki3)) {
                    this.player.connection.send(new ClientboundContainerAckPacket(rj.getContainerId(), rj.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, rj.getUid());
                    this.player.connection.send(new ClientboundContainerAckPacket(rj.getContainerId(), rj.getUid(), false));
                    this.player.containerMenu.setSynched(this.player, false);
                    final NonNullList<ItemStack> gi4 = NonNullList.<ItemStack>create();
                    for (int integer5 = 0; integer5 < this.player.containerMenu.slots.size(); ++integer5) {
                        final ItemStack bki4 = this.player.containerMenu.slots.get(integer5).getItem();
                        gi4.add(bki4.isEmpty() ? ItemStack.EMPTY : bki4);
                    }
                    this.player.refreshContainer(this.player.containerMenu, gi4);
                }
            }
        }
    }
    
    @Override
    public void handlePlaceRecipe(final ServerboundPlaceRecipePacket rw) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)rw, this, this.player.getLevel());
        this.player.resetLastActionTime();
        if (this.player.isSpectator() || this.player.containerMenu.containerId != rw.getContainerId() || !this.player.containerMenu.isSynched(this.player) || !(this.player.containerMenu instanceof RecipeBookMenu)) {
            return;
        }
        this.server.getRecipeManager().byKey(rw.getRecipe()).ifPresent(bmu -> ((RecipeBookMenu)this.player.containerMenu).handlePlacement(rw.isShiftDown(), bmu, this.player));
    }
    
    @Override
    public void handleContainerButtonClick(final ServerboundContainerButtonClickPacket ri) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)ri, this, this.player.getLevel());
        this.player.resetLastActionTime();
        if (this.player.containerMenu.containerId == ri.getContainerId() && this.player.containerMenu.isSynched(this.player) && !this.player.isSpectator()) {
            this.player.containerMenu.clickMenuButton(this.player, ri.getButtonId());
            this.player.containerMenu.broadcastChanges();
        }
    }
    
    @Override
    public void handleSetCreativeModeSlot(final ServerboundSetCreativeModeSlotPacket sk) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)sk, this, this.player.getLevel());
        if (this.player.gameMode.isCreative()) {
            final boolean boolean3 = sk.getSlotNum() < 0;
            final ItemStack bki4 = sk.getItem();
            final CompoundTag le5 = bki4.getTagElement("BlockEntityTag");
            if (!bki4.isEmpty() && le5 != null && le5.contains("x") && le5.contains("y") && le5.contains("z")) {
                final BlockPos fu6 = new BlockPos(le5.getInt("x"), le5.getInt("y"), le5.getInt("z"));
                final BlockEntity cdl7 = this.player.level.getBlockEntity(fu6);
                if (cdl7 != null) {
                    final CompoundTag le6 = cdl7.save(new CompoundTag());
                    le6.remove("x");
                    le6.remove("y");
                    le6.remove("z");
                    bki4.addTagElement("BlockEntityTag", le6);
                }
            }
            final boolean boolean4 = sk.getSlotNum() >= 1 && sk.getSlotNum() <= 45;
            final boolean boolean5 = bki4.isEmpty() || (bki4.getDamageValue() >= 0 && bki4.getCount() <= 64 && !bki4.isEmpty());
            if (boolean4 && boolean5) {
                if (bki4.isEmpty()) {
                    this.player.inventoryMenu.setItem(sk.getSlotNum(), ItemStack.EMPTY);
                }
                else {
                    this.player.inventoryMenu.setItem(sk.getSlotNum(), bki4);
                }
                this.player.inventoryMenu.setSynched(this.player, true);
                this.player.inventoryMenu.broadcastChanges();
            }
            else if (boolean3 && boolean5 && this.dropSpamTickCount < 200) {
                this.dropSpamTickCount += 20;
                this.player.drop(bki4, true);
            }
        }
    }
    
    @Override
    public void handleContainerAck(final ServerboundContainerAckPacket rh) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)rh, this, this.player.getLevel());
        final int integer3 = this.player.containerMenu.containerId;
        if (integer3 == rh.getContainerId() && this.expectedAcks.getOrDefault(integer3, (short)(rh.getUid() + 1)) == rh.getUid() && !this.player.containerMenu.isSynched(this.player) && !this.player.isSpectator()) {
            this.player.containerMenu.setSynched(this.player, true);
        }
    }
    
    @Override
    public void handleSignUpdate(final ServerboundSignUpdatePacket sn) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)sn, this, this.player.getLevel());
        this.player.resetLastActionTime();
        final ServerLevel zd3 = this.player.getLevel();
        final BlockPos fu4 = sn.getPos();
        if (zd3.hasChunkAt(fu4)) {
            final BlockState cfj5 = zd3.getBlockState(fu4);
            final BlockEntity cdl6 = zd3.getBlockEntity(fu4);
            if (!(cdl6 instanceof SignBlockEntity)) {
                return;
            }
            final SignBlockEntity ceh7 = (SignBlockEntity)cdl6;
            if (!ceh7.isEditable() || ceh7.getPlayerWhoMayEdit() != this.player) {
                ServerGamePacketListenerImpl.LOGGER.warn("Player {} just tried to change non-editable sign", this.player.getName().getString());
                return;
            }
            final String[] arr8 = sn.getLines();
            for (int integer9 = 0; integer9 < arr8.length; ++integer9) {
                ceh7.setMessage(integer9, new TextComponent(ChatFormatting.stripFormatting(arr8[integer9])));
            }
            ceh7.setChanged();
            zd3.sendBlockUpdated(fu4, cfj5, cfj5, 3);
        }
    }
    
    @Override
    public void handleKeepAlive(final ServerboundKeepAlivePacket rq) {
        if (this.keepAlivePending && rq.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"));
        }
    }
    
    @Override
    public void handlePlayerAbilities(final ServerboundPlayerAbilitiesPacket rx) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)rx, this, this.player.getLevel());
        this.player.abilities.flying = (rx.isFlying() && this.player.abilities.mayfly);
    }
    
    @Override
    public void handleClientInformation(final ServerboundClientInformationPacket rf) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)rf, this, this.player.getLevel());
        this.player.updateOptions(rf);
    }
    
    @Override
    public void handleCustomPayload(final ServerboundCustomPayloadPacket rl) {
    }
    
    @Override
    public void handleChangeDifficulty(final ServerboundChangeDifficultyPacket rc) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)rc, this, this.player.getLevel());
        if (!this.player.hasPermissions(2) && !this.isSingleplayerOwner()) {
            return;
        }
        this.server.setDifficulty(rc.getDifficulty(), false);
    }
    
    @Override
    public void handleLockDifficulty(final ServerboundLockDifficultyPacket rr) {
        PacketUtils.<ServerGamePacketListenerImpl>ensureRunningOnSameThread((Packet<ServerGamePacketListenerImpl>)rr, this, this.player.getLevel());
        if (!this.player.hasPermissions(2) && !this.isSingleplayerOwner()) {
            return;
        }
        this.server.setDifficultyLocked(rr.isLocked());
    }
    
    static {
        LOGGER = LogManager.getLogger();
    }
}
