642 lines
22 KiB
Java
642 lines
22 KiB
Java
package net.minecraft.client.gui.screens;
|
|
|
|
import com.google.common.annotations.VisibleForTesting;
|
|
import com.google.common.collect.Lists;
|
|
import com.mojang.blaze3d.platform.InputConstants;
|
|
import com.mojang.logging.LogUtils;
|
|
import java.net.URI;
|
|
import java.nio.file.Path;
|
|
import java.util.Comparator;
|
|
import java.util.List;
|
|
import java.util.concurrent.Executor;
|
|
import java.util.concurrent.TimeUnit;
|
|
import net.fabricmc.api.EnvType;
|
|
import net.fabricmc.api.Environment;
|
|
import net.minecraft.CrashReport;
|
|
import net.minecraft.CrashReportCategory;
|
|
import net.minecraft.CrashReportDetail;
|
|
import net.minecraft.Util;
|
|
import net.minecraft.client.Minecraft;
|
|
import net.minecraft.client.NarratorStatus;
|
|
import net.minecraft.client.gui.ComponentPath;
|
|
import net.minecraft.client.gui.Font;
|
|
import net.minecraft.client.gui.GuiGraphics;
|
|
import net.minecraft.client.gui.components.CycleButton;
|
|
import net.minecraft.client.gui.components.Renderable;
|
|
import net.minecraft.client.gui.components.TabOrderedElement;
|
|
import net.minecraft.client.gui.components.Tooltip;
|
|
import net.minecraft.client.gui.components.events.AbstractContainerEventHandler;
|
|
import net.minecraft.client.gui.components.events.GuiEventListener;
|
|
import net.minecraft.client.gui.narration.NarratableEntry;
|
|
import net.minecraft.client.gui.narration.NarratedElementType;
|
|
import net.minecraft.client.gui.narration.NarrationElementOutput;
|
|
import net.minecraft.client.gui.narration.ScreenNarrationCollector;
|
|
import net.minecraft.client.gui.narration.NarratableEntry.NarrationPriority;
|
|
import net.minecraft.client.gui.navigation.FocusNavigationEvent;
|
|
import net.minecraft.client.gui.navigation.ScreenDirection;
|
|
import net.minecraft.client.gui.navigation.ScreenRectangle;
|
|
import net.minecraft.client.gui.navigation.FocusNavigationEvent.ArrowNavigation;
|
|
import net.minecraft.client.gui.navigation.FocusNavigationEvent.InitialFocus;
|
|
import net.minecraft.client.gui.navigation.FocusNavigationEvent.TabNavigation;
|
|
import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipPositioner;
|
|
import net.minecraft.client.gui.screens.inventory.tooltip.DefaultTooltipPositioner;
|
|
import net.minecraft.client.renderer.CubeMap;
|
|
import net.minecraft.client.renderer.PanoramaRenderer;
|
|
import net.minecraft.client.renderer.RenderType;
|
|
import net.minecraft.network.chat.ClickEvent;
|
|
import net.minecraft.network.chat.Component;
|
|
import net.minecraft.network.chat.Style;
|
|
import net.minecraft.resources.ResourceLocation;
|
|
import net.minecraft.sounds.Music;
|
|
import net.minecraft.util.FormattedCharSequence;
|
|
import net.minecraft.world.item.Item;
|
|
import net.minecraft.world.item.ItemStack;
|
|
import net.minecraft.world.item.TooltipFlag.Default;
|
|
import org.jetbrains.annotations.Nullable;
|
|
import org.slf4j.Logger;
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
public abstract class Screen extends AbstractContainerEventHandler implements Renderable {
|
|
private static final Logger LOGGER = LogUtils.getLogger();
|
|
private static final Component USAGE_NARRATION = Component.translatable("narrator.screen.usage");
|
|
protected static final CubeMap CUBE_MAP = new CubeMap(ResourceLocation.withDefaultNamespace("textures/gui/title/background/panorama"));
|
|
protected static final PanoramaRenderer PANORAMA = new PanoramaRenderer(CUBE_MAP);
|
|
public static final ResourceLocation MENU_BACKGROUND = ResourceLocation.withDefaultNamespace("textures/gui/menu_background.png");
|
|
public static final ResourceLocation HEADER_SEPARATOR = ResourceLocation.withDefaultNamespace("textures/gui/header_separator.png");
|
|
public static final ResourceLocation FOOTER_SEPARATOR = ResourceLocation.withDefaultNamespace("textures/gui/footer_separator.png");
|
|
private static final ResourceLocation INWORLD_MENU_BACKGROUND = ResourceLocation.withDefaultNamespace("textures/gui/inworld_menu_background.png");
|
|
public static final ResourceLocation INWORLD_HEADER_SEPARATOR = ResourceLocation.withDefaultNamespace("textures/gui/inworld_header_separator.png");
|
|
public static final ResourceLocation INWORLD_FOOTER_SEPARATOR = ResourceLocation.withDefaultNamespace("textures/gui/inworld_footer_separator.png");
|
|
protected final Component title;
|
|
private final List<GuiEventListener> children = Lists.<GuiEventListener>newArrayList();
|
|
private final List<NarratableEntry> narratables = Lists.<NarratableEntry>newArrayList();
|
|
@Nullable
|
|
protected Minecraft minecraft;
|
|
private boolean initialized;
|
|
public int width;
|
|
public int height;
|
|
private final List<Renderable> renderables = Lists.<Renderable>newArrayList();
|
|
protected Font font;
|
|
private static final long NARRATE_SUPPRESS_AFTER_INIT_TIME = TimeUnit.SECONDS.toMillis(2L);
|
|
private static final long NARRATE_DELAY_NARRATOR_ENABLED = NARRATE_SUPPRESS_AFTER_INIT_TIME;
|
|
private static final long NARRATE_DELAY_MOUSE_MOVE = 750L;
|
|
private static final long NARRATE_DELAY_MOUSE_ACTION = 200L;
|
|
private static final long NARRATE_DELAY_KEYBOARD_ACTION = 200L;
|
|
private final ScreenNarrationCollector narrationState = new ScreenNarrationCollector();
|
|
private long narrationSuppressTime = Long.MIN_VALUE;
|
|
private long nextNarrationTime = Long.MAX_VALUE;
|
|
@Nullable
|
|
protected CycleButton<NarratorStatus> narratorButton;
|
|
@Nullable
|
|
private NarratableEntry lastNarratable;
|
|
@Nullable
|
|
private Screen.DeferredTooltipRendering deferredTooltipRendering;
|
|
protected final Executor screenExecutor = runnable -> this.minecraft.execute(() -> {
|
|
if (this.minecraft.screen == this) {
|
|
runnable.run();
|
|
}
|
|
});
|
|
|
|
protected Screen(Component title) {
|
|
this.title = title;
|
|
}
|
|
|
|
public Component getTitle() {
|
|
return this.title;
|
|
}
|
|
|
|
public Component getNarrationMessage() {
|
|
return this.getTitle();
|
|
}
|
|
|
|
public final void renderWithTooltip(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) {
|
|
this.render(guiGraphics, mouseX, mouseY, partialTick);
|
|
if (this.deferredTooltipRendering != null) {
|
|
guiGraphics.renderTooltip(this.font, this.deferredTooltipRendering.tooltip(), this.deferredTooltipRendering.positioner(), mouseX, mouseY);
|
|
this.deferredTooltipRendering = null;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) {
|
|
this.renderBackground(guiGraphics, mouseX, mouseY, partialTick);
|
|
|
|
for (Renderable renderable : this.renderables) {
|
|
renderable.render(guiGraphics, mouseX, mouseY, partialTick);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
|
|
if (keyCode == 256 && this.shouldCloseOnEsc()) {
|
|
this.onClose();
|
|
return true;
|
|
} else if (super.keyPressed(keyCode, scanCode, modifiers)) {
|
|
return true;
|
|
} else {
|
|
FocusNavigationEvent focusNavigationEvent = (FocusNavigationEvent)(switch (keyCode) {
|
|
case 258 -> this.createTabEvent();
|
|
default -> null;
|
|
case 262 -> this.createArrowEvent(ScreenDirection.RIGHT);
|
|
case 263 -> this.createArrowEvent(ScreenDirection.LEFT);
|
|
case 264 -> this.createArrowEvent(ScreenDirection.DOWN);
|
|
case 265 -> this.createArrowEvent(ScreenDirection.UP);
|
|
});
|
|
if (focusNavigationEvent != null) {
|
|
ComponentPath componentPath = super.nextFocusPath(focusNavigationEvent);
|
|
if (componentPath == null && focusNavigationEvent instanceof TabNavigation) {
|
|
this.clearFocus();
|
|
componentPath = super.nextFocusPath(focusNavigationEvent);
|
|
}
|
|
|
|
if (componentPath != null) {
|
|
this.changeFocus(componentPath);
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private TabNavigation createTabEvent() {
|
|
boolean bl = !hasShiftDown();
|
|
return new TabNavigation(bl);
|
|
}
|
|
|
|
private ArrowNavigation createArrowEvent(ScreenDirection direction) {
|
|
return new ArrowNavigation(direction);
|
|
}
|
|
|
|
protected void setInitialFocus() {
|
|
if (this.minecraft.getLastInputType().isKeyboard()) {
|
|
TabNavigation tabNavigation = new TabNavigation(true);
|
|
ComponentPath componentPath = super.nextFocusPath(tabNavigation);
|
|
if (componentPath != null) {
|
|
this.changeFocus(componentPath);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected void setInitialFocus(GuiEventListener listener) {
|
|
ComponentPath componentPath = ComponentPath.path(this, listener.nextFocusPath(new InitialFocus()));
|
|
if (componentPath != null) {
|
|
this.changeFocus(componentPath);
|
|
}
|
|
}
|
|
|
|
public void clearFocus() {
|
|
ComponentPath componentPath = this.getCurrentFocusPath();
|
|
if (componentPath != null) {
|
|
componentPath.applyFocus(false);
|
|
}
|
|
}
|
|
|
|
@VisibleForTesting
|
|
protected void changeFocus(ComponentPath path) {
|
|
this.clearFocus();
|
|
path.applyFocus(true);
|
|
}
|
|
|
|
public boolean shouldCloseOnEsc() {
|
|
return true;
|
|
}
|
|
|
|
public void onClose() {
|
|
this.minecraft.setScreen(null);
|
|
}
|
|
|
|
protected <T extends GuiEventListener & Renderable & NarratableEntry> T addRenderableWidget(T widget) {
|
|
this.renderables.add(widget);
|
|
return this.addWidget(widget);
|
|
}
|
|
|
|
protected <T extends Renderable> T addRenderableOnly(T renderable) {
|
|
this.renderables.add(renderable);
|
|
return renderable;
|
|
}
|
|
|
|
protected <T extends GuiEventListener & NarratableEntry> T addWidget(T listener) {
|
|
this.children.add(listener);
|
|
this.narratables.add(listener);
|
|
return listener;
|
|
}
|
|
|
|
protected void removeWidget(GuiEventListener listener) {
|
|
if (listener instanceof Renderable) {
|
|
this.renderables.remove((Renderable)listener);
|
|
}
|
|
|
|
if (listener instanceof NarratableEntry) {
|
|
this.narratables.remove((NarratableEntry)listener);
|
|
}
|
|
|
|
this.children.remove(listener);
|
|
}
|
|
|
|
protected void clearWidgets() {
|
|
this.renderables.clear();
|
|
this.children.clear();
|
|
this.narratables.clear();
|
|
}
|
|
|
|
public static List<Component> getTooltipFromItem(Minecraft minecraft, ItemStack item) {
|
|
return item.getTooltipLines(
|
|
Item.TooltipContext.of(minecraft.level), minecraft.player, minecraft.options.advancedItemTooltips ? Default.ADVANCED : Default.NORMAL
|
|
);
|
|
}
|
|
|
|
protected void insertText(String text, boolean overwrite) {
|
|
}
|
|
|
|
public boolean handleComponentClicked(@Nullable Style style) {
|
|
if (style == null) {
|
|
return false;
|
|
} else {
|
|
ClickEvent clickEvent = style.getClickEvent();
|
|
if (hasShiftDown()) {
|
|
if (style.getInsertion() != null) {
|
|
this.insertText(style.getInsertion(), false);
|
|
}
|
|
} else if (clickEvent != null) {
|
|
switch (clickEvent) {
|
|
case ClickEvent.OpenUrl(URI var28):
|
|
URI var19 = var28;
|
|
if (!this.minecraft.options.chatLinks().get()) {
|
|
return false;
|
|
}
|
|
|
|
if (this.minecraft.options.chatLinksPrompt().get()) {
|
|
this.minecraft.setScreen(new ConfirmLinkScreen(bl -> {
|
|
if (bl) {
|
|
Util.getPlatform().openUri(var19);
|
|
}
|
|
|
|
this.minecraft.setScreen(this);
|
|
}, var19.toString(), false));
|
|
} else {
|
|
Util.getPlatform().openUri(var19);
|
|
}
|
|
break;
|
|
case ClickEvent.OpenFile openFile:
|
|
Util.getPlatform().openFile(openFile.file());
|
|
break;
|
|
case ClickEvent.SuggestCommand(String var20):
|
|
this.insertText(var20, true);
|
|
break;
|
|
case ClickEvent.RunCommand(String var24):
|
|
String var21 = var24;
|
|
String string2 = var21;
|
|
if (var21.startsWith("/")) {
|
|
string2 = var21.substring(1);
|
|
}
|
|
|
|
if (!this.minecraft.player.connection.sendUnsignedCommand(string2)) {
|
|
LOGGER.error("Not allowed to run command with signed argument from click event: '{}'", string2);
|
|
}
|
|
break;
|
|
case ClickEvent.CopyToClipboard(String var14):
|
|
this.minecraft.keyboardHandler.setClipboard(var14);
|
|
break;
|
|
default:
|
|
LOGGER.error("Don't know how to handle {}", clickEvent);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public final void init(Minecraft minecraft, int width, int height) {
|
|
this.minecraft = minecraft;
|
|
this.font = minecraft.font;
|
|
this.width = width;
|
|
this.height = height;
|
|
if (!this.initialized) {
|
|
this.init();
|
|
this.setInitialFocus();
|
|
} else {
|
|
this.repositionElements();
|
|
}
|
|
|
|
this.initialized = true;
|
|
this.triggerImmediateNarration(false);
|
|
this.suppressNarration(NARRATE_SUPPRESS_AFTER_INIT_TIME);
|
|
}
|
|
|
|
protected void rebuildWidgets() {
|
|
this.clearWidgets();
|
|
this.clearFocus();
|
|
this.init();
|
|
this.setInitialFocus();
|
|
}
|
|
|
|
@Override
|
|
public List<? extends GuiEventListener> children() {
|
|
return this.children;
|
|
}
|
|
|
|
protected void init() {
|
|
}
|
|
|
|
public void tick() {
|
|
}
|
|
|
|
public void removed() {
|
|
}
|
|
|
|
public void added() {
|
|
}
|
|
|
|
public void renderBackground(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) {
|
|
if (this.minecraft.level == null) {
|
|
this.renderPanorama(guiGraphics, partialTick);
|
|
}
|
|
|
|
this.renderBlurredBackground();
|
|
this.renderMenuBackground(guiGraphics);
|
|
}
|
|
|
|
protected void renderBlurredBackground() {
|
|
this.minecraft.gameRenderer.processBlurEffect();
|
|
}
|
|
|
|
protected void renderPanorama(GuiGraphics guiGraphics, float partialTick) {
|
|
PANORAMA.render(guiGraphics, this.width, this.height, 1.0F, partialTick);
|
|
}
|
|
|
|
protected void renderMenuBackground(GuiGraphics partialTick) {
|
|
this.renderMenuBackground(partialTick, 0, 0, this.width, this.height);
|
|
}
|
|
|
|
protected void renderMenuBackground(GuiGraphics guiGraphics, int x, int y, int width, int height) {
|
|
renderMenuBackgroundTexture(guiGraphics, this.minecraft.level == null ? MENU_BACKGROUND : INWORLD_MENU_BACKGROUND, x, y, 0.0F, 0.0F, width, height);
|
|
}
|
|
|
|
public static void renderMenuBackgroundTexture(
|
|
GuiGraphics guiGraphics, ResourceLocation texture, int x, int y, float uOffset, float vOffset, int width, int height
|
|
) {
|
|
int i = 32;
|
|
guiGraphics.blit(RenderType::guiTextured, texture, x, y, uOffset, vOffset, width, height, 32, 32);
|
|
}
|
|
|
|
public void renderTransparentBackground(GuiGraphics guiGraphics) {
|
|
guiGraphics.fillGradient(0, 0, this.width, this.height, -1072689136, -804253680);
|
|
}
|
|
|
|
public boolean isPauseScreen() {
|
|
return true;
|
|
}
|
|
|
|
public static boolean hasControlDown() {
|
|
return Minecraft.ON_OSX
|
|
? InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), 343)
|
|
|| InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), 347)
|
|
: InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), 341)
|
|
|| InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), 345);
|
|
}
|
|
|
|
public static boolean hasShiftDown() {
|
|
return InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), 340)
|
|
|| InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), 344);
|
|
}
|
|
|
|
public static boolean hasAltDown() {
|
|
return InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), 342)
|
|
|| InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), 346);
|
|
}
|
|
|
|
public static boolean isCut(int keyCode) {
|
|
return keyCode == 88 && hasControlDown() && !hasShiftDown() && !hasAltDown();
|
|
}
|
|
|
|
public static boolean isPaste(int keyCode) {
|
|
return keyCode == 86 && hasControlDown() && !hasShiftDown() && !hasAltDown();
|
|
}
|
|
|
|
public static boolean isCopy(int keyCode) {
|
|
return keyCode == 67 && hasControlDown() && !hasShiftDown() && !hasAltDown();
|
|
}
|
|
|
|
public static boolean isSelectAll(int keyCode) {
|
|
return keyCode == 65 && hasControlDown() && !hasShiftDown() && !hasAltDown();
|
|
}
|
|
|
|
protected void repositionElements() {
|
|
this.rebuildWidgets();
|
|
}
|
|
|
|
public void resize(Minecraft minecraft, int width, int height) {
|
|
this.width = width;
|
|
this.height = height;
|
|
this.repositionElements();
|
|
}
|
|
|
|
public void fillCrashDetails(CrashReport crashReport) {
|
|
CrashReportCategory crashReportCategory = crashReport.addCategory("Affected screen", 1);
|
|
crashReportCategory.setDetail("Screen name", (CrashReportDetail<String>)(() -> this.getClass().getCanonicalName()));
|
|
}
|
|
|
|
protected boolean isValidCharacterForName(String text, char charTyped, int cursorPos) {
|
|
int i = text.indexOf(58);
|
|
int j = text.indexOf(47);
|
|
if (charTyped == ':') {
|
|
return (j == -1 || cursorPos <= j) && i == -1;
|
|
} else {
|
|
return charTyped == '/'
|
|
? cursorPos > i
|
|
: charTyped == '_' || charTyped == '-' || charTyped >= 'a' && charTyped <= 'z' || charTyped >= '0' && charTyped <= '9' || charTyped == '.';
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean isMouseOver(double mouseX, double mouseY) {
|
|
return true;
|
|
}
|
|
|
|
public void onFilesDrop(List<Path> packs) {
|
|
}
|
|
|
|
private void scheduleNarration(long delay, boolean stopSuppression) {
|
|
this.nextNarrationTime = Util.getMillis() + delay;
|
|
if (stopSuppression) {
|
|
this.narrationSuppressTime = Long.MIN_VALUE;
|
|
}
|
|
}
|
|
|
|
private void suppressNarration(long time) {
|
|
this.narrationSuppressTime = Util.getMillis() + time;
|
|
}
|
|
|
|
public void afterMouseMove() {
|
|
this.scheduleNarration(750L, false);
|
|
}
|
|
|
|
public void afterMouseAction() {
|
|
this.scheduleNarration(200L, true);
|
|
}
|
|
|
|
public void afterKeyboardAction() {
|
|
this.scheduleNarration(200L, true);
|
|
}
|
|
|
|
private boolean shouldRunNarration() {
|
|
return this.minecraft.getNarrator().isActive();
|
|
}
|
|
|
|
public void handleDelayedNarration() {
|
|
if (this.shouldRunNarration()) {
|
|
long l = Util.getMillis();
|
|
if (l > this.nextNarrationTime && l > this.narrationSuppressTime) {
|
|
this.runNarration(true);
|
|
this.nextNarrationTime = Long.MAX_VALUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void triggerImmediateNarration(boolean onlyNarrateNew) {
|
|
if (this.shouldRunNarration()) {
|
|
this.runNarration(onlyNarrateNew);
|
|
}
|
|
}
|
|
|
|
private void runNarration(boolean onlyNarrateNew) {
|
|
this.narrationState.update(this::updateNarrationState);
|
|
String string = this.narrationState.collectNarrationText(!onlyNarrateNew);
|
|
if (!string.isEmpty()) {
|
|
this.minecraft.getNarrator().sayNow(string);
|
|
}
|
|
}
|
|
|
|
protected boolean shouldNarrateNavigation() {
|
|
return true;
|
|
}
|
|
|
|
protected void updateNarrationState(NarrationElementOutput output) {
|
|
output.add(NarratedElementType.TITLE, this.getNarrationMessage());
|
|
if (this.shouldNarrateNavigation()) {
|
|
output.add(NarratedElementType.USAGE, USAGE_NARRATION);
|
|
}
|
|
|
|
this.updateNarratedWidget(output);
|
|
}
|
|
|
|
protected void updateNarratedWidget(NarrationElementOutput narrationElementOutput) {
|
|
List<? extends NarratableEntry> list = this.narratables
|
|
.stream()
|
|
.flatMap(narratableEntry -> narratableEntry.getNarratables().stream())
|
|
.filter(NarratableEntry::isActive)
|
|
.sorted(Comparator.comparingInt(TabOrderedElement::getTabOrderGroup))
|
|
.toList();
|
|
Screen.NarratableSearchResult narratableSearchResult = findNarratableWidget(list, this.lastNarratable);
|
|
if (narratableSearchResult != null) {
|
|
if (narratableSearchResult.priority.isTerminal()) {
|
|
this.lastNarratable = narratableSearchResult.entry;
|
|
}
|
|
|
|
if (list.size() > 1) {
|
|
narrationElementOutput.add(NarratedElementType.POSITION, Component.translatable("narrator.position.screen", narratableSearchResult.index + 1, list.size()));
|
|
if (narratableSearchResult.priority == NarrationPriority.FOCUSED) {
|
|
narrationElementOutput.add(NarratedElementType.USAGE, this.getUsageNarration());
|
|
}
|
|
}
|
|
|
|
narratableSearchResult.entry.updateNarration(narrationElementOutput.nest());
|
|
}
|
|
}
|
|
|
|
protected Component getUsageNarration() {
|
|
return Component.translatable("narration.component_list.usage");
|
|
}
|
|
|
|
@Nullable
|
|
public static Screen.NarratableSearchResult findNarratableWidget(List<? extends NarratableEntry> entries, @Nullable NarratableEntry target) {
|
|
Screen.NarratableSearchResult narratableSearchResult = null;
|
|
Screen.NarratableSearchResult narratableSearchResult2 = null;
|
|
int i = 0;
|
|
|
|
for (int j = entries.size(); i < j; i++) {
|
|
NarratableEntry narratableEntry = (NarratableEntry)entries.get(i);
|
|
NarrationPriority narrationPriority = narratableEntry.narrationPriority();
|
|
if (narrationPriority.isTerminal()) {
|
|
if (narratableEntry != target) {
|
|
return new Screen.NarratableSearchResult(narratableEntry, i, narrationPriority);
|
|
}
|
|
|
|
narratableSearchResult2 = new Screen.NarratableSearchResult(narratableEntry, i, narrationPriority);
|
|
} else if (narrationPriority.compareTo(narratableSearchResult != null ? narratableSearchResult.priority : NarrationPriority.NONE) > 0) {
|
|
narratableSearchResult = new Screen.NarratableSearchResult(narratableEntry, i, narrationPriority);
|
|
}
|
|
}
|
|
|
|
return narratableSearchResult != null ? narratableSearchResult : narratableSearchResult2;
|
|
}
|
|
|
|
public void updateNarratorStatus(boolean narratorEnabled) {
|
|
if (narratorEnabled) {
|
|
this.scheduleNarration(NARRATE_DELAY_NARRATOR_ENABLED, false);
|
|
}
|
|
|
|
if (this.narratorButton != null) {
|
|
this.narratorButton.setValue(this.minecraft.options.narrator().get());
|
|
}
|
|
}
|
|
|
|
protected void clearTooltipForNextRenderPass() {
|
|
this.deferredTooltipRendering = null;
|
|
}
|
|
|
|
public void setTooltipForNextRenderPass(List<FormattedCharSequence> tooltip) {
|
|
this.setTooltipForNextRenderPass(tooltip, DefaultTooltipPositioner.INSTANCE, true);
|
|
}
|
|
|
|
public void setTooltipForNextRenderPass(List<FormattedCharSequence> tooltip, ClientTooltipPositioner positioner, boolean override) {
|
|
if (this.deferredTooltipRendering == null || override) {
|
|
this.deferredTooltipRendering = new Screen.DeferredTooltipRendering(tooltip, positioner);
|
|
}
|
|
}
|
|
|
|
public void setTooltipForNextRenderPass(Component tooltip) {
|
|
this.setTooltipForNextRenderPass(Tooltip.splitTooltip(this.minecraft, tooltip));
|
|
}
|
|
|
|
public void setTooltipForNextRenderPass(Tooltip tooltip, ClientTooltipPositioner positioner, boolean override) {
|
|
this.setTooltipForNextRenderPass(tooltip.toCharSequence(this.minecraft), positioner, override);
|
|
}
|
|
|
|
public Font getFont() {
|
|
return this.font;
|
|
}
|
|
|
|
public boolean showsActiveEffects() {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public ScreenRectangle getRectangle() {
|
|
return new ScreenRectangle(0, 0, this.width, this.height);
|
|
}
|
|
|
|
@Nullable
|
|
public Music getBackgroundMusic() {
|
|
return null;
|
|
}
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
record DeferredTooltipRendering(List<FormattedCharSequence> tooltip, ClientTooltipPositioner positioner) {
|
|
}
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
public static class NarratableSearchResult {
|
|
public final NarratableEntry entry;
|
|
public final int index;
|
|
public final NarrationPriority priority;
|
|
|
|
public NarratableSearchResult(NarratableEntry entry, int index, NarrationPriority priority) {
|
|
this.entry = entry;
|
|
this.index = index;
|
|
this.priority = priority;
|
|
}
|
|
}
|
|
}
|