package net.minecraft.client;

import java.util.AbstractList;
import org.apache.logging.log4j.LogManager;
import net.minecraft.world.item.crafting.Recipe;
import java.util.Optional;
import java.util.concurrent.CompletionStage;
import net.minecraft.client.resources.PackAdapterV4;
import net.minecraft.client.resources.LegacyResourcePackAdapter;
import net.minecraft.server.packs.metadata.pack.PackMetadataSection;
import java.util.function.Supplier;
import net.minecraft.util.profiling.ProfilerFiller;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.dimension.end.TheEndDimension;
import net.minecraft.world.level.dimension.NetherDimension;
import net.minecraft.client.gui.screens.WinScreen;
import com.mojang.authlib.GameProfile;
import com.google.common.collect.Multimap;
import java.nio.ByteOrder;
import com.mojang.blaze3d.platform.GlUtil;
import net.minecraft.nbt.StringTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.Tag;
import net.minecraft.world.item.PlayerHeadItem;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.item.SpawnEggItem;
import net.minecraft.world.entity.boss.enderdragon.EndCrystal;
import net.minecraft.world.entity.decoration.ArmorStand;
import net.minecraft.world.entity.vehicle.Boat;
import net.minecraft.world.entity.vehicle.AbstractMinecart;
import net.minecraft.world.entity.decoration.ItemFrame;
import net.minecraft.world.entity.decoration.LeashFenceKnotEntity;
import net.minecraft.world.level.ItemLike;
import net.minecraft.world.item.Items;
import net.minecraft.world.entity.decoration.Painting;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher;
import com.mojang.authlib.AuthenticationService;
import net.minecraft.client.gui.screens.ProgressScreen;
import java.net.SocketAddress;
import com.mojang.authlib.GameProfileRepository;
import net.minecraft.world.level.storage.LevelStorage;
import net.minecraft.network.protocol.login.ServerboundHelloPacket;
import net.minecraft.network.protocol.handshake.ClientIntentionPacket;
import net.minecraft.network.ConnectionProtocol;
import net.minecraft.network.PacketListener;
import net.minecraft.client.multiplayer.ClientHandshakePacketListenerImpl;
import net.minecraft.client.gui.screens.LevelLoadingScreen;
import net.minecraft.server.level.progress.ChunkProgressListener;
import net.minecraft.server.level.progress.ProcessorChunkProgressListener;
import net.minecraft.world.level.block.entity.SkullBlockEntity;
import net.minecraft.server.players.GameProfileCache;
import net.minecraft.world.level.storage.LevelData;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.level.LevelSettings;
import net.minecraft.client.gui.screens.ChatScreen;
import net.minecraft.world.entity.player.ChatVisiblity;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ServerboundPlayerActionPacket;
import net.minecraft.client.gui.screens.advancements.AdvancementsScreen;
import net.minecraft.client.gui.screens.inventory.InventoryScreen;
import net.minecraft.client.gui.screens.inventory.CreativeModeInventoryScreen;
import net.minecraft.CrashReportCategory;
import net.minecraft.world.Difficulty;
import net.minecraft.client.gui.screens.InBedChatScreen;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.phys.EntityHitResult;
import net.minecraft.core.Direction;
import net.minecraft.core.BlockPos;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.client.gui.screens.PauseScreen;
import com.mojang.blaze3d.vertex.BufferBuilder;
import java.text.DecimalFormatSymbols;
import java.text.DecimalFormat;
import net.minecraft.util.Mth;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.Tesselator;
import net.minecraft.util.profiling.ProfileResults;
import net.minecraft.util.profiling.ResultField;
import net.minecraft.client.gui.screens.GenericDirtMessageScreen;
import net.minecraft.client.renderer.FogRenderer;
import net.minecraft.client.gui.chat.NarratorChatListener;
import net.minecraft.client.gui.screens.multiplayer.JoinMultiplayerScreen;
import net.minecraft.client.gui.screens.DeathScreen;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import com.google.common.collect.UnmodifiableIterator;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.renderer.block.BlockModelShaper;
import net.minecraft.client.gui.screens.MenuScreens;
import java.util.Locale;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.Block;
import java.util.Date;
import java.text.SimpleDateFormat;
import net.minecraft.DefaultUncaughtExceptionHandler;
import java.util.Iterator;
import net.minecraft.client.searchtree.MutableSearchTree;
import net.minecraft.client.gui.screens.recipebook.RecipeCollection;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.Item;
import net.minecraft.core.NonNullList;
import net.minecraft.client.searchtree.ReloadableIdSearchTree;
import net.minecraft.tags.ItemTags;
import net.minecraft.world.item.ItemStack;
import net.minecraft.client.searchtree.ReloadableSearchTree;
import java.util.stream.Stream;
import net.minecraft.core.Registry;
import net.minecraft.ChatFormatting;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.ReportedException;
import net.minecraft.client.gui.screens.OutOfMemoryScreen;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.client.gui.components.toasts.SystemToast;
import java.util.Collection;
import java.util.Collections;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.client.multiplayer.ClientPacketListener;
import net.minecraft.client.resources.language.I18n;
import java.io.InputStream;
import net.minecraft.SharedConstants;
import java.util.concurrent.Executor;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.function.Function;
import net.minecraft.server.packs.repository.UnopenedPack;
import net.minecraft.server.packs.Pack;
import java.util.List;
import net.minecraft.client.gui.screens.LoadingOverlay;
import net.minecraft.client.gui.screens.ConnectScreen;
import net.minecraft.client.gui.screens.TitleScreen;
import net.minecraft.world.level.Level;
import net.minecraft.client.resources.FoliageColorReloadListener;
import net.minecraft.client.resources.GrassColorReloadListener;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.server.packs.resources.PreparableReloadListener;
import net.minecraft.server.packs.resources.SimpleReloadableResourceManager;
import java.io.IOException;
import net.minecraft.server.packs.PackType;
import com.mojang.blaze3d.platform.DisplayData;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.util.datafix.DataFixers;
import net.minecraft.network.chat.KeybindComponent;
import net.minecraft.server.Bootstrap;
import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
import java.util.UUID;
import net.minecraft.server.packs.repository.FolderRepositorySource;
import net.minecraft.server.packs.repository.RepositorySource;
import com.google.common.collect.Queues;
import net.minecraft.Util;
import net.minecraft.client.main.GameConfig;
import java.util.Queue;
import net.minecraft.CrashReport;
import net.minecraft.client.gui.screens.Overlay;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.entity.Entity;
import net.minecraft.network.Connection;
import net.minecraft.client.multiplayer.ServerData;
import net.minecraft.client.server.IntegratedServer;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.client.multiplayer.ClientLevel;
import javax.annotation.Nullable;
import net.minecraft.client.multiplayer.MultiPlayerGameMode;
import net.minecraft.client.tutorial.Tutorial;
import net.minecraft.client.gui.components.toasts.ToastComponent;
import net.minecraft.client.resources.MobEffectTextureManager;
import net.minecraft.client.resources.PaintingTextureManager;
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
import net.minecraft.client.resources.model.ModelManager;
import net.minecraft.client.resources.SkinManager;
import com.mojang.authlib.minecraft.MinecraftSessionService;
import net.minecraft.client.resources.SplashManager;
import net.minecraft.client.gui.font.FontManager;
import net.minecraft.client.sounds.MusicManager;
import net.minecraft.client.sounds.SoundManager;
import com.mojang.blaze3d.pipeline.RenderTarget;
import net.minecraft.client.color.item.ItemColors;
import net.minecraft.client.color.block.BlockColors;
import net.minecraft.client.resources.language.LanguageManager;
import net.minecraft.client.resources.UnopenedResourcePack;
import net.minecraft.server.packs.repository.PackRepository;
import net.minecraft.client.resources.ClientPackSource;
import net.minecraft.server.packs.resources.ReloadableResourceManager;
import net.minecraft.util.profiling.GameProfiler;
import net.minecraft.util.FrameTimer;
import net.minecraft.world.level.storage.LevelStorageSource;
import java.net.Proxy;
import net.minecraft.client.gui.Gui;
import net.minecraft.server.level.progress.StoringChunkProgressListener;
import java.util.concurrent.atomic.AtomicReference;
import net.minecraft.client.renderer.debug.DebugRenderer;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.gui.Font;
import net.minecraft.client.searchtree.SearchRegistry;
import net.minecraft.client.particle.ParticleEngine;
import net.minecraft.client.renderer.ItemInHandRenderer;
import net.minecraft.client.renderer.entity.ItemRenderer;
import net.minecraft.client.renderer.entity.EntityRenderDispatcher;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.RenderBuffers;
import net.minecraft.world.Snooper;
import com.mojang.blaze3d.platform.Window;
import net.minecraft.client.renderer.VirtualScreen;
import com.mojang.datafixers.DataFixer;
import net.minecraft.client.renderer.texture.TextureManager;
import com.mojang.authlib.properties.PropertyMap;
import java.io.File;
import net.minecraft.util.Unit;
import java.util.concurrent.CompletableFuture;
import net.minecraft.resources.ResourceLocation;
import org.apache.logging.log4j.Logger;
import com.mojang.blaze3d.platform.WindowEventHandler;
import net.minecraft.world.SnooperPopulator;
import net.minecraft.util.thread.ReentrantBlockableEventLoop;

public class Minecraft extends ReentrantBlockableEventLoop<Runnable> implements SnooperPopulator, WindowEventHandler {
    private static Minecraft instance;
    private static final Logger LOGGER;
    public static final boolean ON_OSX;
    public static final ResourceLocation DEFAULT_FONT;
    public static final ResourceLocation ALT_FONT;
    private static final CompletableFuture<Unit> RESOURCE_RELOAD_INITIAL_TASK;
    private final File resourcePackDirectory;
    private final PropertyMap profileProperties;
    private final TextureManager textureManager;
    private final DataFixer fixerUpper;
    private final VirtualScreen virtualScreen;
    private final Window window;
    private final Timer timer;
    private final Snooper snooper;
    private final RenderBuffers renderBuffers;
    public final LevelRenderer levelRenderer;
    private final EntityRenderDispatcher entityRenderDispatcher;
    private final ItemRenderer itemRenderer;
    private final ItemInHandRenderer itemInHandRenderer;
    public final ParticleEngine particleEngine;
    private final SearchRegistry searchRegistry;
    private final User user;
    public final Font font;
    public final GameRenderer gameRenderer;
    public final DebugRenderer debugRenderer;
    private final AtomicReference<StoringChunkProgressListener> progressListener;
    public final Gui gui;
    public final Options options;
    private final HotbarManager hotbarManager;
    public final MouseHandler mouseHandler;
    public final KeyboardHandler keyboardHandler;
    public final File gameDirectory;
    private final String launchedVersion;
    private final String versionType;
    private final Proxy proxy;
    private final LevelStorageSource levelSource;
    public final FrameTimer frameTimer;
    private final boolean is64bit;
    private final boolean demo;
    private final GameProfiler profiler;
    private final ReloadableResourceManager resourceManager;
    private final ClientPackSource clientPackSource;
    private final PackRepository<UnopenedResourcePack> resourcePackRepository;
    private final LanguageManager languageManager;
    private final BlockColors blockColors;
    private final ItemColors itemColors;
    private final RenderTarget mainRenderTarget;
    private final SoundManager soundManager;
    private final MusicManager musicManager;
    private final FontManager fontManager;
    private final SplashManager splashManager;
    private final MinecraftSessionService minecraftSessionService;
    private final SkinManager skinManager;
    private final ModelManager modelManager;
    private final BlockRenderDispatcher blockRenderer;
    private final PaintingTextureManager paintingTextures;
    private final MobEffectTextureManager mobEffectTextures;
    private final ToastComponent toast;
    private final Game game;
    private final Tutorial tutorial;
    public static byte[] reserve;
    @Nullable
    public MultiPlayerGameMode gameMode;
    @Nullable
    public ClientLevel level;
    @Nullable
    public LocalPlayer player;
    @Nullable
    private IntegratedServer singleplayerServer;
    @Nullable
    private ServerData currentServer;
    @Nullable
    private Connection pendingConnection;
    private boolean isLocalServer;
    @Nullable
    public Entity cameraEntity;
    @Nullable
    public Entity crosshairPickEntity;
    @Nullable
    public HitResult hitResult;
    private int rightClickDelay;
    protected int missTime;
    private boolean pause;
    private float pausePartialTick;
    private long lastNanoTime;
    private long lastTime;
    private int frames;
    public boolean noRender;
    @Nullable
    public Screen screen;
    @Nullable
    public Overlay overlay;
    private boolean connectedToRealms;
    private Thread gameThread;
    private volatile boolean running;
    @Nullable
    private CrashReport delayedCrash;
    private static int fps;
    public String fpsString;
    public boolean chunkPath;
    public boolean chunkVisibility;
    public boolean smartCull;
    private boolean windowActive;
    private final Queue<Runnable> progressTasks;
    @Nullable
    private CompletableFuture<Void> pendingReload;
    private String debugPath;
    
    public Minecraft(final GameConfig djy) {
        super("Client");
        this.timer = new Timer(20.0f, 0L);
        this.snooper = new Snooper("client", this, Util.getMillis());
        this.searchRegistry = new SearchRegistry();
        this.progressListener = new AtomicReference<StoringChunkProgressListener>();
        this.frameTimer = new FrameTimer();
        this.profiler = new GameProfiler(() -> this.timer.ticks);
        this.game = new Game(this);
        this.lastNanoTime = Util.getNanos();
        this.running = true;
        this.fpsString = "";
        this.smartCull = true;
        this.progressTasks = Queues.newConcurrentLinkedQueue();
        this.debugPath = "root";
        Minecraft.instance = this;
        this.gameDirectory = djy.location.gameDirectory;
        final File file3 = djy.location.assetDirectory;
        this.resourcePackDirectory = djy.location.resourcePackDirectory;
        this.launchedVersion = djy.game.launchVersion;
        this.versionType = djy.game.versionType;
        this.profileProperties = djy.user.profileProperties;
        this.clientPackSource = new ClientPackSource(new File(this.gameDirectory, "server-resource-packs"), djy.location.getAssetIndex());
        (this.resourcePackRepository = new PackRepository<UnopenedResourcePack>(Minecraft::createClientPackAdapter)).addSource(this.clientPackSource);
        this.resourcePackRepository.addSource(new FolderRepositorySource(this.resourcePackDirectory));
        this.proxy = djy.user.proxy;
        this.minecraftSessionService = new YggdrasilAuthenticationService(this.proxy, UUID.randomUUID().toString()).createMinecraftSessionService();
        this.user = djy.user.user;
        Minecraft.LOGGER.info("Setting user: {}", this.user.getName());
        Minecraft.LOGGER.debug("(Session ID is {})", this.user.getSessionId());
        this.demo = djy.game.demo;
        this.is64bit = checkIs64Bit();
        this.singleplayerServer = null;
        String string4;
        int integer5;
        if (djy.server.hostname != null) {
            string4 = djy.server.hostname;
            integer5 = djy.server.port;
        }
        else {
            string4 = null;
            integer5 = 0;
        }
        Bootstrap.bootStrap();
        Bootstrap.validate();
        KeybindComponent.keyResolver = KeyMapping::createNameSupplier;
        this.fixerUpper = DataFixers.getDataFixer();
        this.toast = new ToastComponent(this);
        this.tutorial = new Tutorial(this);
        this.gameThread = Thread.currentThread();
        this.options = new Options(this, this.gameDirectory);
        this.hotbarManager = new HotbarManager(this.gameDirectory, this.fixerUpper);
        this.startTimerHackThread();
        Minecraft.LOGGER.info("Backend library: {}", RenderSystem.getBackendDescription());
        DisplayData cxh6;
        if (this.options.overrideHeight > 0 && this.options.overrideWidth > 0) {
            cxh6 = new DisplayData(this.options.overrideWidth, this.options.overrideHeight, djy.display.fullscreenWidth, djy.display.fullscreenHeight, djy.display.isFullscreen);
        }
        else {
            cxh6 = djy.display;
        }
        Util.timeSource = RenderSystem.initBackendSystem();
        this.virtualScreen = new VirtualScreen(this);
        this.window = this.virtualScreen.newWindow(cxh6, this.options.fullscreenVideoModeString, this.createTitle());
        this.setWindowActive(true);
        try {
            final InputStream inputStream7 = this.getClientPackSource().getVanillaPack().getResource(PackType.CLIENT_RESOURCES, new ResourceLocation("icons/icon_16x16.png"));
            final InputStream inputStream8 = this.getClientPackSource().getVanillaPack().getResource(PackType.CLIENT_RESOURCES, new ResourceLocation("icons/icon_32x32.png"));
            this.window.setIcon(inputStream7, inputStream8);
        }
        catch (IOException iOException7) {
            Minecraft.LOGGER.error("Couldn't set icon", (Throwable)iOException7);
        }
        this.window.setFramerateLimit(this.options.framerateLimit);
        (this.mouseHandler = new MouseHandler(this)).setup(this.window.getWindow());
        (this.keyboardHandler = new KeyboardHandler(this)).setup(this.window.getWindow());
        RenderSystem.initRenderer(this.options.glDebugVerbosity, false);
        (this.mainRenderTarget = new RenderTarget(this.window.getWidth(), this.window.getHeight(), true, Minecraft.ON_OSX)).setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        this.resourceManager = new SimpleReloadableResourceManager(PackType.CLIENT_RESOURCES, this.gameThread);
        this.options.loadResourcePacks(this.resourcePackRepository);
        this.resourcePackRepository.reload();
        this.languageManager = new LanguageManager(this.options.languageCode);
        this.resourceManager.registerReloadListener(this.languageManager);
        this.textureManager = new TextureManager(this.resourceManager);
        this.resourceManager.registerReloadListener(this.textureManager);
        this.skinManager = new SkinManager(this.textureManager, new File(file3, "skins"), this.minecraftSessionService);
        this.levelSource = new LevelStorageSource(this.gameDirectory.toPath().resolve("saves"), this.gameDirectory.toPath().resolve("backups"), this.fixerUpper);
        this.soundManager = new SoundManager(this.resourceManager, this.options);
        this.resourceManager.registerReloadListener(this.soundManager);
        this.splashManager = new SplashManager(this.user);
        this.resourceManager.registerReloadListener(this.splashManager);
        this.musicManager = new MusicManager(this);
        this.fontManager = new FontManager(this.textureManager, this.isEnforceUnicode());
        this.resourceManager.registerReloadListener(this.fontManager.getReloadListener());
        final Font dch7 = this.fontManager.get(Minecraft.DEFAULT_FONT);
        if (dch7 == null) {
            throw new IllegalStateException("Default font is null");
        }
        (this.font = dch7).setBidirectional(this.languageManager.isBidirectional());
        this.resourceManager.registerReloadListener(new GrassColorReloadListener());
        this.resourceManager.registerReloadListener(new FoliageColorReloadListener());
        this.window.setErrorSection("Startup");
        RenderSystem.setupDefaultState(0, 0, this.window.getWidth(), this.window.getHeight());
        this.window.setErrorSection("Post startup");
        this.blockColors = BlockColors.createDefault();
        this.itemColors = ItemColors.createDefault(this.blockColors);
        this.modelManager = new ModelManager(this.textureManager, this.blockColors, this.options.mipmapLevels);
        this.resourceManager.registerReloadListener(this.modelManager);
        this.itemRenderer = new ItemRenderer(this.textureManager, this.modelManager, this.itemColors);
        this.entityRenderDispatcher = new EntityRenderDispatcher(this.textureManager, this.itemRenderer, this.resourceManager, this.font, this.options);
        this.itemInHandRenderer = new ItemInHandRenderer(this);
        this.resourceManager.registerReloadListener(this.itemRenderer);
        this.renderBuffers = new RenderBuffers();
        this.gameRenderer = new GameRenderer(this, this.resourceManager, this.renderBuffers);
        this.resourceManager.registerReloadListener(this.gameRenderer);
        this.blockRenderer = new BlockRenderDispatcher(this.modelManager.getBlockModelShaper(), this.blockColors);
        this.resourceManager.registerReloadListener(this.blockRenderer);
        this.levelRenderer = new LevelRenderer(this, this.renderBuffers);
        this.resourceManager.registerReloadListener(this.levelRenderer);
        this.createSearchTrees();
        this.resourceManager.registerReloadListener(this.searchRegistry);
        this.particleEngine = new ParticleEngine(this.level, this.textureManager);
        this.resourceManager.registerReloadListener(this.particleEngine);
        this.paintingTextures = new PaintingTextureManager(this.textureManager);
        this.resourceManager.registerReloadListener(this.paintingTextures);
        this.mobEffectTextures = new MobEffectTextureManager(this.textureManager);
        this.resourceManager.registerReloadListener(this.mobEffectTextures);
        this.gui = new Gui(this);
        this.debugRenderer = new DebugRenderer(this);
        RenderSystem.setErrorCallback(this::onFullscreenError);
        if (this.options.fullscreen && !this.window.isFullscreen()) {
            this.window.toggleFullScreen();
            this.options.fullscreen = this.window.isFullscreen();
        }
        this.window.updateVsync(this.options.enableVsync);
        this.window.updateRawMouseInput(this.options.rawMouseInput);
        this.window.setDefaultErrorCallback();
        this.resizeDisplay();
        if (string4 != null) {
            this.setScreen(new ConnectScreen(new TitleScreen(), this, string4, integer5));
        }
        else {
            this.setScreen(new TitleScreen(true));
        }
        LoadingOverlay.registerTextures(this);
        final List<Pack> list8 = this.resourcePackRepository.getSelected().stream().map(UnopenedPack::open).collect(Collectors.toList());
        this.setOverlay(new LoadingOverlay(this, this.resourceManager.createFullReload(Util.backgroundExecutor(), this, Minecraft.RESOURCE_RELOAD_INITIAL_TASK, list8), optional -> Util.<Throwable>ifElse(optional, this::rollbackResourcePacks, () -> {
            this.languageManager.reload(list8);
            if (SharedConstants.IS_RUNNING_IN_IDE) {
                this.selfTest();
            }
        }), false));
    }
    
    public void updateTitle() {
        this.window.setTitle(this.createTitle());
    }
    
    private String createTitle() {
        final StringBuilder stringBuilder2 = new StringBuilder("Minecraft");
        if (this.isProbablyModded()) {
            stringBuilder2.append("*");
        }
        stringBuilder2.append(" ");
        stringBuilder2.append(SharedConstants.getCurrentVersion().getName());
        final ClientPacketListener dnp3 = this.getConnection();
        if (dnp3 != null && dnp3.getConnection().isConnected()) {
            stringBuilder2.append(" - ");
            if (this.singleplayerServer != null && !this.singleplayerServer.isPublished()) {
                stringBuilder2.append(I18n.get("title.singleplayer"));
            }
            else if (this.isConnectedToRealms()) {
                stringBuilder2.append(I18n.get("title.multiplayer.realms"));
            }
            else if (this.singleplayerServer != null || (this.currentServer != null && this.currentServer.isLan())) {
                stringBuilder2.append(I18n.get("title.multiplayer.lan"));
            }
            else {
                stringBuilder2.append(I18n.get("title.multiplayer.other"));
            }
        }
        return stringBuilder2.toString();
    }
    
    public boolean isProbablyModded() {
        return !"vanilla".equals(ClientBrandRetriever.getClientModName()) || Minecraft.class.getSigners() == null;
    }
    
    private void rollbackResourcePacks(final Throwable throwable) {
        if (this.resourcePackRepository.getSelected().size() > 1) {
            if (throwable instanceof SimpleReloadableResourceManager.ResourcePackLoadingFailure) {
                final Component lf3 = new TextComponent(((SimpleReloadableResourceManager.ResourcePackLoadingFailure)throwable).getPack().getName());
            }
            else {
                final Component lf3 = null;
            }
            Minecraft.LOGGER.info("Caught error loading resourcepacks, removing all selected resourcepacks", throwable);
            this.resourcePackRepository.setSelected(Collections.emptyList());
            this.options.resourcePacks.clear();
            this.options.incompatibleResourcePacks.clear();
            this.options.save();
            final ToastComponent deb3;
            final Component lf4;
            this.reloadResourcePacks().thenRun(() -> {
                deb3 = this.getToasts();
                SystemToast.addOrUpdate(deb3, SystemToast.SystemToastIds.PACK_LOAD_FAILURE, new TranslatableComponent("resourcePack.load_fail", new Object[0]), lf4);
            });
        }
        else {
            Util.throwAsRuntime(throwable);
        }
    }
    
    public void run() {
        this.gameThread = Thread.currentThread();
        try {
            boolean boolean2 = false;
            while (this.running) {
                if (this.delayedCrash != null) {
                    crash(this.delayedCrash);
                    return;
                }
                try {
                    this.runTick(!boolean2);
                }
                catch (OutOfMemoryError outOfMemoryError3) {
                    if (boolean2) {
                        throw outOfMemoryError3;
                    }
                    this.emergencySave();
                    this.setScreen(new OutOfMemoryScreen());
                    System.gc();
                    Minecraft.LOGGER.fatal("Out of memory", (Throwable)outOfMemoryError3);
                    boolean2 = true;
                }
            }
        }
        catch (ReportedException q2) {
            this.fillReport(q2.getReport());
            this.emergencySave();
            Minecraft.LOGGER.fatal("Reported exception thrown!", (Throwable)q2);
            crash(q2.getReport());
        }
        catch (Throwable throwable2) {
            final CrashReport h3 = this.fillReport(new CrashReport("Unexpected error", throwable2));
            Minecraft.LOGGER.fatal("Unreported exception thrown!", throwable2);
            this.emergencySave();
            crash(h3);
        }
    }
    
    private void createSearchTrees() {
        final ReloadableSearchTree<ItemStack> edg2 = new ReloadableSearchTree<ItemStack>(ben -> ben.getTooltipLines(null, TooltipFlag.Default.NORMAL).stream().map(lf -> ChatFormatting.stripFormatting(lf.getString()).trim()).filter(string -> !string.isEmpty()), ben -> Stream.<ResourceLocation>of(Registry.ITEM.getKey(ben.getItem())));
        final ReloadableIdSearchTree<ItemStack> edf3 = new ReloadableIdSearchTree<ItemStack>(ben -> ItemTags.getAllTags().getMatchingTags(ben.getItem()).stream());
        final NonNullList<ItemStack> fy4 = NonNullList.<ItemStack>create();
        for (final Item bei6 : Registry.ITEM) {
            bei6.fillItemCategory(CreativeModeTab.TAB_SEARCH, fy4);
        }
        final ReloadableIdSearchTree<ItemStack> reloadableIdSearchTree;
        final ReloadableIdSearchTree<ItemStack> reloadableIdSearchTree2;
        fy4.forEach(ben -> {
            reloadableIdSearchTree.add(ben);
            reloadableIdSearchTree2.add(ben);
            return;
        });
        final ReloadableSearchTree<RecipeCollection> edg3 = new ReloadableSearchTree<RecipeCollection>(dit -> dit.getRecipes().stream().flatMap(bgw -> bgw.getResultItem().getTooltipLines(null, TooltipFlag.Default.NORMAL).stream()).map(lf -> ChatFormatting.stripFormatting(lf.getString()).trim()).filter(string -> !string.isEmpty()), dit -> dit.getRecipes().stream().map(bgw -> Registry.ITEM.getKey(bgw.getResultItem().getItem())));
        this.searchRegistry.<ItemStack>register(SearchRegistry.CREATIVE_NAMES, edg2);
        this.searchRegistry.<ItemStack>register(SearchRegistry.CREATIVE_TAGS, edf3);
        this.searchRegistry.<RecipeCollection>register(SearchRegistry.RECIPE_COLLECTIONS, edg3);
    }
    
    private void onFullscreenError(final int integer, final long long2) {
        this.options.enableVsync = false;
        this.options.save();
    }
    
    private static boolean checkIs64Bit() {
        final String[] array;
        final String[] arr1 = array = new String[] { "sun.arch.data.model", "com.ibm.vm.bitmode", "os.arch" };
        for (final String string5 : array) {
            final String string6 = System.getProperty(string5);
            if (string6 != null && string6.contains("64")) {
                return true;
            }
        }
        return false;
    }
    
    public RenderTarget getMainRenderTarget() {
        return this.mainRenderTarget;
    }
    
    public String getLaunchedVersion() {
        return this.launchedVersion;
    }
    
    public String getVersionType() {
        return this.versionType;
    }
    
    private void startTimerHackThread() {
        final Thread thread2 = new Thread("Timer hack thread") {
            @Override
            public void run() {
                while (Minecraft.this.running) {
                    try {
                        Thread.sleep(2147483647L);
                    }
                    catch (InterruptedException ex) {}
                }
            }
        };
        thread2.setDaemon(true);
        thread2.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(Minecraft.LOGGER));
        thread2.start();
    }
    
    public void delayCrash(final CrashReport h) {
        this.delayedCrash = h;
    }
    
    public static void crash(final CrashReport h) {
        final File file2 = new File(getInstance().gameDirectory, "crash-reports");
        final File file3 = new File(file2, "crash-" + new SimpleDateFormat("yyyy-MM-dd_HH.mm.ss").format(new Date()) + "-client.txt");
        Bootstrap.realStdoutPrintln(h.getFriendlyReport());
        if (h.getSaveFile() != null) {
            Bootstrap.realStdoutPrintln("#@!@# Game crashed! Crash report saved to: #@!@# " + h.getSaveFile());
            System.exit(-1);
        }
        else if (h.saveToFile(file3)) {
            Bootstrap.realStdoutPrintln("#@!@# Game crashed! Crash report saved to: #@!@# " + file3.getAbsolutePath());
            System.exit(-1);
        }
        else {
            Bootstrap.realStdoutPrintln("#@?@# Game crashed! Crash report could not be saved. #@?@#");
            System.exit(-2);
        }
    }
    
    public boolean isEnforceUnicode() {
        return this.options.forceUnicodeFont;
    }
    
    public CompletableFuture<Void> reloadResourcePacks() {
        if (this.pendingReload != null) {
            return this.pendingReload;
        }
        final CompletableFuture<Void> completableFuture2 = new CompletableFuture<Void>();
        if (this.overlay instanceof LoadingOverlay) {
            return this.pendingReload = completableFuture2;
        }
        this.resourcePackRepository.reload();
        final List<Pack> list3 = this.resourcePackRepository.getSelected().stream().map(UnopenedPack::open).collect(Collectors.toList());
        final List<Pack> list4;
        final CompletableFuture<Object> completableFuture3;
        this.setOverlay(new LoadingOverlay(this, this.resourceManager.createFullReload(Util.backgroundExecutor(), this, Minecraft.RESOURCE_RELOAD_INITIAL_TASK, list3), optional -> Util.<Throwable>ifElse(optional, this::rollbackResourcePacks, () -> {
            this.languageManager.reload(list4);
            this.levelRenderer.allChanged();
            completableFuture3.complete(null);
        }), true));
        return completableFuture2;
    }
    
    private void selfTest() {
        boolean boolean2 = false;
        final BlockModelShaper drj3 = this.getBlockRenderer().getBlockModelShaper();
        final BakedModel ebv4 = drj3.getModelManager().getMissingModel();
        for (final Block bph6 : Registry.BLOCK) {
            for (final BlockState byj8 : bph6.getStateDefinition().getPossibleStates()) {
                if (byj8.getRenderShape() == RenderShape.MODEL) {
                    final BakedModel ebv5 = drj3.getBlockModel(byj8);
                    if (ebv5 != ebv4) {
                        continue;
                    }
                    Minecraft.LOGGER.debug("Missing model for: {}", byj8);
                    boolean2 = true;
                }
            }
        }
        final TextureAtlasSprite eaj5 = ebv4.getParticleIcon();
        for (final Block bph7 : Registry.BLOCK) {
            for (final BlockState byj9 : bph7.getStateDefinition().getPossibleStates()) {
                final TextureAtlasSprite eaj6 = drj3.getParticleIcon(byj9);
                if (!byj9.isAir() && eaj6 == eaj5) {
                    Minecraft.LOGGER.debug("Missing particle icon for: {}", byj9);
                    boolean2 = true;
                }
            }
        }
        final NonNullList<ItemStack> fy6 = NonNullList.<ItemStack>create();
        for (final Item bei8 : Registry.ITEM) {
            fy6.clear();
            bei8.fillItemCategory(CreativeModeTab.TAB_SEARCH, fy6);
            for (final ItemStack ben10 : fy6) {
                final String string11 = ben10.getDescriptionId();
                final String string12 = new TranslatableComponent(string11, new Object[0]).getString();
                if (string12.toLowerCase(Locale.ROOT).equals(bei8.getDescriptionId())) {
                    Minecraft.LOGGER.debug("Missing translation for: {} {} {}", ben10, string11, ben10.getItem());
                }
            }
        }
        boolean2 |= MenuScreens.selfTest();
        if (boolean2) {
            throw new IllegalStateException("Your game data is foobar, fix the errors above!");
        }
    }
    
    public LevelStorageSource getLevelSource() {
        return this.levelSource;
    }
    
    public void setScreen(@Nullable Screen dgb) {
        if (this.screen != null) {
            this.screen.removed();
        }
        if (dgb == null && this.level == null) {
            dgb = new TitleScreen();
        }
        else if (dgb == null && this.player.getHealth() <= 0.0f) {
            if (this.player.shouldShowDeathScreen()) {
                dgb = new DeathScreen(null, this.level.getLevelData().isHardcore());
            }
            else {
                this.player.respawn();
            }
        }
        if (dgb instanceof TitleScreen || dgb instanceof JoinMultiplayerScreen) {
            this.options.renderDebug = false;
            this.gui.getChat().clearMessages(true);
        }
        if ((this.screen = dgb) != null) {
            this.mouseHandler.releaseMouse();
            KeyMapping.releaseAll();
            dgb.init(this, this.window.getGuiScaledWidth(), this.window.getGuiScaledHeight());
            this.noRender = false;
            NarratorChatListener.INSTANCE.sayNow(dgb.getNarrationMessage());
        }
        else {
            this.soundManager.resume();
            this.mouseHandler.grabMouse();
        }
        this.updateTitle();
    }
    
    public void setOverlay(@Nullable final Overlay dfw) {
        this.overlay = dfw;
    }
    
    public void destroy() {
        try {
            Minecraft.LOGGER.info("Stopping!");
            try {
                NarratorChatListener.INSTANCE.destroy();
            }
            catch (Throwable t) {}
            try {
                if (this.level != null) {
                    this.level.disconnect();
                }
                this.clearLevel();
            }
            catch (Throwable t2) {}
            if (this.screen != null) {
                this.screen.removed();
            }
            this.close();
        }
        finally {
            Util.timeSource = System::nanoTime;
            if (this.delayedCrash == null) {
                System.exit(0);
            }
        }
    }
    
    @Override
    public void close() {
        try {
            this.modelManager.close();
            this.fontManager.close();
            this.gameRenderer.close();
            this.levelRenderer.close();
            this.soundManager.destroy();
            this.resourcePackRepository.close();
            this.particleEngine.close();
            this.mobEffectTextures.close();
            this.paintingTextures.close();
            this.textureManager.close();
            Util.shutdownBackgroundExecutor();
        }
        catch (Throwable throwable2) {
            Minecraft.LOGGER.error("Shutdown failure!", throwable2);
            throw throwable2;
        }
        finally {
            this.virtualScreen.close();
            this.window.close();
        }
    }
    
    private void runTick(final boolean boolean1) {
        this.window.setErrorSection("Pre render");
        final long long3 = Util.getNanos();
        this.profiler.startTick();
        if (this.window.shouldClose()) {
            this.stop();
        }
        if (this.pendingReload != null && !(this.overlay instanceof LoadingOverlay)) {
            final CompletableFuture<Void> completableFuture5 = this.pendingReload;
            this.pendingReload = null;
            this.reloadResourcePacks().thenRun(() -> completableFuture5.complete(null));
        }
        Runnable runnable5;
        while ((runnable5 = this.progressTasks.poll()) != null) {
            runnable5.run();
        }
        if (boolean1) {
            this.timer.advanceTime(Util.getMillis());
            this.profiler.push("scheduledExecutables");
            this.runAllTasks();
            this.profiler.pop();
        }
        this.profiler.push("tick");
        if (boolean1) {
            for (int integer6 = 0; integer6 < Math.min(10, this.timer.ticks); ++integer6) {
                this.tick();
            }
        }
        this.mouseHandler.turnPlayer();
        this.window.setErrorSection("Render");
        this.profiler.popPush("sound");
        this.soundManager.updateSource(this.gameRenderer.getMainCamera());
        this.profiler.pop();
        this.profiler.push("render");
        RenderSystem.pushMatrix();
        RenderSystem.clear(16640, Minecraft.ON_OSX);
        this.mainRenderTarget.bindWrite(true);
        FogRenderer.setupNoFog();
        this.profiler.push("display");
        RenderSystem.enableTexture();
        this.profiler.pop();
        if (!this.noRender) {
            this.profiler.popPush("gameRenderer");
            this.gameRenderer.render(this.pause ? this.pausePartialTick : this.timer.partialTick, long3, boolean1);
            this.profiler.popPush("toasts");
            this.toast.render();
            this.profiler.pop();
        }
        this.profiler.endTick();
        if (this.options.renderDebug && this.options.renderDebugCharts && !this.options.hideGui) {
            this.profiler.continuous().enable();
            this.renderFpsMeter();
        }
        else {
            this.profiler.continuous().disable();
        }
        this.mainRenderTarget.unbindWrite();
        RenderSystem.popMatrix();
        RenderSystem.pushMatrix();
        this.mainRenderTarget.blitToScreen(this.window.getWidth(), this.window.getHeight());
        RenderSystem.popMatrix();
        this.profiler.startTick();
        this.profiler.push("updateDisplay");
        this.window.updateDisplay();
        int integer6 = this.getFramerateLimit();
        if (integer6 < Option.FRAMERATE_LIMIT.getMaxValue()) {
            RenderSystem.limitDisplayFPS(integer6);
        }
        this.profiler.popPush("yield");
        Thread.yield();
        this.profiler.pop();
        this.window.setErrorSection("Post render");
        ++this.frames;
        final boolean boolean2 = this.hasSingleplayerServer() && ((this.screen != null && this.screen.isPauseScreen()) || (this.overlay != null && this.overlay.isPauseScreen())) && !this.singleplayerServer.isPublished();
        if (this.pause != boolean2) {
            if (this.pause) {
                this.pausePartialTick = this.timer.partialTick;
            }
            else {
                this.timer.partialTick = this.pausePartialTick;
            }
            this.pause = boolean2;
        }
        final long long4 = Util.getNanos();
        this.frameTimer.logFrameDuration(long4 - this.lastNanoTime);
        this.lastNanoTime = long4;
        while (Util.getMillis() >= this.lastTime + 1000L) {
            Minecraft.fps = this.frames;
            this.fpsString = String.format("%d fps T: %s%s%s%s B: %d", Minecraft.fps, (this.options.framerateLimit == Option.FRAMERATE_LIMIT.getMaxValue()) ? "inf" : Integer.valueOf(this.options.framerateLimit), this.options.enableVsync ? " vsync" : "", this.options.fancyGraphics ? "" : " fast", (this.options.renderClouds == CloudStatus.OFF) ? "" : ((this.options.renderClouds == CloudStatus.FAST) ? " fast-clouds" : " fancy-clouds"), this.options.biomeBlendRadius);
            this.lastTime += 1000L;
            this.frames = 0;
            this.snooper.prepare();
            if (!this.snooper.isStarted()) {
                this.snooper.start();
            }
        }
        this.profiler.endTick();
    }
    
    @Override
    public void resizeDisplay() {
        final int integer2 = this.window.calculateScale(this.options.guiScale, this.isEnforceUnicode());
        this.window.setGuiScale(integer2);
        if (this.screen != null) {
            this.screen.resize(this, this.window.getGuiScaledWidth(), this.window.getGuiScaledHeight());
        }
        final RenderTarget cxe3 = this.getMainRenderTarget();
        cxe3.resize(this.window.getWidth(), this.window.getHeight(), Minecraft.ON_OSX);
        this.gameRenderer.resize(this.window.getWidth(), this.window.getHeight());
        this.mouseHandler.setIgnoreFirstMove();
    }
    
    private int getFramerateLimit() {
        if (this.level == null && (this.screen != null || this.overlay != null)) {
            return 60;
        }
        return this.window.getFramerateLimit();
    }
    
    public void emergencySave() {
        try {
            Minecraft.reserve = new byte[0];
            this.levelRenderer.clear();
        }
        catch (Throwable t) {}
        try {
            System.gc();
            if (this.isLocalServer && this.singleplayerServer != null) {
                this.singleplayerServer.halt(true);
            }
            this.clearLevel(new GenericDirtMessageScreen(new TranslatableComponent("menu.savingLevel", new Object[0])));
        }
        catch (Throwable t2) {}
        System.gc();
    }
    
    void debugFpsMeterKeyPress(int integer) {
        final ProfileResults ain3 = this.profiler.continuous().getResults();
        final List<ResultField> list4 = ain3.getTimes(this.debugPath);
        if (list4.isEmpty()) {
            return;
        }
        final ResultField aiq5 = list4.remove(0);
        if (integer == 0) {
            if (!aiq5.name.isEmpty()) {
                final int integer2 = this.debugPath.lastIndexOf(30);
                if (integer2 >= 0) {
                    this.debugPath = this.debugPath.substring(0, integer2);
                }
            }
        }
        else if (--integer < list4.size() && !"unspecified".equals(list4.get(integer).name)) {
            if (!this.debugPath.isEmpty()) {
                this.debugPath += '\u001e';
            }
            this.debugPath += list4.get(integer).name;
        }
    }
    
    private void renderFpsMeter() {
        if (!this.profiler.continuous().isEnabled()) {
            return;
        }
        final ProfileResults ain2 = this.profiler.continuous().getResults();
        final List<ResultField> list3 = ain2.getTimes(this.debugPath);
        final ResultField aiq4 = list3.remove(0);
        RenderSystem.clear(256, Minecraft.ON_OSX);
        RenderSystem.matrixMode(5889);
        RenderSystem.loadIdentity();
        RenderSystem.ortho(0.0, this.window.getWidth(), this.window.getHeight(), 0.0, 1000.0, 3000.0);
        RenderSystem.matrixMode(5888);
        RenderSystem.loadIdentity();
        RenderSystem.translatef(0.0f, 0.0f, -2000.0f);
        RenderSystem.lineWidth(1.0f);
        RenderSystem.disableTexture();
        final Tesselator cym5 = Tesselator.getInstance();
        final BufferBuilder cyg6 = cym5.getBuilder();
        final int integer7 = 160;
        final int integer8 = this.window.getWidth() - 160 - 10;
        final int integer9 = this.window.getHeight() - 320;
        RenderSystem.enableBlend();
        cyg6.begin(7, DefaultVertexFormat.POSITION_COLOR);
        cyg6.vertex(integer8 - 176.0f, integer9 - 96.0f - 16.0f, 0.0).color(200, 0, 0, 0).endVertex();
        cyg6.vertex(integer8 - 176.0f, integer9 + 320, 0.0).color(200, 0, 0, 0).endVertex();
        cyg6.vertex(integer8 + 176.0f, integer9 + 320, 0.0).color(200, 0, 0, 0).endVertex();
        cyg6.vertex(integer8 + 176.0f, integer9 - 96.0f - 16.0f, 0.0).color(200, 0, 0, 0).endVertex();
        cym5.end();
        RenderSystem.disableBlend();
        double double10 = 0.0;
        for (final ResultField aiq5 : list3) {
            final int integer10 = Mth.floor(aiq5.percentage / 4.0) + 1;
            cyg6.begin(6, DefaultVertexFormat.POSITION_COLOR);
            final int integer11 = aiq5.getColor();
            final int integer12 = integer11 >> 16 & 0xFF;
            final int integer13 = integer11 >> 8 & 0xFF;
            final int integer14 = integer11 & 0xFF;
            cyg6.vertex(integer8, integer9, 0.0).color(integer12, integer13, integer14, 255).endVertex();
            for (int integer15 = integer10; integer15 >= 0; --integer15) {
                final float float20 = (float)((double10 + aiq5.percentage * integer15 / integer10) * 6.2831854820251465 / 100.0);
                final float float21 = Mth.sin(float20) * 160.0f;
                final float float22 = Mth.cos(float20) * 160.0f * 0.5f;
                cyg6.vertex(integer8 + float21, integer9 - float22, 0.0).color(integer12, integer13, integer14, 255).endVertex();
            }
            cym5.end();
            cyg6.begin(5, DefaultVertexFormat.POSITION_COLOR);
            for (int integer15 = integer10; integer15 >= 0; --integer15) {
                final float float20 = (float)((double10 + aiq5.percentage * integer15 / integer10) * 6.2831854820251465 / 100.0);
                final float float21 = Mth.sin(float20) * 160.0f;
                final float float22 = Mth.cos(float20) * 160.0f * 0.5f;
                if (float22 <= 0.0f) {
                    cyg6.vertex(integer8 + float21, integer9 - float22, 0.0).color(integer12 >> 1, integer13 >> 1, integer14 >> 1, 255).endVertex();
                    cyg6.vertex(integer8 + float21, integer9 - float22 + 10.0f, 0.0).color(integer12 >> 1, integer13 >> 1, integer14 >> 1, 255).endVertex();
                }
            }
            cym5.end();
            double10 += aiq5.percentage;
        }
        final DecimalFormat decimalFormat12 = new DecimalFormat("##0.00");
        decimalFormat12.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT));
        RenderSystem.enableTexture();
        final String string13 = ProfileResults.demanglePath(aiq4.name);
        String string14 = "";
        if (!"unspecified".equals(string13)) {
            string14 += "[0] ";
        }
        if (string13.isEmpty()) {
            string14 += "ROOT ";
        }
        else {
            string14 = string14 + string13 + ' ';
        }
        final int integer11 = 16777215;
        this.font.drawShadow(string14, (float)(integer8 - 160), (float)(integer9 - 80 - 16), 16777215);
        string14 = decimalFormat12.format(aiq4.globalPercentage) + "%";
        this.font.drawShadow(string14, (float)(integer8 + 160 - this.font.width(string14)), (float)(integer9 - 80 - 16), 16777215);
        for (int integer16 = 0; integer16 < list3.size(); ++integer16) {
            final ResultField aiq6 = list3.get(integer16);
            final StringBuilder stringBuilder15 = new StringBuilder();
            if ("unspecified".equals(aiq6.name)) {
                stringBuilder15.append("[?] ");
            }
            else {
                stringBuilder15.append("[").append(integer16 + 1).append("] ");
            }
            String string15 = stringBuilder15.append(aiq6.name).toString();
            this.font.drawShadow(string15, (float)(integer8 - 160), (float)(integer9 + 80 + integer16 * 8 + 20), aiq6.getColor());
            string15 = decimalFormat12.format(aiq6.percentage) + "%";
            this.font.drawShadow(string15, (float)(integer8 + 160 - 50 - this.font.width(string15)), (float)(integer9 + 80 + integer16 * 8 + 20), aiq6.getColor());
            string15 = decimalFormat12.format(aiq6.globalPercentage) + "%";
            this.font.drawShadow(string15, (float)(integer8 + 160 - this.font.width(string15)), (float)(integer9 + 80 + integer16 * 8 + 20), aiq6.getColor());
        }
    }
    
    public void stop() {
        this.running = false;
    }
    
    public boolean isRunning() {
        return this.running;
    }
    
    public void pauseGame(final boolean boolean1) {
        if (this.screen != null) {
            return;
        }
        final boolean boolean2 = this.hasSingleplayerServer() && !this.singleplayerServer.isPublished();
        if (boolean2) {
            this.setScreen(new PauseScreen(!boolean1));
            this.soundManager.pause();
        }
        else {
            this.setScreen(new PauseScreen(true));
        }
    }
    
    private void continueAttack(final boolean boolean1) {
        if (!boolean1) {
            this.missTime = 0;
        }
        if (this.missTime > 0 || this.player.isUsingItem()) {
            return;
        }
        if (boolean1 && this.hitResult != null && this.hitResult.getType() == HitResult.Type.BLOCK) {
            final BlockHitResult cvg3 = (BlockHitResult)this.hitResult;
            final BlockPos fk4 = cvg3.getBlockPos();
            if (!this.level.getBlockState(fk4).isAir()) {
                final Direction fp5 = cvg3.getDirection();
                if (this.gameMode.continueDestroyBlock(fk4, fp5)) {
                    this.particleEngine.crack(fk4, fp5);
                    this.player.swing(InteractionHand.MAIN_HAND);
                }
            }
            return;
        }
        this.gameMode.stopDestroyBlock();
    }
    
    private void startAttack() {
        if (this.missTime > 0) {
            return;
        }
        if (this.hitResult == null) {
            Minecraft.LOGGER.error("Null returned as 'hitResult', this shouldn't happen!");
            if (this.gameMode.hasMissTime()) {
                this.missTime = 10;
            }
            return;
        }
        if (this.player.isHandsBusy()) {
            return;
        }
        switch (this.hitResult.getType()) {
            case ENTITY: {
                this.gameMode.attack(this.player, ((EntityHitResult)this.hitResult).getEntity());
                break;
            }
            case BLOCK: {
                final BlockHitResult cvg2 = (BlockHitResult)this.hitResult;
                final BlockPos fk3 = cvg2.getBlockPos();
                if (!this.level.getBlockState(fk3).isAir()) {
                    this.gameMode.startDestroyBlock(fk3, cvg2.getDirection());
                    break;
                }
            }
            case MISS: {
                if (this.gameMode.hasMissTime()) {
                    this.missTime = 10;
                }
                this.player.resetAttackStrengthTicker();
                break;
            }
        }
        this.player.swing(InteractionHand.MAIN_HAND);
    }
    
    private void startUseItem() {
        if (this.gameMode.isDestroying()) {
            return;
        }
        this.rightClickDelay = 4;
        if (this.player.isHandsBusy()) {
            return;
        }
        if (this.hitResult == null) {
            Minecraft.LOGGER.warn("Null returned as 'hitResult', this shouldn't happen!");
        }
        for (final InteractionHand ajk5 : InteractionHand.values()) {
            final ItemStack ben6 = this.player.getItemInHand(ajk5);
            if (this.hitResult != null) {
                switch (this.hitResult.getType()) {
                    case ENTITY: {
                        final EntityHitResult cvh7 = (EntityHitResult)this.hitResult;
                        final Entity akq8 = cvh7.getEntity();
                        InteractionResult ajl9 = this.gameMode.interactAt(this.player, akq8, cvh7, ajk5);
                        if (!ajl9.consumesAction()) {
                            ajl9 = this.gameMode.interact(this.player, akq8, ajk5);
                        }
                        if (ajl9.consumesAction()) {
                            if (ajl9.shouldSwing()) {
                                this.player.swing(ajk5);
                            }
                            return;
                        }
                        break;
                    }
                    case BLOCK: {
                        final BlockHitResult cvg10 = (BlockHitResult)this.hitResult;
                        final int integer11 = ben6.getCount();
                        final InteractionResult ajl10 = this.gameMode.useItemOn(this.player, this.level, ajk5, cvg10);
                        if (ajl10.consumesAction()) {
                            if (ajl10.shouldSwing()) {
                                this.player.swing(ajk5);
                                if (!ben6.isEmpty() && (ben6.getCount() != integer11 || this.gameMode.hasInfiniteItems())) {
                                    this.gameRenderer.itemInHandRenderer.itemUsed(ajk5);
                                }
                            }
                            return;
                        }
                        if (ajl10 == InteractionResult.FAIL) {
                            return;
                        }
                        break;
                    }
                }
            }
            if (!ben6.isEmpty()) {
                final InteractionResult ajl11 = this.gameMode.useItem(this.player, this.level, ajk5);
                if (ajl11.consumesAction()) {
                    if (ajl11.shouldSwing()) {
                        this.player.swing(ajk5);
                    }
                    this.gameRenderer.itemInHandRenderer.itemUsed(ajk5);
                    return;
                }
            }
        }
    }
    
    public MusicManager getMusicManager() {
        return this.musicManager;
    }
    
    public void tick() {
        if (this.rightClickDelay > 0) {
            --this.rightClickDelay;
        }
        this.profiler.push("gui");
        if (!this.pause) {
            this.gui.tick();
        }
        this.profiler.pop();
        this.gameRenderer.pick(1.0f);
        this.tutorial.onLookAt(this.level, this.hitResult);
        this.profiler.push("gameMode");
        if (!this.pause && this.level != null) {
            this.gameMode.tick();
        }
        this.profiler.popPush("textures");
        if (this.level != null) {
            this.textureManager.tick();
        }
        if (this.screen == null && this.player != null) {
            if (this.player.getHealth() <= 0.0f && !(this.screen instanceof DeathScreen)) {
                this.setScreen(null);
            }
            else if (this.player.isSleeping() && this.level != null) {
                this.setScreen(new InBedChatScreen());
            }
        }
        else if (this.screen != null && this.screen instanceof InBedChatScreen && !this.player.isSleeping()) {
            this.setScreen(null);
        }
        if (this.screen != null) {
            this.missTime = 10000;
        }
        if (this.screen != null) {
            Screen.wrapScreenError(() -> this.screen.tick(), "Ticking screen", this.screen.getClass().getCanonicalName());
        }
        if (!this.options.renderDebug) {
            this.gui.clearCache();
        }
        if (this.overlay == null && (this.screen == null || this.screen.passEvents)) {
            this.profiler.popPush("Keybindings");
            this.handleKeybinds();
            if (this.missTime > 0) {
                --this.missTime;
            }
        }
        if (this.level != null) {
            this.profiler.popPush("gameRenderer");
            if (!this.pause) {
                this.gameRenderer.tick();
            }
            this.profiler.popPush("levelRenderer");
            if (!this.pause) {
                this.levelRenderer.tick();
            }
            this.profiler.popPush("level");
            if (!this.pause) {
                if (this.level.getSkyFlashTime() > 0) {
                    this.level.setSkyFlashTime(this.level.getSkyFlashTime() - 1);
                }
                this.level.tickEntities();
            }
        }
        else if (this.gameRenderer.currentEffect() != null) {
            this.gameRenderer.shutdownEffect();
        }
        if (!this.pause) {
            this.musicManager.tick();
        }
        this.soundManager.tick(this.pause);
        if (this.level != null) {
            if (!this.pause) {
                this.level.setSpawnSettings(this.level.getDifficulty() != Difficulty.PEACEFUL, true);
                this.tutorial.tick();
                try {
                    this.level.tick(() -> true);
                }
                catch (Throwable throwable2) {
                    final CrashReport h3 = CrashReport.forThrowable(throwable2, "Exception in world tick");
                    if (this.level == null) {
                        final CrashReportCategory i4 = h3.addCategory("Affected level");
                        i4.setDetail("Problem", "Level is null!");
                    }
                    else {
                        this.level.fillReportDetails(h3);
                    }
                    throw new ReportedException(h3);
                }
            }
            this.profiler.popPush("animateTick");
            if (!this.pause && this.level != null) {
                this.level.animateTick(Mth.floor(this.player.getX()), Mth.floor(this.player.getY()), Mth.floor(this.player.getZ()));
            }
            this.profiler.popPush("particles");
            if (!this.pause) {
                this.particleEngine.tick();
            }
        }
        else if (this.pendingConnection != null) {
            this.profiler.popPush("pendingConnection");
            this.pendingConnection.tick();
        }
        this.profiler.popPush("keyboard");
        this.keyboardHandler.tick();
        this.profiler.pop();
    }
    
    private void handleKeybinds() {
        while (this.options.keyTogglePerspective.consumeClick()) {
            final Options options = this.options;
            ++options.thirdPersonView;
            if (this.options.thirdPersonView > 2) {
                this.options.thirdPersonView = 0;
            }
            if (this.options.thirdPersonView == 0) {
                this.gameRenderer.checkEntityPostEffect(this.getCameraEntity());
            }
            else if (this.options.thirdPersonView == 1) {
                this.gameRenderer.checkEntityPostEffect(null);
            }
            this.levelRenderer.needsUpdate();
        }
        while (this.options.keySmoothCamera.consumeClick()) {
            this.options.smoothCamera = !this.options.smoothCamera;
        }
        for (int integer2 = 0; integer2 < 9; ++integer2) {
            final boolean boolean3 = this.options.keySaveHotbarActivator.isDown();
            final boolean boolean4 = this.options.keyLoadHotbarActivator.isDown();
            if (this.options.keyHotbarSlots[integer2].consumeClick()) {
                if (this.player.isSpectator()) {
                    this.gui.getSpectatorGui().onHotbarSelected(integer2);
                }
                else if (this.player.isCreative() && this.screen == null && (boolean4 || boolean3)) {
                    CreativeModeInventoryScreen.handleHotbarLoadOrSave(this, integer2, boolean4, boolean3);
                }
                else {
                    this.player.inventory.selected = integer2;
                }
            }
        }
        while (this.options.keyInventory.consumeClick()) {
            if (this.gameMode.isServerControlledInventory()) {
                this.player.sendOpenInventory();
            }
            else {
                this.tutorial.onOpenInventory();
                this.setScreen(new InventoryScreen(this.player));
            }
        }
        while (this.options.keyAdvancements.consumeClick()) {
            this.setScreen(new AdvancementsScreen(this.player.connection.getAdvancements()));
        }
        while (this.options.keySwapHands.consumeClick()) {
            if (!this.player.isSpectator()) {
                this.getConnection().send(new ServerboundPlayerActionPacket(ServerboundPlayerActionPacket.Action.SWAP_HELD_ITEMS, BlockPos.ZERO, Direction.DOWN));
            }
        }
        while (this.options.keyDrop.consumeClick()) {
            if (!this.player.isSpectator() && this.player.drop(Screen.hasControlDown())) {
                this.player.swing(InteractionHand.MAIN_HAND);
            }
        }
        final boolean boolean5 = this.options.chatVisibility != ChatVisiblity.HIDDEN;
        if (boolean5) {
            while (this.options.keyChat.consumeClick()) {
                this.setScreen(new ChatScreen(""));
            }
            if (this.screen == null && this.overlay == null && this.options.keyCommand.consumeClick()) {
                this.setScreen(new ChatScreen("/"));
            }
        }
        if (this.player.isUsingItem()) {
            if (!this.options.keyUse.isDown()) {
                this.gameMode.releaseUsingItem(this.player);
            }
            while (this.options.keyAttack.consumeClick()) {}
            while (this.options.keyUse.consumeClick()) {}
            while (this.options.keyPickItem.consumeClick()) {}
        }
        else {
            while (this.options.keyAttack.consumeClick()) {
                this.startAttack();
            }
            while (this.options.keyUse.consumeClick()) {
                this.startUseItem();
            }
            while (this.options.keyPickItem.consumeClick()) {
                this.pickBlock();
            }
        }
        if (this.options.keyUse.isDown() && this.rightClickDelay == 0 && !this.player.isUsingItem()) {
            this.startUseItem();
        }
        this.continueAttack(this.screen == null && this.options.keyAttack.isDown() && this.mouseHandler.isMouseGrabbed());
    }
    
    public void selectLevel(final String string1, final String string2, @Nullable LevelSettings bka) {
        this.clearLevel();
        final LevelStorage crn5 = this.levelSource.selectLevel(string1, null);
        LevelData crm6 = crn5.prepareLevel();
        if (crm6 == null && bka != null) {
            crm6 = new LevelData(bka, string1);
            crn5.saveLevelData(crm6);
        }
        if (bka == null) {
            bka = new LevelSettings(crm6);
        }
        this.progressListener.set(null);
        try {
            final YggdrasilAuthenticationService yggdrasilAuthenticationService7 = new YggdrasilAuthenticationService(this.proxy, UUID.randomUUID().toString());
            final MinecraftSessionService minecraftSessionService8 = yggdrasilAuthenticationService7.createMinecraftSessionService();
            final GameProfileRepository gameProfileRepository9 = yggdrasilAuthenticationService7.createProfileRepository();
            final GameProfileCache zk10 = new GameProfileCache(gameProfileRepository9, new File(this.gameDirectory, MinecraftServer.USERID_CACHE_FILE.getName()));
            SkullBlockEntity.setProfileCache(zk10);
            SkullBlockEntity.setSessionService(minecraftSessionService8);
            GameProfileCache.setUsesAuthentication(false);
            final StoringChunkProgressListener xq3;
            (this.singleplayerServer = new IntegratedServer(this, string1, string2, bka, yggdrasilAuthenticationService7, minecraftSessionService8, gameProfileRepository9, zk10, integer -> {
                xq3 = new StoringChunkProgressListener(integer + 0);
                xq3.start();
                this.progressListener.set(xq3);
                return new ProcessorChunkProgressListener(xq3, this.progressTasks::add);
            })).forkAndRun();
            this.isLocalServer = true;
        }
        catch (Throwable throwable7) {
            final CrashReport h8 = CrashReport.forThrowable(throwable7, "Starting integrated server");
            final CrashReportCategory i9 = h8.addCategory("Starting integrated server");
            i9.setDetail("Level ID", string1);
            i9.setDetail("Level Name", string2);
            throw new ReportedException(h8);
        }
        while (this.progressListener.get() == null) {
            Thread.yield();
        }
        final LevelLoadingScreen dfp7 = new LevelLoadingScreen(this.progressListener.get());
        this.setScreen(dfp7);
        while (!this.singleplayerServer.isReady()) {
            dfp7.tick();
            this.runTick(false);
            try {
                Thread.sleep(16L);
            }
            catch (InterruptedException ex) {}
            if (this.delayedCrash != null) {
                crash(this.delayedCrash);
                return;
            }
        }
        final SocketAddress socketAddress8 = this.singleplayerServer.getConnection().startMemoryChannel();
        final Connection kt9 = Connection.connectToLocalServer(socketAddress8);
        kt9.setListener(new ClientHandshakePacketListenerImpl(kt9, this, null, lf -> {}));
        kt9.send(new ClientIntentionPacket(socketAddress8.toString(), 0, ConnectionProtocol.LOGIN));
        kt9.send(new ServerboundHelloPacket(this.getUser().getGameProfile()));
        this.pendingConnection = kt9;
    }
    
    public void setLevel(final ClientLevel dno) {
        final ProgressScreen dfz3 = new ProgressScreen();
        dfz3.progressStartNoAbort(new TranslatableComponent("connect.joining", new Object[0]));
        this.updateScreenAndTick(dfz3);
        this.updateLevelInEngines(this.level = dno);
        if (!this.isLocalServer) {
            final AuthenticationService authenticationService4 = (AuthenticationService)new YggdrasilAuthenticationService(this.proxy, UUID.randomUUID().toString());
            final MinecraftSessionService minecraftSessionService5 = authenticationService4.createMinecraftSessionService();
            final GameProfileRepository gameProfileRepository6 = authenticationService4.createProfileRepository();
            final GameProfileCache zk7 = new GameProfileCache(gameProfileRepository6, new File(this.gameDirectory, MinecraftServer.USERID_CACHE_FILE.getName()));
            SkullBlockEntity.setProfileCache(zk7);
            SkullBlockEntity.setSessionService(minecraftSessionService5);
            GameProfileCache.setUsesAuthentication(false);
        }
    }
    
    public void clearLevel() {
        this.clearLevel(new ProgressScreen());
    }
    
    public void clearLevel(final Screen dgb) {
        final ClientPacketListener dnp3 = this.getConnection();
        if (dnp3 != null) {
            this.dropAllTasks();
            dnp3.cleanup();
        }
        final IntegratedServer edm4 = this.singleplayerServer;
        this.singleplayerServer = null;
        this.gameRenderer.resetData();
        this.gameMode = null;
        NarratorChatListener.INSTANCE.clear();
        this.updateScreenAndTick(dgb);
        if (this.level != null) {
            if (edm4 != null) {
                while (!edm4.isShutdown()) {
                    this.runTick(false);
                }
            }
            this.clientPackSource.clearServerPack();
            this.gui.onDisconnected();
            this.currentServer = null;
            this.isLocalServer = false;
            this.game.onLeaveGameSession();
        }
        this.updateLevelInEngines(this.level = null);
        this.player = null;
    }
    
    private void updateScreenAndTick(final Screen dgb) {
        this.musicManager.stopPlaying();
        this.soundManager.stop();
        this.cameraEntity = null;
        this.pendingConnection = null;
        this.setScreen(dgb);
        this.runTick(false);
    }
    
    private void updateLevelInEngines(@Nullable final ClientLevel dno) {
        this.levelRenderer.setLevel(dno);
        this.particleEngine.setLevel(dno);
        BlockEntityRenderDispatcher.instance.setLevel(dno);
        this.updateTitle();
    }
    
    public final boolean isDemo() {
        return this.demo;
    }
    
    @Nullable
    public ClientPacketListener getConnection() {
        return (this.player == null) ? null : this.player.connection;
    }
    
    public static boolean renderNames() {
        return !Minecraft.instance.options.hideGui;
    }
    
    public static boolean useFancyGraphics() {
        return Minecraft.instance.options.fancyGraphics;
    }
    
    public static boolean useAmbientOcclusion() {
        return Minecraft.instance.options.ambientOcclusion != AmbientOcclusionStatus.OFF;
    }
    
    private void pickBlock() {
        if (this.hitResult == null || this.hitResult.getType() == HitResult.Type.MISS) {
            return;
        }
        final boolean boolean2 = this.player.abilities.instabuild;
        BlockEntity bwl3 = null;
        final HitResult.Type a5 = this.hitResult.getType();
        ItemStack ben4;
        if (a5 == HitResult.Type.BLOCK) {
            final BlockPos fk6 = ((BlockHitResult)this.hitResult).getBlockPos();
            final BlockState byj7 = this.level.getBlockState(fk6);
            final Block bph8 = byj7.getBlock();
            if (byj7.isAir()) {
                return;
            }
            ben4 = bph8.getCloneItemStack(this.level, fk6, byj7);
            if (ben4.isEmpty()) {
                return;
            }
            if (boolean2 && Screen.hasControlDown() && bph8.isEntityBlock()) {
                bwl3 = this.level.getBlockEntity(fk6);
            }
        }
        else {
            if (a5 != HitResult.Type.ENTITY || !boolean2) {
                return;
            }
            final Entity akq6 = ((EntityHitResult)this.hitResult).getEntity();
            if (akq6 instanceof Painting) {
                ben4 = new ItemStack(Items.PAINTING);
            }
            else if (akq6 instanceof LeashFenceKnotEntity) {
                ben4 = new ItemStack(Items.LEAD);
            }
            else if (akq6 instanceof ItemFrame) {
                final ItemFrame avr7 = (ItemFrame)akq6;
                final ItemStack ben5 = avr7.getItem();
                if (ben5.isEmpty()) {
                    ben4 = new ItemStack(Items.ITEM_FRAME);
                }
                else {
                    ben4 = ben5.copy();
                }
            }
            else if (akq6 instanceof AbstractMinecart) {
                final AbstractMinecart azx7 = (AbstractMinecart)akq6;
                Item bei8 = null;
                switch (azx7.getMinecartType()) {
                    case FURNACE: {
                        bei8 = Items.FURNACE_MINECART;
                        break;
                    }
                    case CHEST: {
                        bei8 = Items.CHEST_MINECART;
                        break;
                    }
                    case TNT: {
                        bei8 = Items.TNT_MINECART;
                        break;
                    }
                    case HOPPER: {
                        bei8 = Items.HOPPER_MINECART;
                        break;
                    }
                    case COMMAND_BLOCK: {
                        bei8 = Items.COMMAND_BLOCK_MINECART;
                        break;
                    }
                    default: {
                        bei8 = Items.MINECART;
                        break;
                    }
                }
                ben4 = new ItemStack(bei8);
            }
            else if (akq6 instanceof Boat) {
                ben4 = new ItemStack(((Boat)akq6).getDropItem());
            }
            else if (akq6 instanceof ArmorStand) {
                ben4 = new ItemStack(Items.ARMOR_STAND);
            }
            else if (akq6 instanceof EndCrystal) {
                ben4 = new ItemStack(Items.END_CRYSTAL);
            }
            else {
                final SpawnEggItem bfl7 = SpawnEggItem.byId(akq6.getType());
                if (bfl7 == null) {
                    return;
                }
                ben4 = new ItemStack(bfl7);
            }
        }
        if (ben4.isEmpty()) {
            String string6 = "";
            if (a5 == HitResult.Type.BLOCK) {
                string6 = Registry.BLOCK.getKey(this.level.getBlockState(((BlockHitResult)this.hitResult).getBlockPos()).getBlock()).toString();
            }
            else if (a5 == HitResult.Type.ENTITY) {
                string6 = Registry.ENTITY_TYPE.getKey(((EntityHitResult)this.hitResult).getEntity().getType()).toString();
            }
            Minecraft.LOGGER.warn("Picking on: [{}] {} gave null item", a5, string6);
            return;
        }
        final Inventory ayi6 = this.player.inventory;
        if (bwl3 != null) {
            this.addCustomNbtData(ben4, bwl3);
        }
        final int integer7 = ayi6.findSlotMatchingItem(ben4);
        if (boolean2) {
            ayi6.setPickedItem(ben4);
            this.gameMode.handleCreativeModeItemAdd(this.player.getItemInHand(InteractionHand.MAIN_HAND), 36 + ayi6.selected);
        }
        else if (integer7 != -1) {
            if (Inventory.isHotbarSlot(integer7)) {
                ayi6.selected = integer7;
            }
            else {
                this.gameMode.handlePickItem(integer7);
            }
        }
    }
    
    private ItemStack addCustomNbtData(final ItemStack ben, final BlockEntity bwl) {
        final CompoundTag jt4 = bwl.save(new CompoundTag());
        if (ben.getItem() instanceof PlayerHeadItem && jt4.contains("Owner")) {
            final CompoundTag jt5 = jt4.getCompound("Owner");
            ben.getOrCreateTag().put("SkullOwner", jt5);
            return ben;
        }
        ben.addTagElement("BlockEntityTag", jt4);
        final CompoundTag jt5 = new CompoundTag();
        final ListTag jz6 = new ListTag();
        ((AbstractList<StringTag>)jz6).add(StringTag.valueOf("\"(+NBT)\""));
        jt5.put("Lore", jz6);
        ben.addTagElement("display", jt5);
        return ben;
    }
    
    public CrashReport fillReport(final CrashReport h) {
        fillReport(this.languageManager, this.launchedVersion, this.options, h);
        if (this.level != null) {
            this.level.fillReportDetails(h);
        }
        return h;
    }
    
    public static void fillReport(@Nullable final LanguageManager ebf, final String string, @Nullable final Options dbr, final CrashReport h) {
        final CrashReportCategory i5 = h.getSystemDetails();
        i5.setDetail("Launched Version", () -> string);
        i5.setDetail("Backend library", RenderSystem::getBackendDescription);
        i5.setDetail("Backend API", RenderSystem::getApiDescription);
        i5.setDetail("GL Caps", RenderSystem::getCapsString);
        i5.setDetail("Using VBOs", () -> "Yes");
        final String string2;
        i5.setDetail("Is Modded", () -> {
            string2 = ClientBrandRetriever.getClientModName();
            if (!"vanilla".equals(string2)) {
                return "Definitely; Client brand changed to '" + string2 + "'";
            }
            else if (Minecraft.class.getSigners() == null) {
                return "Very likely; Jar signature invalidated";
            }
            else {
                return "Probably not. Jar signature remains and client brand is untouched.";
            }
        });
        i5.setDetail("Type", "Client (map_client.txt)");
        if (dbr != null) {
            final StringBuilder stringBuilder2;
            final Iterator<String> iterator;
            String string3;
            i5.setDetail("Resource Packs", () -> {
                stringBuilder2 = new StringBuilder();
                dbr.resourcePacks.iterator();
                while (iterator.hasNext()) {
                    string3 = iterator.next();
                    if (stringBuilder2.length() > 0) {
                        stringBuilder2.append(", ");
                    }
                    stringBuilder2.append(string3);
                    if (dbr.incompatibleResourcePacks.contains(string3)) {
                        stringBuilder2.append(" (incompatible)");
                    }
                }
                return stringBuilder2.toString();
            });
        }
        if (ebf != null) {
            i5.setDetail("Current Language", () -> ebf.getSelected().toString());
        }
        i5.setDetail("CPU", GlUtil::getCpuInfo);
    }
    
    public static Minecraft getInstance() {
        return Minecraft.instance;
    }
    
    public CompletableFuture<Void> delayTextureReload() {
        return this.<CompletableFuture>submit(this::reloadResourcePacks).<Void>thenCompose(completableFuture -> completableFuture);
    }
    
    @Override
    public void populateSnooper(final Snooper ajs) {
        ajs.setDynamicData("fps", Minecraft.fps);
        ajs.setDynamicData("vsync_enabled", this.options.enableVsync);
        ajs.setDynamicData("display_frequency", this.window.getRefreshRate());
        ajs.setDynamicData("display_type", this.window.isFullscreen() ? "fullscreen" : "windowed");
        ajs.setDynamicData("run_time", (Util.getMillis() - ajs.getStartupTime()) / 60L * 1000L);
        ajs.setDynamicData("current_action", this.getCurrentSnooperAction());
        ajs.setDynamicData("language", (this.options.languageCode == null) ? "en_us" : this.options.languageCode);
        final String string3 = (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN) ? "little" : "big";
        ajs.setDynamicData("endianness", string3);
        ajs.setDynamicData("subtitles", this.options.showSubtitles);
        ajs.setDynamicData("touch", this.options.touchscreen ? "touch" : "mouse");
        int integer4 = 0;
        for (final UnopenedResourcePack ebc6 : this.resourcePackRepository.getSelected()) {
            if (!ebc6.isRequired() && !ebc6.isFixedPosition()) {
                ajs.setDynamicData("resource_pack[" + integer4++ + "]", ebc6.getId());
            }
        }
        ajs.setDynamicData("resource_packs", integer4);
        if (this.singleplayerServer != null) {
            ajs.setDynamicData("snooper_partner", this.singleplayerServer.getSnooper().getToken());
        }
    }
    
    private String getCurrentSnooperAction() {
        if (this.singleplayerServer != null) {
            if (this.singleplayerServer.isPublished()) {
                return "hosting_lan";
            }
            return "singleplayer";
        }
        else {
            if (this.currentServer == null) {
                return "out_of_game";
            }
            if (this.currentServer.isLan()) {
                return "playing_lan";
            }
            return "multiplayer";
        }
    }
    
    public void setCurrentServer(@Nullable final ServerData dnu) {
        this.currentServer = dnu;
    }
    
    @Nullable
    public ServerData getCurrentServer() {
        return this.currentServer;
    }
    
    public boolean isLocalServer() {
        return this.isLocalServer;
    }
    
    public boolean hasSingleplayerServer() {
        return this.isLocalServer && this.singleplayerServer != null;
    }
    
    @Nullable
    public IntegratedServer getSingleplayerServer() {
        return this.singleplayerServer;
    }
    
    public Snooper getSnooper() {
        return this.snooper;
    }
    
    public User getUser() {
        return this.user;
    }
    
    public PropertyMap getProfileProperties() {
        if (this.profileProperties.isEmpty()) {
            final GameProfile gameProfile2 = this.getMinecraftSessionService().fillProfileProperties(this.user.getGameProfile(), false);
            this.profileProperties.putAll((Multimap)gameProfile2.getProperties());
        }
        return this.profileProperties;
    }
    
    public Proxy getProxy() {
        return this.proxy;
    }
    
    public TextureManager getTextureManager() {
        return this.textureManager;
    }
    
    public ResourceManager getResourceManager() {
        return this.resourceManager;
    }
    
    public PackRepository<UnopenedResourcePack> getResourcePackRepository() {
        return this.resourcePackRepository;
    }
    
    public ClientPackSource getClientPackSource() {
        return this.clientPackSource;
    }
    
    public File getResourcePackDirectory() {
        return this.resourcePackDirectory;
    }
    
    public LanguageManager getLanguageManager() {
        return this.languageManager;
    }
    
    public Function<ResourceLocation, TextureAtlasSprite> getTextureAtlas(final ResourceLocation sm) {
        return this.modelManager.getAtlas(sm)::getSprite;
    }
    
    public boolean is64Bit() {
        return this.is64bit;
    }
    
    public boolean isPaused() {
        return this.pause;
    }
    
    public SoundManager getSoundManager() {
        return this.soundManager;
    }
    
    public MusicManager.Music getSituationalMusic() {
        if (this.screen instanceof WinScreen) {
            return MusicManager.Music.CREDITS;
        }
        if (this.player == null) {
            return MusicManager.Music.MENU;
        }
        if (this.player.level.dimension instanceof NetherDimension) {
            return MusicManager.Music.NETHER;
        }
        if (this.player.level.dimension instanceof TheEndDimension) {
            if (this.gui.getBossOverlay().shouldPlayMusic()) {
                return MusicManager.Music.END_BOSS;
            }
            return MusicManager.Music.END;
        }
        else {
            final Biome.BiomeCategory b2 = this.player.level.getBiome(new BlockPos(this.player)).getBiomeCategory();
            if (this.musicManager.isPlayingMusic(MusicManager.Music.UNDER_WATER) || (this.player.isUnderWater() && !this.musicManager.isPlayingMusic(MusicManager.Music.GAME) && (b2 == Biome.BiomeCategory.OCEAN || b2 == Biome.BiomeCategory.RIVER))) {
                return MusicManager.Music.UNDER_WATER;
            }
            if (this.player.abilities.instabuild && this.player.abilities.mayfly) {
                return MusicManager.Music.CREATIVE;
            }
            return MusicManager.Music.GAME;
        }
    }
    
    public MinecraftSessionService getMinecraftSessionService() {
        return this.minecraftSessionService;
    }
    
    public SkinManager getSkinManager() {
        return this.skinManager;
    }
    
    @Nullable
    public Entity getCameraEntity() {
        return this.cameraEntity;
    }
    
    public void setCameraEntity(final Entity akq) {
        this.cameraEntity = akq;
        this.gameRenderer.checkEntityPostEffect(akq);
    }
    
    @Override
    protected Thread getRunningThread() {
        return this.gameThread;
    }
    
    @Override
    protected Runnable wrapRunnable(final Runnable runnable) {
        return runnable;
    }
    
    @Override
    protected boolean shouldRun(final Runnable runnable) {
        return true;
    }
    
    public BlockRenderDispatcher getBlockRenderer() {
        return this.blockRenderer;
    }
    
    public EntityRenderDispatcher getEntityRenderDispatcher() {
        return this.entityRenderDispatcher;
    }
    
    public ItemRenderer getItemRenderer() {
        return this.itemRenderer;
    }
    
    public ItemInHandRenderer getItemInHandRenderer() {
        return this.itemInHandRenderer;
    }
    
    public <T> MutableSearchTree<T> getSearchTree(final SearchRegistry.Key<T> a) {
        return this.searchRegistry.<T>getTree(a);
    }
    
    public FrameTimer getFrameTimer() {
        return this.frameTimer;
    }
    
    public boolean isConnectedToRealms() {
        return this.connectedToRealms;
    }
    
    public void setConnectedToRealms(final boolean boolean1) {
        this.connectedToRealms = boolean1;
    }
    
    public DataFixer getFixerUpper() {
        return this.fixerUpper;
    }
    
    public float getFrameTime() {
        return this.timer.partialTick;
    }
    
    public float getDeltaFrameTime() {
        return this.timer.tickDelta;
    }
    
    public BlockColors getBlockColors() {
        return this.blockColors;
    }
    
    public boolean showOnlyReducedInfo() {
        return (this.player != null && this.player.isReducedDebugInfo()) || this.options.reducedDebugInfo;
    }
    
    public ToastComponent getToasts() {
        return this.toast;
    }
    
    public Tutorial getTutorial() {
        return this.tutorial;
    }
    
    public boolean isWindowActive() {
        return this.windowActive;
    }
    
    public HotbarManager getHotbarManager() {
        return this.hotbarManager;
    }
    
    public ModelManager getModelManager() {
        return this.modelManager;
    }
    
    public FontManager getFontManager() {
        return this.fontManager;
    }
    
    public PaintingTextureManager getPaintingTextures() {
        return this.paintingTextures;
    }
    
    public MobEffectTextureManager getMobEffectTextures() {
        return this.mobEffectTextures;
    }
    
    @Override
    public void setWindowActive(final boolean boolean1) {
        this.windowActive = boolean1;
    }
    
    public ProfilerFiller getProfiler() {
        return this.profiler;
    }
    
    public Game getGame() {
        return this.game;
    }
    
    public SplashManager getSplashManager() {
        return this.splashManager;
    }
    
    @Nullable
    public Overlay getOverlay() {
        return this.overlay;
    }
    
    public boolean renderOnThread() {
        return false;
    }
    
    public Window getWindow() {
        return this.window;
    }
    
    public RenderBuffers renderBuffers() {
        return this.renderBuffers;
    }
    
    private static UnopenedResourcePack createClientPackAdapter(final String string, final boolean boolean2, final Supplier<Pack> supplier, final Pack ye, final PackMetadataSection yj, final UnopenedPack.Position a) {
        final int integer7 = yj.getPackFormat();
        Supplier<Pack> supplier2 = supplier;
        if (integer7 <= 3) {
            supplier2 = adaptV3(supplier2);
        }
        if (integer7 <= 4) {
            supplier2 = adaptV4(supplier2);
        }
        return new UnopenedResourcePack(string, boolean2, supplier2, ye, yj, a);
    }
    
    private static Supplier<Pack> adaptV3(final Supplier<Pack> supplier) {
        return (Supplier<Pack>)(() -> new LegacyResourcePackAdapter(supplier.get(), LegacyResourcePackAdapter.V3));
    }
    
    private static Supplier<Pack> adaptV4(final Supplier<Pack> supplier) {
        return (Supplier<Pack>)(() -> new PackAdapterV4(supplier.get()));
    }
    
    public void updateMaxMipLevel(final int integer) {
        this.modelManager.updateMaxMipLevel(integer);
    }
    
    static {
        LOGGER = LogManager.getLogger();
        ON_OSX = (Util.getPlatform() == Util.OS.OSX);
        DEFAULT_FONT = new ResourceLocation("default");
        ALT_FONT = new ResourceLocation("alt");
        RESOURCE_RELOAD_INITIAL_TASK = CompletableFuture.<Unit>completedFuture(Unit.INSTANCE);
        Minecraft.reserve = new byte[10485760];
    }
}
