1237 lines
64 KiB
Java
1237 lines
64 KiB
Java
/*
|
|
* 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<PlayerScoreEntry> 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<ContextualInfo, ContextualBarRenderer> contextualInfoBar = Pair.of((Object)((Object)ContextualInfo.EMPTY), (Object)ContextualBarRenderer.EMPTY);
|
|
private final Map<ContextualInfo, Supplier<ContextualBarRenderer>> 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<MobEffectInstance> 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<MobEffect> 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<MobEffect> 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);
|
|
}
|
|
}
|
|
|