/* * Decompiled with CFR 0.152. * * Could not load the following classes: * com.google.common.collect.ImmutableMap * com.google.common.collect.Ordering * org.apache.commons.lang3.tuple.Pair * org.jspecify.annotations.Nullable */ package net.minecraft.client.gui; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Ordering; import com.mojang.blaze3d.platform.Window; import java.util.Collection; import java.util.Comparator; import java.util.Map; import java.util.function.Supplier; import net.minecraft.ChatFormatting; import net.minecraft.Optionull; import net.minecraft.client.AttackIndicatorStatus; import net.minecraft.client.DeltaTracker; import net.minecraft.client.Minecraft; import net.minecraft.client.Options; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.BossHealthOverlay; import net.minecraft.client.gui.components.ChatComponent; import net.minecraft.client.gui.components.DebugScreenOverlay; import net.minecraft.client.gui.components.PlayerTabOverlay; import net.minecraft.client.gui.components.SubtitleOverlay; import net.minecraft.client.gui.components.debug.DebugScreenEntries; import net.minecraft.client.gui.components.spectator.SpectatorGui; import net.minecraft.client.gui.contextualbar.ContextualBarRenderer; import net.minecraft.client.gui.contextualbar.ExperienceBarRenderer; import net.minecraft.client.gui.contextualbar.JumpableVehicleBarRenderer; import net.minecraft.client.gui.contextualbar.LocatorBarRenderer; import net.minecraft.client.gui.screens.LevelLoadingScreen; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.RenderPipelines; import net.minecraft.client.renderer.texture.MissingTextureAtlasSprite; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.server.IntegratedServer; import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; import net.minecraft.core.component.DataComponents; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.chat.numbers.NumberFormat; import net.minecraft.network.chat.numbers.StyledFormat; import net.minecraft.resources.Identifier; import net.minecraft.resources.ResourceKey; import net.minecraft.sounds.SoundEvents; import net.minecraft.tags.FluidTags; import net.minecraft.util.ARGB; import net.minecraft.util.Mth; import net.minecraft.util.RandomSource; import net.minecraft.util.StringUtil; import net.minecraft.util.Util; import net.minecraft.util.profiling.Profiler; import net.minecraft.world.MenuProvider; import net.minecraft.world.effect.MobEffect; import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.HumanoidArm; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.PlayerRideableJumping; import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.entity.player.Player; import net.minecraft.world.food.FoodData; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.equipment.Equippable; import net.minecraft.world.level.GameType; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.border.WorldBorder; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.EntityHitResult; import net.minecraft.world.phys.HitResult; import net.minecraft.world.scores.DisplaySlot; import net.minecraft.world.scores.Objective; import net.minecraft.world.scores.PlayerScoreEntry; import net.minecraft.world.scores.PlayerTeam; import net.minecraft.world.scores.Scoreboard; import org.apache.commons.lang3.tuple.Pair; import org.jspecify.annotations.Nullable; public class Gui { private static final Identifier CROSSHAIR_SPRITE = Identifier.withDefaultNamespace("hud/crosshair"); private static final Identifier CROSSHAIR_ATTACK_INDICATOR_FULL_SPRITE = Identifier.withDefaultNamespace("hud/crosshair_attack_indicator_full"); private static final Identifier CROSSHAIR_ATTACK_INDICATOR_BACKGROUND_SPRITE = Identifier.withDefaultNamespace("hud/crosshair_attack_indicator_background"); private static final Identifier CROSSHAIR_ATTACK_INDICATOR_PROGRESS_SPRITE = Identifier.withDefaultNamespace("hud/crosshair_attack_indicator_progress"); private static final Identifier EFFECT_BACKGROUND_AMBIENT_SPRITE = Identifier.withDefaultNamespace("hud/effect_background_ambient"); private static final Identifier EFFECT_BACKGROUND_SPRITE = Identifier.withDefaultNamespace("hud/effect_background"); private static final Identifier HOTBAR_SPRITE = Identifier.withDefaultNamespace("hud/hotbar"); private static final Identifier HOTBAR_SELECTION_SPRITE = Identifier.withDefaultNamespace("hud/hotbar_selection"); private static final Identifier HOTBAR_OFFHAND_LEFT_SPRITE = Identifier.withDefaultNamespace("hud/hotbar_offhand_left"); private static final Identifier HOTBAR_OFFHAND_RIGHT_SPRITE = Identifier.withDefaultNamespace("hud/hotbar_offhand_right"); private static final Identifier HOTBAR_ATTACK_INDICATOR_BACKGROUND_SPRITE = Identifier.withDefaultNamespace("hud/hotbar_attack_indicator_background"); private static final Identifier HOTBAR_ATTACK_INDICATOR_PROGRESS_SPRITE = Identifier.withDefaultNamespace("hud/hotbar_attack_indicator_progress"); private static final Identifier ARMOR_EMPTY_SPRITE = Identifier.withDefaultNamespace("hud/armor_empty"); private static final Identifier ARMOR_HALF_SPRITE = Identifier.withDefaultNamespace("hud/armor_half"); private static final Identifier ARMOR_FULL_SPRITE = Identifier.withDefaultNamespace("hud/armor_full"); private static final Identifier FOOD_EMPTY_HUNGER_SPRITE = Identifier.withDefaultNamespace("hud/food_empty_hunger"); private static final Identifier FOOD_HALF_HUNGER_SPRITE = Identifier.withDefaultNamespace("hud/food_half_hunger"); private static final Identifier FOOD_FULL_HUNGER_SPRITE = Identifier.withDefaultNamespace("hud/food_full_hunger"); private static final Identifier FOOD_EMPTY_SPRITE = Identifier.withDefaultNamespace("hud/food_empty"); private static final Identifier FOOD_HALF_SPRITE = Identifier.withDefaultNamespace("hud/food_half"); private static final Identifier FOOD_FULL_SPRITE = Identifier.withDefaultNamespace("hud/food_full"); private static final Identifier AIR_SPRITE = Identifier.withDefaultNamespace("hud/air"); private static final Identifier AIR_POPPING_SPRITE = Identifier.withDefaultNamespace("hud/air_bursting"); private static final Identifier AIR_EMPTY_SPRITE = Identifier.withDefaultNamespace("hud/air_empty"); private static final Identifier HEART_VEHICLE_CONTAINER_SPRITE = Identifier.withDefaultNamespace("hud/heart/vehicle_container"); private static final Identifier HEART_VEHICLE_FULL_SPRITE = Identifier.withDefaultNamespace("hud/heart/vehicle_full"); private static final Identifier HEART_VEHICLE_HALF_SPRITE = Identifier.withDefaultNamespace("hud/heart/vehicle_half"); private static final Identifier VIGNETTE_LOCATION = Identifier.withDefaultNamespace("textures/misc/vignette.png"); public static final Identifier NAUSEA_LOCATION = Identifier.withDefaultNamespace("textures/misc/nausea.png"); private static final Identifier SPYGLASS_SCOPE_LOCATION = Identifier.withDefaultNamespace("textures/misc/spyglass_scope.png"); private static final Identifier POWDER_SNOW_OUTLINE_LOCATION = Identifier.withDefaultNamespace("textures/misc/powder_snow_outline.png"); private static final Comparator SCORE_DISPLAY_ORDER = Comparator.comparing(PlayerScoreEntry::value).reversed().thenComparing(PlayerScoreEntry::owner, String.CASE_INSENSITIVE_ORDER); private static final Component DEMO_EXPIRED_TEXT = Component.translatable("demo.demoExpired"); private static final Component SAVING_TEXT = Component.translatable("menu.savingLevel"); private static final float MIN_CROSSHAIR_ATTACK_SPEED = 5.0f; private static final int EXPERIENCE_BAR_DISPLAY_TICKS = 100; private static final int NUM_HEARTS_PER_ROW = 10; private static final int LINE_HEIGHT = 10; private static final String SPACER = ": "; private static final float PORTAL_OVERLAY_ALPHA_MIN = 0.2f; private static final int HEART_SIZE = 9; private static final int HEART_SEPARATION = 8; private static final int NUM_AIR_BUBBLES = 10; private static final int AIR_BUBBLE_SIZE = 9; private static final int AIR_BUBBLE_SEPERATION = 8; private static final int AIR_BUBBLE_POPPING_DURATION = 2; private static final int EMPTY_AIR_BUBBLE_DELAY_DURATION = 1; private static final float AIR_BUBBLE_POP_SOUND_VOLUME_BASE = 0.5f; private static final float AIR_BUBBLE_POP_SOUND_VOLUME_INCREMENT = 0.1f; private static final float AIR_BUBBLE_POP_SOUND_PITCH_BASE = 1.0f; private static final float AIR_BUBBLE_POP_SOUND_PITCH_INCREMENT = 0.1f; private static final int NUM_AIR_BUBBLE_POPPED_BEFORE_SOUND_VOLUME_INCREASE = 3; private static final int NUM_AIR_BUBBLE_POPPED_BEFORE_SOUND_PITCH_INCREASE = 5; private static final float AUTOSAVE_FADE_SPEED_FACTOR = 0.2f; private static final int SAVING_INDICATOR_WIDTH_PADDING_RIGHT = 5; private static final int SAVING_INDICATOR_HEIGHT_PADDING_BOTTOM = 5; private final RandomSource random = RandomSource.create(); private final Minecraft minecraft; private final ChatComponent chat; private int tickCount; private @Nullable Component overlayMessageString; private int overlayMessageTime; private boolean animateOverlayMessageColor; private boolean chatDisabledByPlayerShown; public float vignetteBrightness = 1.0f; private int toolHighlightTimer; private ItemStack lastToolHighlight = ItemStack.EMPTY; private final DebugScreenOverlay debugOverlay; private final SubtitleOverlay subtitleOverlay; private final SpectatorGui spectatorGui; private final PlayerTabOverlay tabList; private final BossHealthOverlay bossOverlay; private int titleTime; private @Nullable Component title; private @Nullable Component subtitle; private int titleFadeInTime; private int titleStayTime; private int titleFadeOutTime; private int lastHealth; private int displayHealth; private long lastHealthTime; private long healthBlinkTime; private int lastBubblePopSoundPlayed; private @Nullable Runnable deferredSubtitles; private float autosaveIndicatorValue; private float lastAutosaveIndicatorValue; private Pair contextualInfoBar = Pair.of((Object)((Object)ContextualInfo.EMPTY), (Object)ContextualBarRenderer.EMPTY); private final Map> contextualInfoBarRenderers; private float scopeScale; public Gui(Minecraft minecraft) { this.minecraft = minecraft; this.debugOverlay = new DebugScreenOverlay(minecraft); this.spectatorGui = new SpectatorGui(minecraft); this.chat = new ChatComponent(minecraft); this.tabList = new PlayerTabOverlay(minecraft, this); this.bossOverlay = new BossHealthOverlay(minecraft); this.subtitleOverlay = new SubtitleOverlay(minecraft); this.contextualInfoBarRenderers = ImmutableMap.of((Object)((Object)ContextualInfo.EMPTY), () -> ContextualBarRenderer.EMPTY, (Object)((Object)ContextualInfo.EXPERIENCE), () -> new ExperienceBarRenderer(minecraft), (Object)((Object)ContextualInfo.LOCATOR), () -> new LocatorBarRenderer(minecraft), (Object)((Object)ContextualInfo.JUMPABLE_VEHICLE), () -> new JumpableVehicleBarRenderer(minecraft)); this.resetTitleTimes(); } public void resetTitleTimes() { this.titleFadeInTime = 10; this.titleStayTime = 70; this.titleFadeOutTime = 20; } public void render(GuiGraphics graphics, DeltaTracker deltaTracker) { if (this.minecraft.screen instanceof LevelLoadingScreen) { return; } if (!this.minecraft.options.hideGui) { this.renderCameraOverlays(graphics, deltaTracker); this.renderCrosshair(graphics, deltaTracker); graphics.nextStratum(); this.renderHotbarAndDecorations(graphics, deltaTracker); this.renderEffects(graphics, deltaTracker); this.renderBossOverlay(graphics, deltaTracker); } this.renderSleepOverlay(graphics, deltaTracker); if (!this.minecraft.options.hideGui) { this.renderDemoOverlay(graphics, deltaTracker); this.renderScoreboardSidebar(graphics, deltaTracker); this.renderOverlayMessage(graphics, deltaTracker); this.renderTitle(graphics, deltaTracker); this.renderChat(graphics, deltaTracker); this.renderTabList(graphics, deltaTracker); this.renderSubtitleOverlay(graphics, this.minecraft.screen == null || this.minecraft.screen.isInGameUi()); } else if (this.minecraft.screen != null && this.minecraft.screen.isInGameUi()) { this.renderSubtitleOverlay(graphics, true); } } private void renderBossOverlay(GuiGraphics graphics, DeltaTracker deltaTracker) { this.bossOverlay.render(graphics); } public void renderDebugOverlay(GuiGraphics graphics) { this.debugOverlay.render(graphics); } private void renderSubtitleOverlay(GuiGraphics graphics, boolean deferRendering) { if (deferRendering) { this.deferredSubtitles = () -> this.subtitleOverlay.render(graphics); } else { this.deferredSubtitles = null; this.subtitleOverlay.render(graphics); } } public void renderDeferredSubtitles() { if (this.deferredSubtitles != null) { this.deferredSubtitles.run(); this.deferredSubtitles = null; } } private void renderCameraOverlays(GuiGraphics graphics, DeltaTracker deltaTracker) { float screenEffectScale; if (this.minecraft.options.vignette().get().booleanValue()) { this.renderVignette(graphics, this.minecraft.getCameraEntity()); } LocalPlayer player = this.minecraft.player; float gameTimeDeltaTicks = deltaTracker.getGameTimeDeltaTicks(); this.scopeScale = Mth.lerp(0.5f * gameTimeDeltaTicks, this.scopeScale, 1.125f); if (this.minecraft.options.getCameraType().isFirstPerson()) { if (player.isScoping()) { this.renderSpyglassOverlay(graphics, this.scopeScale); } else { this.scopeScale = 0.5f; for (EquipmentSlot slot : EquipmentSlot.values()) { ItemStack item = player.getItemBySlot(slot); Equippable equippable = item.get(DataComponents.EQUIPPABLE); if (equippable == null || equippable.slot() != slot || !equippable.cameraOverlay().isPresent()) continue; this.renderTextureOverlay(graphics, equippable.cameraOverlay().get().withPath(p -> "textures/" + p + ".png"), 1.0f); } } } if (player.getTicksFrozen() > 0) { this.renderTextureOverlay(graphics, POWDER_SNOW_OUTLINE_LOCATION, player.getPercentFrozen()); } float partialTicks = deltaTracker.getGameTimeDeltaPartialTick(false); float portalIntensity = Mth.lerp(partialTicks, player.oPortalEffectIntensity, player.portalEffectIntensity); float nauseaIntensity = player.getEffectBlendFactor(MobEffects.NAUSEA, partialTicks); if (portalIntensity > 0.0f) { this.renderPortalOverlay(graphics, portalIntensity); } else if (nauseaIntensity > 0.0f && (screenEffectScale = this.minecraft.options.screenEffectScale().get().floatValue()) < 1.0f) { float overlayStrength = nauseaIntensity * (1.0f - screenEffectScale); this.renderConfusionOverlay(graphics, overlayStrength); } } private void renderSleepOverlay(GuiGraphics graphics, DeltaTracker deltaTracker) { if (this.minecraft.player.getSleepTimer() <= 0) { return; } Profiler.get().push("sleep"); graphics.nextStratum(); float sleepTimer = this.minecraft.player.getSleepTimer(); float amount = sleepTimer / 100.0f; if (amount > 1.0f) { amount = 1.0f - (sleepTimer - 100.0f) / 10.0f; } int color = (int)(220.0f * amount) << 24 | 0x101020; graphics.fill(0, 0, graphics.guiWidth(), graphics.guiHeight(), color); Profiler.get().pop(); } private void renderOverlayMessage(GuiGraphics graphics, DeltaTracker deltaTracker) { Font font = this.getFont(); if (this.overlayMessageString == null || this.overlayMessageTime <= 0) { return; } Profiler.get().push("overlayMessage"); float t = (float)this.overlayMessageTime - deltaTracker.getGameTimeDeltaPartialTick(false); int alpha = (int)(t * 255.0f / 20.0f); if (alpha > 255) { alpha = 255; } if (alpha > 0) { graphics.nextStratum(); graphics.pose().pushMatrix(); graphics.pose().translate((float)(graphics.guiWidth() / 2), (float)(graphics.guiHeight() - 68)); int color = this.animateOverlayMessageColor ? Mth.hsvToArgb(t / 50.0f, 0.7f, 0.6f, alpha) : ARGB.white(alpha); int width = font.width(this.overlayMessageString); graphics.drawStringWithBackdrop(font, this.overlayMessageString, -width / 2, -4, width, color); graphics.pose().popMatrix(); } Profiler.get().pop(); } private void renderTitle(GuiGraphics graphics, DeltaTracker deltaTracker) { if (this.title == null || this.titleTime <= 0) { return; } Font font = this.getFont(); Profiler.get().push("titleAndSubtitle"); float t = (float)this.titleTime - deltaTracker.getGameTimeDeltaPartialTick(false); int alpha = 255; if (this.titleTime > this.titleFadeOutTime + this.titleStayTime) { float time = (float)(this.titleFadeInTime + this.titleStayTime + this.titleFadeOutTime) - t; alpha = (int)(time * 255.0f / (float)this.titleFadeInTime); } if (this.titleTime <= this.titleFadeOutTime) { alpha = (int)(t * 255.0f / (float)this.titleFadeOutTime); } if ((alpha = Mth.clamp(alpha, 0, 255)) > 0) { graphics.nextStratum(); graphics.pose().pushMatrix(); graphics.pose().translate((float)(graphics.guiWidth() / 2), (float)(graphics.guiHeight() / 2)); graphics.pose().pushMatrix(); graphics.pose().scale(4.0f, 4.0f); int titleWidth = font.width(this.title); int textColor = ARGB.white(alpha); graphics.drawStringWithBackdrop(font, this.title, -titleWidth / 2, -10, titleWidth, textColor); graphics.pose().popMatrix(); if (this.subtitle != null) { graphics.pose().pushMatrix(); graphics.pose().scale(2.0f, 2.0f); int subtitleWidth = font.width(this.subtitle); graphics.drawStringWithBackdrop(font, this.subtitle, -subtitleWidth / 2, 5, subtitleWidth, textColor); graphics.pose().popMatrix(); } graphics.pose().popMatrix(); } Profiler.get().pop(); } private void renderChat(GuiGraphics graphics, DeltaTracker deltaTracker) { if (!this.chat.isChatFocused()) { Window window = this.minecraft.getWindow(); int mouseX = Mth.floor(this.minecraft.mouseHandler.getScaledXPos(window)); int mouseY = Mth.floor(this.minecraft.mouseHandler.getScaledYPos(window)); graphics.nextStratum(); this.chat.render(graphics, this.getFont(), this.tickCount, mouseX, mouseY, false); } } private void renderScoreboardSidebar(GuiGraphics graphics, DeltaTracker deltaTracker) { Objective displayObjective; DisplaySlot displaySlot; Scoreboard scoreboard = this.minecraft.level.getScoreboard(); Objective teamObjective = null; PlayerTeam playerTeam = scoreboard.getPlayersTeam(this.minecraft.player.getScoreboardName()); if (playerTeam != null && (displaySlot = DisplaySlot.teamColorToSlot(playerTeam.getColor())) != null) { teamObjective = scoreboard.getDisplayObjective(displaySlot); } Objective objective = displayObjective = teamObjective != null ? teamObjective : scoreboard.getDisplayObjective(DisplaySlot.SIDEBAR); if (displayObjective != null) { graphics.nextStratum(); this.displayScoreboardSidebar(graphics, displayObjective); } } private void renderTabList(GuiGraphics graphics, DeltaTracker deltaTracker) { Scoreboard scoreboard = this.minecraft.level.getScoreboard(); Objective displayObjective = scoreboard.getDisplayObjective(DisplaySlot.LIST); if (this.minecraft.options.keyPlayerList.isDown() && (!this.minecraft.isLocalServer() || this.minecraft.player.connection.getListedOnlinePlayers().size() > 1 || displayObjective != null)) { this.tabList.setVisible(true); graphics.nextStratum(); this.tabList.render(graphics, graphics.guiWidth(), scoreboard, displayObjective); } else { this.tabList.setVisible(false); } } private void renderCrosshair(GuiGraphics graphics, DeltaTracker deltaTracker) { Options options = this.minecraft.options; if (!options.getCameraType().isFirstPerson()) { return; } if (this.minecraft.gameMode.getPlayerMode() == GameType.SPECTATOR && !this.canRenderCrosshairForSpectator(this.minecraft.hitResult)) { return; } if (!this.minecraft.debugEntries.isCurrentlyEnabled(DebugScreenEntries.THREE_DIMENSIONAL_CROSSHAIR)) { graphics.nextStratum(); int size = 15; graphics.blitSprite(RenderPipelines.CROSSHAIR, CROSSHAIR_SPRITE, (graphics.guiWidth() - 15) / 2, (graphics.guiHeight() - 15) / 2, 15, 15); if (this.minecraft.options.attackIndicator().get() == AttackIndicatorStatus.CROSSHAIR) { float attackStrengthScale = this.minecraft.player.getAttackStrengthScale(0.0f); boolean renderMaxAttackIndicator = false; if (this.minecraft.crosshairPickEntity != null && this.minecraft.crosshairPickEntity instanceof LivingEntity && attackStrengthScale >= 1.0f) { renderMaxAttackIndicator = this.minecraft.player.getCurrentItemAttackStrengthDelay() > 5.0f; renderMaxAttackIndicator &= this.minecraft.crosshairPickEntity.isAlive(); } int y = graphics.guiHeight() / 2 - 7 + 16; int x = graphics.guiWidth() / 2 - 8; if (renderMaxAttackIndicator) { graphics.blitSprite(RenderPipelines.CROSSHAIR, CROSSHAIR_ATTACK_INDICATOR_FULL_SPRITE, x, y, 16, 16); } else if (attackStrengthScale < 1.0f) { int progress = (int)(attackStrengthScale * 17.0f); graphics.blitSprite(RenderPipelines.CROSSHAIR, CROSSHAIR_ATTACK_INDICATOR_BACKGROUND_SPRITE, x, y, 16, 4); graphics.blitSprite(RenderPipelines.CROSSHAIR, CROSSHAIR_ATTACK_INDICATOR_PROGRESS_SPRITE, 16, 4, 0, 0, x, y, progress, 4); } } } } private boolean canRenderCrosshairForSpectator(@Nullable HitResult hitResult) { if (hitResult == null) { return false; } if (hitResult.getType() == HitResult.Type.ENTITY) { return ((EntityHitResult)hitResult).getEntity() instanceof MenuProvider; } if (hitResult.getType() == HitResult.Type.BLOCK) { ClientLevel level = this.minecraft.level; BlockPos pos = ((BlockHitResult)hitResult).getBlockPos(); return level.getBlockState(pos).getMenuProvider(level, pos) != null; } return false; } private void renderEffects(GuiGraphics graphics, DeltaTracker deltaTracker) { Collection activeEffects = this.minecraft.player.getActiveEffects(); if (activeEffects.isEmpty() || this.minecraft.screen != null && this.minecraft.screen.showsActiveEffects()) { return; } int beneficialCount = 0; int harmfulCount = 0; for (MobEffectInstance instance : Ordering.natural().reverse().sortedCopy(activeEffects)) { Holder effect = instance.getEffect(); if (!instance.showIcon()) continue; int x = graphics.guiWidth(); int y = 1; if (this.minecraft.isDemo()) { y += 15; } if (effect.value().isBeneficial()) { x -= 25 * ++beneficialCount; } else { x -= 25 * ++harmfulCount; y += 26; } float alpha = 1.0f; if (instance.isAmbient()) { graphics.blitSprite(RenderPipelines.GUI_TEXTURED, EFFECT_BACKGROUND_AMBIENT_SPRITE, x, y, 24, 24); } else { graphics.blitSprite(RenderPipelines.GUI_TEXTURED, EFFECT_BACKGROUND_SPRITE, x, y, 24, 24); if (instance.endsWithin(200)) { int remainingDuration = instance.getDuration(); int usedSeconds = 10 - remainingDuration / 20; alpha = Mth.clamp((float)remainingDuration / 10.0f / 5.0f * 0.5f, 0.0f, 0.5f) + Mth.cos((float)remainingDuration * (float)Math.PI / 5.0f) * Mth.clamp((float)usedSeconds / 10.0f * 0.25f, 0.0f, 0.25f); alpha = Mth.clamp(alpha, 0.0f, 1.0f); } } graphics.blitSprite(RenderPipelines.GUI_TEXTURED, Gui.getMobEffectSprite(effect), x + 3, y + 3, 18, 18, ARGB.white(alpha)); } } public static Identifier getMobEffectSprite(Holder effect) { return effect.unwrapKey().map(ResourceKey::identifier).map(id -> id.withPrefix("mob_effect/")).orElseGet(MissingTextureAtlasSprite::getLocation); } private void renderHotbarAndDecorations(GuiGraphics graphics, DeltaTracker deltaTracker) { if (this.minecraft.gameMode.getPlayerMode() == GameType.SPECTATOR) { this.spectatorGui.renderHotbar(graphics); } else { this.renderItemHotbar(graphics, deltaTracker); } if (this.minecraft.gameMode.canHurtPlayer()) { this.renderPlayerHealth(graphics); } this.renderVehicleHealth(graphics); ContextualInfo nextContextualInfo = this.nextContextualInfoState(); if (nextContextualInfo != this.contextualInfoBar.getKey()) { this.contextualInfoBar = Pair.of((Object)((Object)nextContextualInfo), (Object)this.contextualInfoBarRenderers.get((Object)nextContextualInfo).get()); } ((ContextualBarRenderer)this.contextualInfoBar.getValue()).renderBackground(graphics, deltaTracker); if (this.minecraft.gameMode.hasExperience() && this.minecraft.player.experienceLevel > 0) { ContextualBarRenderer.renderExperienceLevel(graphics, this.minecraft.font, this.minecraft.player.experienceLevel); } ((ContextualBarRenderer)this.contextualInfoBar.getValue()).render(graphics, deltaTracker); if (this.minecraft.gameMode.getPlayerMode() != GameType.SPECTATOR) { this.renderSelectedItemName(graphics); } else if (this.minecraft.player.isSpectator()) { this.spectatorGui.renderAction(graphics); } } private void renderItemHotbar(GuiGraphics graphics, DeltaTracker deltaTracker) { float attackStrengthScale; Player player = this.getCameraPlayer(); if (player == null) { return; } ItemStack offhand = player.getOffhandItem(); HumanoidArm offhandArm = player.getMainArm().getOpposite(); int screenCenter = graphics.guiWidth() / 2; int hotbarWidth = 182; int halfHotbar = 91; graphics.blitSprite(RenderPipelines.GUI_TEXTURED, HOTBAR_SPRITE, screenCenter - 91, graphics.guiHeight() - 22, 182, 22); graphics.blitSprite(RenderPipelines.GUI_TEXTURED, HOTBAR_SELECTION_SPRITE, screenCenter - 91 - 1 + player.getInventory().getSelectedSlot() * 20, graphics.guiHeight() - 22 - 1, 24, 23); if (!offhand.isEmpty()) { if (offhandArm == HumanoidArm.LEFT) { graphics.blitSprite(RenderPipelines.GUI_TEXTURED, HOTBAR_OFFHAND_LEFT_SPRITE, screenCenter - 91 - 29, graphics.guiHeight() - 23, 29, 24); } else { graphics.blitSprite(RenderPipelines.GUI_TEXTURED, HOTBAR_OFFHAND_RIGHT_SPRITE, screenCenter + 91, graphics.guiHeight() - 23, 29, 24); } } int seed = 1; for (int i = 0; i < 9; ++i) { int x = screenCenter - 90 + i * 20 + 2; int y = graphics.guiHeight() - 16 - 3; this.renderSlot(graphics, x, y, deltaTracker, player, player.getInventory().getItem(i), seed++); } if (!offhand.isEmpty()) { int y = graphics.guiHeight() - 16 - 3; if (offhandArm == HumanoidArm.LEFT) { this.renderSlot(graphics, screenCenter - 91 - 26, y, deltaTracker, player, offhand, seed++); } else { this.renderSlot(graphics, screenCenter + 91 + 10, y, deltaTracker, player, offhand, seed++); } } if (this.minecraft.options.attackIndicator().get() == AttackIndicatorStatus.HOTBAR && (attackStrengthScale = this.minecraft.player.getAttackStrengthScale(0.0f)) < 1.0f) { int y = graphics.guiHeight() - 20; int x = screenCenter + 91 + 6; if (offhandArm == HumanoidArm.RIGHT) { x = screenCenter - 91 - 22; } int progress = (int)(attackStrengthScale * 19.0f); graphics.blitSprite(RenderPipelines.GUI_TEXTURED, HOTBAR_ATTACK_INDICATOR_BACKGROUND_SPRITE, x, y, 18, 18); graphics.blitSprite(RenderPipelines.GUI_TEXTURED, HOTBAR_ATTACK_INDICATOR_PROGRESS_SPRITE, 18, 18, 0, 18 - progress, x, y + 18 - progress, 18, progress); } } private void renderSelectedItemName(GuiGraphics graphics) { Profiler.get().push("selectedItemName"); if (this.toolHighlightTimer > 0 && !this.lastToolHighlight.isEmpty()) { int alpha; MutableComponent str = Component.empty().append(this.lastToolHighlight.getHoverName()).withStyle(this.lastToolHighlight.getRarity().color()); if (this.lastToolHighlight.has(DataComponents.CUSTOM_NAME)) { str.withStyle(ChatFormatting.ITALIC); } int strWidth = this.getFont().width(str); int x = (graphics.guiWidth() - strWidth) / 2; int y = graphics.guiHeight() - 59; if (!this.minecraft.gameMode.canHurtPlayer()) { y += 14; } if ((alpha = (int)((float)this.toolHighlightTimer * 256.0f / 10.0f)) > 255) { alpha = 255; } if (alpha > 0) { graphics.drawStringWithBackdrop(this.getFont(), str, x, y, strWidth, ARGB.white(alpha)); } } Profiler.get().pop(); } private void renderDemoOverlay(GuiGraphics graphics, DeltaTracker deltaTracker) { if (!this.minecraft.isDemo()) { return; } Profiler.get().push("demo"); graphics.nextStratum(); Component msg = this.minecraft.level.getGameTime() >= 120500L ? DEMO_EXPIRED_TEXT : Component.translatable("demo.remainingTime", StringUtil.formatTickDuration((int)(120500L - this.minecraft.level.getGameTime()), this.minecraft.level.tickRateManager().tickrate())); int width = this.getFont().width(msg); int textX = graphics.guiWidth() - width - 10; int textY = 5; graphics.drawStringWithBackdrop(this.getFont(), msg, textX, 5, width, -1); Profiler.get().pop(); } private void displayScoreboardSidebar(GuiGraphics graphics, Objective objective) { int objectiveDisplayNameWidth; Scoreboard scoreboard = objective.getScoreboard(); NumberFormat objectiveScoreFormat = objective.numberFormatOrDefault(StyledFormat.SIDEBAR_DEFAULT); record DisplayEntry(Component name, Component score, int scoreWidth) { } DisplayEntry[] entriesToDisplay = (DisplayEntry[])scoreboard.listPlayerScores(objective).stream().filter(input -> !input.isHidden()).sorted(SCORE_DISPLAY_ORDER).limit(15L).map(score -> { PlayerTeam team = scoreboard.getPlayersTeam(score.owner()); Component ownerName = score.ownerName(); MutableComponent name = PlayerTeam.formatNameForTeam(team, ownerName); MutableComponent scoreString = score.formatValue(objectiveScoreFormat); int scoreWidth = this.getFont().width(scoreString); return new DisplayEntry(name, scoreString, scoreWidth); }).toArray(x$0 -> new DisplayEntry[x$0]); Component objectiveDisplayName = objective.getDisplayName(); int biggestWidth = objectiveDisplayNameWidth = this.getFont().width(objectiveDisplayName); int spacerWidth = this.getFont().width(SPACER); for (DisplayEntry entry : entriesToDisplay) { biggestWidth = Math.max(biggestWidth, this.getFont().width(entry.name) + (entry.scoreWidth > 0 ? spacerWidth + entry.scoreWidth : 0)); } int width = biggestWidth; int entriesCount = entriesToDisplay.length; int height = entriesCount * this.getFont().lineHeight; int bottom = graphics.guiHeight() / 2 + height / 3; int rightPadding = 3; int left = graphics.guiWidth() - width - 3; int right = graphics.guiWidth() - 3 + 2; int backgroundColor = this.minecraft.options.getBackgroundColor(0.3f); int headerBackgroundColor = this.minecraft.options.getBackgroundColor(0.4f); int headerY = bottom - entriesCount * this.getFont().lineHeight; graphics.fill(left - 2, headerY - this.getFont().lineHeight - 1, right, headerY - 1, headerBackgroundColor); graphics.fill(left - 2, headerY - 1, right, bottom, backgroundColor); graphics.drawString(this.getFont(), objectiveDisplayName, left + width / 2 - objectiveDisplayNameWidth / 2, headerY - this.getFont().lineHeight, -1, false); for (int i = 0; i < entriesCount; ++i) { DisplayEntry e = entriesToDisplay[i]; int y = bottom - (entriesCount - i) * this.getFont().lineHeight; graphics.drawString(this.getFont(), e.name, left, y, -1, false); graphics.drawString(this.getFont(), e.score, right - e.scoreWidth, y, -1, false); } } private @Nullable Player getCameraPlayer() { Player player; Entity entity = this.minecraft.getCameraEntity(); return entity instanceof Player ? (player = (Player)entity) : null; } private @Nullable LivingEntity getPlayerVehicleWithHealth() { Player player = this.getCameraPlayer(); if (player != null) { Entity vehicle = player.getVehicle(); if (vehicle == null) { return null; } if (vehicle instanceof LivingEntity) { return (LivingEntity)vehicle; } } return null; } private int getVehicleMaxHearts(@Nullable LivingEntity vehicle) { if (vehicle == null || !vehicle.showVehicleHealth()) { return 0; } float maxVehicleHealth = vehicle.getMaxHealth(); int hearts = (int)(maxVehicleHealth + 0.5f) / 2; if (hearts > 30) { hearts = 30; } return hearts; } private int getVisibleVehicleHeartRows(int hearts) { return (int)Math.ceil((double)hearts / 10.0); } private void renderPlayerHealth(GuiGraphics graphics) { Player player = this.getCameraPlayer(); if (player == null) { return; } int currentHealth = Mth.ceil(player.getHealth()); boolean blink = this.healthBlinkTime > (long)this.tickCount && (this.healthBlinkTime - (long)this.tickCount) / 3L % 2L == 1L; long timeMillis = Util.getMillis(); if (currentHealth < this.lastHealth && player.invulnerableTime > 0) { this.lastHealthTime = timeMillis; this.healthBlinkTime = this.tickCount + 20; } else if (currentHealth > this.lastHealth && player.invulnerableTime > 0) { this.lastHealthTime = timeMillis; this.healthBlinkTime = this.tickCount + 10; } if (timeMillis - this.lastHealthTime > 1000L) { this.displayHealth = currentHealth; this.lastHealthTime = timeMillis; } this.lastHealth = currentHealth; int oldHealth = this.displayHealth; this.random.setSeed(this.tickCount * 312871); int xLeft = graphics.guiWidth() / 2 - 91; int xRight = graphics.guiWidth() / 2 + 91; int yLineBase = graphics.guiHeight() - 39; float maxHealth = Math.max((float)player.getAttributeValue(Attributes.MAX_HEALTH), (float)Math.max(oldHealth, currentHealth)); int totalAbsorption = Mth.ceil(player.getAbsorptionAmount()); int numHealthRows = Mth.ceil((maxHealth + (float)totalAbsorption) / 2.0f / 10.0f); int healthRowHeight = Math.max(10 - (numHealthRows - 2), 3); int yLineAir = yLineBase - 10; int heartOffsetIndex = -1; if (player.hasEffect(MobEffects.REGENERATION)) { heartOffsetIndex = this.tickCount % Mth.ceil(maxHealth + 5.0f); } Profiler.get().push("armor"); Gui.renderArmor(graphics, player, yLineBase, numHealthRows, healthRowHeight, xLeft); Profiler.get().popPush("health"); this.renderHearts(graphics, player, xLeft, yLineBase, healthRowHeight, heartOffsetIndex, maxHealth, currentHealth, oldHealth, totalAbsorption, blink); LivingEntity vehicleWithHearts = this.getPlayerVehicleWithHealth(); int vehicleHearts = this.getVehicleMaxHearts(vehicleWithHearts); if (vehicleHearts == 0) { Profiler.get().popPush("food"); this.renderFood(graphics, player, yLineBase, xRight); yLineAir -= 10; } Profiler.get().popPush("air"); this.renderAirBubbles(graphics, player, vehicleHearts, yLineAir, xRight); Profiler.get().pop(); } private static void renderArmor(GuiGraphics graphics, Player player, int yLineBase, int numHealthRows, int healthRowHeight, int xLeft) { int armor = player.getArmorValue(); if (armor <= 0) { return; } int yLineArmor = yLineBase - (numHealthRows - 1) * healthRowHeight - 10; for (int i = 0; i < 10; ++i) { int xo = xLeft + i * 8; if (i * 2 + 1 < armor) { graphics.blitSprite(RenderPipelines.GUI_TEXTURED, ARMOR_FULL_SPRITE, xo, yLineArmor, 9, 9); } if (i * 2 + 1 == armor) { graphics.blitSprite(RenderPipelines.GUI_TEXTURED, ARMOR_HALF_SPRITE, xo, yLineArmor, 9, 9); } if (i * 2 + 1 <= armor) continue; graphics.blitSprite(RenderPipelines.GUI_TEXTURED, ARMOR_EMPTY_SPRITE, xo, yLineArmor, 9, 9); } } private void renderHearts(GuiGraphics graphics, Player player, int xLeft, int yLineBase, int healthRowHeight, int heartOffsetIndex, float maxHealth, int currentHealth, int oldHealth, int absorption, boolean blink) { HeartType type = HeartType.forPlayer(player); boolean isHardcore = player.level().getLevelData().isHardcore(); int healthContainerCount = Mth.ceil((double)maxHealth / 2.0); int absorptionContainerCount = Mth.ceil((double)absorption / 2.0); int maxHealthHalvesCount = healthContainerCount * 2; for (int containerIndex = healthContainerCount + absorptionContainerCount - 1; containerIndex >= 0; --containerIndex) { boolean halfHeart; int absorptionHalves; boolean isAbsorptionHeart; int row = containerIndex / 10; int column = containerIndex % 10; int xo = xLeft + column * 8; int yo = yLineBase - row * healthRowHeight; if (currentHealth + absorption <= 4) { yo += this.random.nextInt(2); } if (containerIndex < healthContainerCount && containerIndex == heartOffsetIndex) { yo -= 2; } this.renderHeart(graphics, HeartType.CONTAINER, xo, yo, isHardcore, blink, false); int halves = containerIndex * 2; boolean bl = isAbsorptionHeart = containerIndex >= healthContainerCount; if (isAbsorptionHeart && (absorptionHalves = halves - maxHealthHalvesCount) < absorption) { boolean halfHeart2 = absorptionHalves + 1 == absorption; this.renderHeart(graphics, type == HeartType.WITHERED ? type : HeartType.ABSORBING, xo, yo, isHardcore, false, halfHeart2); } if (blink && halves < oldHealth) { halfHeart = halves + 1 == oldHealth; this.renderHeart(graphics, type, xo, yo, isHardcore, true, halfHeart); } if (halves >= currentHealth) continue; halfHeart = halves + 1 == currentHealth; this.renderHeart(graphics, type, xo, yo, isHardcore, false, halfHeart); } } private void renderHeart(GuiGraphics graphics, HeartType type, int xo, int yo, boolean isHardcore, boolean blinks, boolean half) { graphics.blitSprite(RenderPipelines.GUI_TEXTURED, type.getSprite(isHardcore, half, blinks), xo, yo, 9, 9); } private void renderAirBubbles(GuiGraphics graphics, Player player, int vehicleHearts, int yLineAir, int xRight) { int maxAirSupplyTicks = player.getMaxAirSupply(); int currentAirSupplyTicks = Math.clamp((long)player.getAirSupply(), 0, maxAirSupplyTicks); boolean isUnderWater = player.isEyeInFluid(FluidTags.WATER); if (isUnderWater || currentAirSupplyTicks < maxAirSupplyTicks) { boolean isPoppingBubble; yLineAir = this.getAirBubbleYLine(vehicleHearts, yLineAir); int fullAirBubbles = Gui.getCurrentAirSupplyBubble(currentAirSupplyTicks, maxAirSupplyTicks, -2); int poppingAirBubblePosition = Gui.getCurrentAirSupplyBubble(currentAirSupplyTicks, maxAirSupplyTicks, 0); int emptyAirBubbles = 10 - Gui.getCurrentAirSupplyBubble(currentAirSupplyTicks, maxAirSupplyTicks, Gui.getEmptyBubbleDelayDuration(currentAirSupplyTicks, isUnderWater)); boolean bl = isPoppingBubble = fullAirBubbles != poppingAirBubblePosition; if (!isUnderWater) { this.lastBubblePopSoundPlayed = 0; } for (int airBubble = 1; airBubble <= 10; ++airBubble) { int airBubbleXPos = xRight - (airBubble - 1) * 8 - 9; if (airBubble <= fullAirBubbles) { graphics.blitSprite(RenderPipelines.GUI_TEXTURED, AIR_SPRITE, airBubbleXPos, yLineAir, 9, 9); continue; } if (isPoppingBubble && airBubble == poppingAirBubblePosition && isUnderWater) { graphics.blitSprite(RenderPipelines.GUI_TEXTURED, AIR_POPPING_SPRITE, airBubbleXPos, yLineAir, 9, 9); this.playAirBubblePoppedSound(airBubble, player, emptyAirBubbles); continue; } if (airBubble <= 10 - emptyAirBubbles) continue; int wobbleYOffset = emptyAirBubbles == 10 && this.tickCount % 2 == 0 ? this.random.nextInt(2) : 0; graphics.blitSprite(RenderPipelines.GUI_TEXTURED, AIR_EMPTY_SPRITE, airBubbleXPos, yLineAir + wobbleYOffset, 9, 9); } } } private int getAirBubbleYLine(int vehicleHearts, int yLineAir) { int rowOffset = this.getVisibleVehicleHeartRows(vehicleHearts) - 1; return yLineAir -= rowOffset * 10; } private static int getCurrentAirSupplyBubble(int currentAirSupplyTicks, int maxAirSupplyTicks, int tickOffset) { return Mth.ceil((float)((currentAirSupplyTicks + tickOffset) * 10) / (float)maxAirSupplyTicks); } private static int getEmptyBubbleDelayDuration(int currentAirSupplyTicks, boolean isUnderWater) { return currentAirSupplyTicks == 0 || !isUnderWater ? 0 : 1; } private void playAirBubblePoppedSound(int bubble, Player player, int emptyAirBubbles) { if (this.lastBubblePopSoundPlayed != bubble) { float soundVolume = 0.5f + 0.1f * (float)Math.max(0, emptyAirBubbles - 3 + 1); float soundPitch = 1.0f + 0.1f * (float)Math.max(0, emptyAirBubbles - 5 + 1); player.playSound(SoundEvents.BUBBLE_POP, soundVolume, soundPitch); this.lastBubblePopSoundPlayed = bubble; } } private void renderFood(GuiGraphics graphics, Player player, int yLineBase, int xRight) { FoodData foodData = player.getFoodData(); int food = foodData.getFoodLevel(); for (int i = 0; i < 10; ++i) { Identifier full; Identifier half; Identifier empty; int yo = yLineBase; if (player.hasEffect(MobEffects.HUNGER)) { empty = FOOD_EMPTY_HUNGER_SPRITE; half = FOOD_HALF_HUNGER_SPRITE; full = FOOD_FULL_HUNGER_SPRITE; } else { empty = FOOD_EMPTY_SPRITE; half = FOOD_HALF_SPRITE; full = FOOD_FULL_SPRITE; } if (player.getFoodData().getSaturationLevel() <= 0.0f && this.tickCount % (food * 3 + 1) == 0) { yo += this.random.nextInt(3) - 1; } int xo = xRight - i * 8 - 9; graphics.blitSprite(RenderPipelines.GUI_TEXTURED, empty, xo, yo, 9, 9); if (i * 2 + 1 < food) { graphics.blitSprite(RenderPipelines.GUI_TEXTURED, full, xo, yo, 9, 9); } if (i * 2 + 1 != food) continue; graphics.blitSprite(RenderPipelines.GUI_TEXTURED, half, xo, yo, 9, 9); } } private void renderVehicleHealth(GuiGraphics graphics) { LivingEntity vehicleWithHearts = this.getPlayerVehicleWithHealth(); if (vehicleWithHearts == null) { return; } int hearts = this.getVehicleMaxHearts(vehicleWithHearts); if (hearts == 0) { return; } int currentHealth = (int)Math.ceil(vehicleWithHearts.getHealth()); Profiler.get().popPush("mountHealth"); int yLine1 = graphics.guiHeight() - 39; int xRight = graphics.guiWidth() / 2 + 91; int yo = yLine1; int baseHealth = 0; while (hearts > 0) { int rowHearts = Math.min(hearts, 10); hearts -= rowHearts; for (int i = 0; i < rowHearts; ++i) { int xo = xRight - i * 8 - 9; graphics.blitSprite(RenderPipelines.GUI_TEXTURED, HEART_VEHICLE_CONTAINER_SPRITE, xo, yo, 9, 9); if (i * 2 + 1 + baseHealth < currentHealth) { graphics.blitSprite(RenderPipelines.GUI_TEXTURED, HEART_VEHICLE_FULL_SPRITE, xo, yo, 9, 9); } if (i * 2 + 1 + baseHealth != currentHealth) continue; graphics.blitSprite(RenderPipelines.GUI_TEXTURED, HEART_VEHICLE_HALF_SPRITE, xo, yo, 9, 9); } yo -= 10; baseHealth += 20; } } private void renderTextureOverlay(GuiGraphics graphics, Identifier texture, float alpha) { int color = ARGB.white(alpha); graphics.blit(RenderPipelines.GUI_TEXTURED, texture, 0, 0, 0.0f, 0.0f, graphics.guiWidth(), graphics.guiHeight(), graphics.guiWidth(), graphics.guiHeight(), color); } private void renderSpyglassOverlay(GuiGraphics graphics, float scale) { float srcWidth; float srcHeight = srcWidth = (float)Math.min(graphics.guiWidth(), graphics.guiHeight()); float ratio = Math.min((float)graphics.guiWidth() / srcWidth, (float)graphics.guiHeight() / srcHeight) * scale; int width = Mth.floor(srcWidth * ratio); int height = Mth.floor(srcHeight * ratio); int left = (graphics.guiWidth() - width) / 2; int top = (graphics.guiHeight() - height) / 2; int right = left + width; int bottom = top + height; graphics.blit(RenderPipelines.GUI_TEXTURED, SPYGLASS_SCOPE_LOCATION, left, top, 0.0f, 0.0f, width, height, width, height); graphics.fill(RenderPipelines.GUI, 0, bottom, graphics.guiWidth(), graphics.guiHeight(), -16777216); graphics.fill(RenderPipelines.GUI, 0, 0, graphics.guiWidth(), top, -16777216); graphics.fill(RenderPipelines.GUI, 0, top, left, bottom, -16777216); graphics.fill(RenderPipelines.GUI, right, top, graphics.guiWidth(), bottom, -16777216); } private void updateVignetteBrightness(Entity camera) { BlockPos blockPos = BlockPos.containing(camera.getX(), camera.getEyeY(), camera.getZ()); float levelBrightness = LightTexture.getBrightness(camera.level().dimensionType(), camera.level().getMaxLocalRawBrightness(blockPos)); float brightness = Mth.clamp(1.0f - levelBrightness, 0.0f, 1.0f); this.vignetteBrightness += (brightness - this.vignetteBrightness) * 0.01f; } private void renderVignette(GuiGraphics graphics, @Nullable Entity camera) { int color; WorldBorder worldBorder = this.minecraft.level.getWorldBorder(); float borderWarningStrength = 0.0f; if (camera != null) { float distToBorder = (float)worldBorder.getDistanceToBorder(camera); double movingBlocksThreshold = Math.min(worldBorder.getLerpSpeed() * (double)worldBorder.getWarningTime(), Math.abs(worldBorder.getLerpTarget() - worldBorder.getSize())); double warningDistance = Math.max((double)worldBorder.getWarningBlocks(), movingBlocksThreshold); if ((double)distToBorder < warningDistance) { borderWarningStrength = 1.0f - (float)((double)distToBorder / warningDistance); } } if (borderWarningStrength > 0.0f) { borderWarningStrength = Mth.clamp(borderWarningStrength, 0.0f, 1.0f); color = ARGB.colorFromFloat(1.0f, 0.0f, borderWarningStrength, borderWarningStrength); } else { float brightness = this.vignetteBrightness; brightness = Mth.clamp(brightness, 0.0f, 1.0f); color = ARGB.colorFromFloat(1.0f, brightness, brightness, brightness); } graphics.blit(RenderPipelines.VIGNETTE, VIGNETTE_LOCATION, 0, 0, 0.0f, 0.0f, graphics.guiWidth(), graphics.guiHeight(), graphics.guiWidth(), graphics.guiHeight(), color); } private void renderPortalOverlay(GuiGraphics graphics, float alpha) { if (alpha < 1.0f) { alpha *= alpha; alpha *= alpha; alpha = alpha * 0.8f + 0.2f; } int color = ARGB.white(alpha); TextureAtlasSprite slot = this.minecraft.getBlockRenderer().getBlockModelShaper().getParticleIcon(Blocks.NETHER_PORTAL.defaultBlockState()); graphics.blitSprite(RenderPipelines.GUI_TEXTURED, slot, 0, 0, graphics.guiWidth(), graphics.guiHeight(), color); } private void renderConfusionOverlay(GuiGraphics graphics, float strength) { int screenWidth = graphics.guiWidth(); int screenHeight = graphics.guiHeight(); graphics.pose().pushMatrix(); float size = Mth.lerp(strength, 2.0f, 1.0f); graphics.pose().translate((float)screenWidth / 2.0f, (float)screenHeight / 2.0f); graphics.pose().scale(size, size); graphics.pose().translate((float)(-screenWidth) / 2.0f, (float)(-screenHeight) / 2.0f); float red = 0.2f * strength; float green = 0.4f * strength; float blue = 0.2f * strength; graphics.blit(RenderPipelines.GUI_NAUSEA_OVERLAY, NAUSEA_LOCATION, 0, 0, 0.0f, 0.0f, screenWidth, screenHeight, screenWidth, screenHeight, ARGB.colorFromFloat(1.0f, red, green, blue)); graphics.pose().popMatrix(); } private void renderSlot(GuiGraphics graphics, int x, int y, DeltaTracker deltaTracker, Player player, ItemStack itemStack, int seed) { if (itemStack.isEmpty()) { return; } float pop = (float)itemStack.getPopTime() - deltaTracker.getGameTimeDeltaPartialTick(false); if (pop > 0.0f) { float squeeze = 1.0f + pop / 5.0f; graphics.pose().pushMatrix(); graphics.pose().translate((float)(x + 8), (float)(y + 12)); graphics.pose().scale(1.0f / squeeze, (squeeze + 1.0f) / 2.0f); graphics.pose().translate((float)(-(x + 8)), (float)(-(y + 12))); } graphics.renderItem(player, itemStack, x, y, seed); if (pop > 0.0f) { graphics.pose().popMatrix(); } graphics.renderItemDecorations(this.minecraft.font, itemStack, x, y); } public void tick(boolean pause) { this.tickAutosaveIndicator(); if (!pause) { this.tick(); } } private void tick() { if (this.overlayMessageTime > 0) { --this.overlayMessageTime; } if (this.titleTime > 0) { --this.titleTime; if (this.titleTime <= 0) { this.title = null; this.subtitle = null; } } ++this.tickCount; Entity camera = this.minecraft.getCameraEntity(); if (camera != null) { this.updateVignetteBrightness(camera); } if (this.minecraft.player != null) { ItemStack selected = this.minecraft.player.getInventory().getSelectedItem(); if (selected.isEmpty()) { this.toolHighlightTimer = 0; } else if (this.lastToolHighlight.isEmpty() || !selected.is(this.lastToolHighlight.getItem()) || !selected.getHoverName().equals(this.lastToolHighlight.getHoverName())) { this.toolHighlightTimer = (int)(40.0 * this.minecraft.options.notificationDisplayTime().get()); } else if (this.toolHighlightTimer > 0) { --this.toolHighlightTimer; } this.lastToolHighlight = selected; } this.chat.tick(); } private void tickAutosaveIndicator() { IntegratedServer server = this.minecraft.getSingleplayerServer(); boolean isAutosaving = server != null && server.isCurrentlySaving(); this.lastAutosaveIndicatorValue = this.autosaveIndicatorValue; this.autosaveIndicatorValue = Mth.lerp(0.2f, this.autosaveIndicatorValue, isAutosaving ? 1.0f : 0.0f); } public void setNowPlaying(Component string) { MutableComponent message = Component.translatable("record.nowPlaying", string); this.setOverlayMessage(message, true); this.minecraft.getNarrator().saySystemNow(message); } public void setOverlayMessage(Component string, boolean animate) { this.setChatDisabledByPlayerShown(false); this.overlayMessageString = string; this.overlayMessageTime = 60; this.animateOverlayMessageColor = animate; } public void setChatDisabledByPlayerShown(boolean chatDisabledByPlayerShown) { this.chatDisabledByPlayerShown = chatDisabledByPlayerShown; } public boolean isShowingChatDisabledByPlayer() { return this.chatDisabledByPlayerShown && this.overlayMessageTime > 0; } public void setTimes(int fadeInTime, int stayTime, int fadeOutTime) { if (fadeInTime >= 0) { this.titleFadeInTime = fadeInTime; } if (stayTime >= 0) { this.titleStayTime = stayTime; } if (fadeOutTime >= 0) { this.titleFadeOutTime = fadeOutTime; } if (this.titleTime > 0) { this.titleTime = this.titleFadeInTime + this.titleStayTime + this.titleFadeOutTime; } } public void setSubtitle(Component subtitle) { this.subtitle = subtitle; } public void setTitle(Component title) { this.title = title; this.titleTime = this.titleFadeInTime + this.titleStayTime + this.titleFadeOutTime; } public void clearTitles() { this.title = null; this.subtitle = null; this.titleTime = 0; } public ChatComponent getChat() { return this.chat; } public int getGuiTicks() { return this.tickCount; } public Font getFont() { return this.minecraft.font; } public SpectatorGui getSpectatorGui() { return this.spectatorGui; } public PlayerTabOverlay getTabList() { return this.tabList; } public void onDisconnected() { this.tabList.reset(); this.bossOverlay.reset(); this.minecraft.getToastManager().clear(); this.debugOverlay.reset(); this.chat.clearMessages(true); this.clearTitles(); this.resetTitleTimes(); } public BossHealthOverlay getBossOverlay() { return this.bossOverlay; } public DebugScreenOverlay getDebugOverlay() { return this.debugOverlay; } public void clearCache() { this.debugOverlay.clearChunkCache(); } public void renderSavingIndicator(GuiGraphics graphics, DeltaTracker deltaTracker) { int alpha; if (this.minecraft.options.showAutosaveIndicator().get().booleanValue() && (this.autosaveIndicatorValue > 0.0f || this.lastAutosaveIndicatorValue > 0.0f) && (alpha = Mth.floor(255.0f * Mth.clamp(Mth.lerp(deltaTracker.getRealtimeDeltaTicks(), this.lastAutosaveIndicatorValue, this.autosaveIndicatorValue), 0.0f, 1.0f))) > 0) { Font font = this.getFont(); int width = font.width(SAVING_TEXT); int color = ARGB.color(alpha, -1); int textX = graphics.guiWidth() - width - 5; int textY = graphics.guiHeight() - font.lineHeight - 5; graphics.nextStratum(); graphics.drawStringWithBackdrop(font, SAVING_TEXT, textX, textY, width, color); } } private boolean willPrioritizeExperienceInfo() { return this.minecraft.player.experienceDisplayStartTick + 100 > this.minecraft.player.tickCount; } private boolean willPrioritizeJumpInfo() { return this.minecraft.player.getJumpRidingScale() > 0.0f || Optionull.mapOrDefault(this.minecraft.player.jumpableVehicle(), PlayerRideableJumping::getJumpCooldown, 0) > 0; } private ContextualInfo nextContextualInfoState() { boolean canShowLocatorInfo = this.minecraft.player.connection.getWaypointManager().hasWaypoints(); boolean canShowVehicleJumpInfo = this.minecraft.player.jumpableVehicle() != null; boolean canShowExperienceInfo = this.minecraft.gameMode.hasExperience(); if (canShowLocatorInfo) { if (canShowVehicleJumpInfo && this.willPrioritizeJumpInfo()) { return ContextualInfo.JUMPABLE_VEHICLE; } if (canShowExperienceInfo && this.willPrioritizeExperienceInfo()) { return ContextualInfo.EXPERIENCE; } return ContextualInfo.LOCATOR; } if (canShowVehicleJumpInfo) { return ContextualInfo.JUMPABLE_VEHICLE; } if (canShowExperienceInfo) { return ContextualInfo.EXPERIENCE; } return ContextualInfo.EMPTY; } static enum ContextualInfo { EMPTY, EXPERIENCE, LOCATOR, JUMPABLE_VEHICLE; } private static enum HeartType { CONTAINER(Identifier.withDefaultNamespace("hud/heart/container"), Identifier.withDefaultNamespace("hud/heart/container_blinking"), Identifier.withDefaultNamespace("hud/heart/container"), Identifier.withDefaultNamespace("hud/heart/container_blinking"), Identifier.withDefaultNamespace("hud/heart/container_hardcore"), Identifier.withDefaultNamespace("hud/heart/container_hardcore_blinking"), Identifier.withDefaultNamespace("hud/heart/container_hardcore"), Identifier.withDefaultNamespace("hud/heart/container_hardcore_blinking")), NORMAL(Identifier.withDefaultNamespace("hud/heart/full"), Identifier.withDefaultNamespace("hud/heart/full_blinking"), Identifier.withDefaultNamespace("hud/heart/half"), Identifier.withDefaultNamespace("hud/heart/half_blinking"), Identifier.withDefaultNamespace("hud/heart/hardcore_full"), Identifier.withDefaultNamespace("hud/heart/hardcore_full_blinking"), Identifier.withDefaultNamespace("hud/heart/hardcore_half"), Identifier.withDefaultNamespace("hud/heart/hardcore_half_blinking")), POISIONED(Identifier.withDefaultNamespace("hud/heart/poisoned_full"), Identifier.withDefaultNamespace("hud/heart/poisoned_full_blinking"), Identifier.withDefaultNamespace("hud/heart/poisoned_half"), Identifier.withDefaultNamespace("hud/heart/poisoned_half_blinking"), Identifier.withDefaultNamespace("hud/heart/poisoned_hardcore_full"), Identifier.withDefaultNamespace("hud/heart/poisoned_hardcore_full_blinking"), Identifier.withDefaultNamespace("hud/heart/poisoned_hardcore_half"), Identifier.withDefaultNamespace("hud/heart/poisoned_hardcore_half_blinking")), WITHERED(Identifier.withDefaultNamespace("hud/heart/withered_full"), Identifier.withDefaultNamespace("hud/heart/withered_full_blinking"), Identifier.withDefaultNamespace("hud/heart/withered_half"), Identifier.withDefaultNamespace("hud/heart/withered_half_blinking"), Identifier.withDefaultNamespace("hud/heart/withered_hardcore_full"), Identifier.withDefaultNamespace("hud/heart/withered_hardcore_full_blinking"), Identifier.withDefaultNamespace("hud/heart/withered_hardcore_half"), Identifier.withDefaultNamespace("hud/heart/withered_hardcore_half_blinking")), ABSORBING(Identifier.withDefaultNamespace("hud/heart/absorbing_full"), Identifier.withDefaultNamespace("hud/heart/absorbing_full_blinking"), Identifier.withDefaultNamespace("hud/heart/absorbing_half"), Identifier.withDefaultNamespace("hud/heart/absorbing_half_blinking"), Identifier.withDefaultNamespace("hud/heart/absorbing_hardcore_full"), Identifier.withDefaultNamespace("hud/heart/absorbing_hardcore_full_blinking"), Identifier.withDefaultNamespace("hud/heart/absorbing_hardcore_half"), Identifier.withDefaultNamespace("hud/heart/absorbing_hardcore_half_blinking")), FROZEN(Identifier.withDefaultNamespace("hud/heart/frozen_full"), Identifier.withDefaultNamespace("hud/heart/frozen_full_blinking"), Identifier.withDefaultNamespace("hud/heart/frozen_half"), Identifier.withDefaultNamespace("hud/heart/frozen_half_blinking"), Identifier.withDefaultNamespace("hud/heart/frozen_hardcore_full"), Identifier.withDefaultNamespace("hud/heart/frozen_hardcore_full_blinking"), Identifier.withDefaultNamespace("hud/heart/frozen_hardcore_half"), Identifier.withDefaultNamespace("hud/heart/frozen_hardcore_half_blinking")); private final Identifier full; private final Identifier fullBlinking; private final Identifier half; private final Identifier halfBlinking; private final Identifier hardcoreFull; private final Identifier hardcoreFullBlinking; private final Identifier hardcoreHalf; private final Identifier hardcoreHalfBlinking; private HeartType(Identifier full, Identifier fullBlinking, Identifier half, Identifier halfBlinking, Identifier hardcoreFull, Identifier hardcoreFullBlinking, Identifier hardcoreHalf, Identifier hardcoreHalfBlinking) { this.full = full; this.fullBlinking = fullBlinking; this.half = half; this.halfBlinking = halfBlinking; this.hardcoreFull = hardcoreFull; this.hardcoreFullBlinking = hardcoreFullBlinking; this.hardcoreHalf = hardcoreHalf; this.hardcoreHalfBlinking = hardcoreHalfBlinking; } public Identifier getSprite(boolean isHardcore, boolean isHalf, boolean isBlink) { if (!isHardcore) { if (isHalf) { return isBlink ? this.halfBlinking : this.half; } return isBlink ? this.fullBlinking : this.full; } if (isHalf) { return isBlink ? this.hardcoreHalfBlinking : this.hardcoreHalf; } return isBlink ? this.hardcoreFullBlinking : this.hardcoreFull; } private static HeartType forPlayer(Player player) { HeartType type = player.hasEffect(MobEffects.POISON) ? POISIONED : (player.hasEffect(MobEffects.WITHER) ? WITHERED : (player.isFullyFrozen() ? FROZEN : NORMAL)); return type; } } public static interface RenderFunction { public void render(GuiGraphics var1, DeltaTracker var2); } }