AdvancementWidget.java

net.minecraft.client.gui.screens.advancements.AdvancementWidget

信息

  • 全限定名:net.minecraft.client.gui.screens.advancements.AdvancementWidget
  • 类型:public class
  • 包:net.minecraft.client.gui.screens.advancements
  • 源码路径:src/main/java/net/minecraft/client/gui/screens/advancements/AdvancementWidget.java
  • 起始行号:L27
  • 职责:

    TODO

字段/常量

  • TITLE_BOX_SPRITE

    • 类型: Identifier
    • 修饰符: private static final
    • 源码定位: L28
    • 说明:

      TODO

  • HEIGHT

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L29
    • 说明:

      TODO

  • BOX_X

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L30
    • 说明:

      TODO

  • BOX_WIDTH

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L31
    • 说明:

      TODO

  • FRAME_WIDTH

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L32
    • 说明:

      TODO

  • ICON_X

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L33
    • 说明:

      TODO

  • ICON_Y

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L34
    • 说明:

      TODO

  • ICON_WIDTH

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L35
    • 说明:

      TODO

  • TITLE_PADDING_LEFT

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L36
    • 说明:

      TODO

  • TITLE_PADDING_RIGHT

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L37
    • 说明:

      TODO

  • TITLE_X

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L38
    • 说明:

      TODO

  • TITLE_PADDING_TOP

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L39
    • 说明:

      TODO

  • TITLE_PADDING_BOTTOM

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L40
    • 说明:

      TODO

  • TITLE_MAX_WIDTH

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L41
    • 说明:

      TODO

  • TITLE_MIN_WIDTH

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L42
    • 说明:

      TODO

  • TEST_SPLIT_OFFSETS

    • 类型: int[]
    • 修饰符: private static final
    • 源码定位: L43
    • 说明:

      TODO

  • tab

    • 类型: AdvancementTab
    • 修饰符: private final
    • 源码定位: L44
    • 说明:

      TODO

  • advancementNode

    • 类型: AdvancementNode
    • 修饰符: private final
    • 源码定位: L45
    • 说明:

      TODO

  • display

    • 类型: DisplayInfo
    • 修饰符: private final
    • 源码定位: L46
    • 说明:

      TODO

  • icon

    • 类型: ItemStack
    • 修饰符: private final
    • 源码定位: L47
    • 说明:

      TODO

  • titleLines

    • 类型: List<FormattedCharSequence>
    • 修饰符: private final
    • 源码定位: L48
    • 说明:

      TODO

  • width

    • 类型: int
    • 修饰符: private final
    • 源码定位: L49
    • 说明:

      TODO

  • description

    • 类型: List<FormattedCharSequence>
    • 修饰符: private final
    • 源码定位: L50
    • 说明:

      TODO

  • minecraft

    • 类型: Minecraft
    • 修饰符: private final
    • 源码定位: L51
    • 说明:

      TODO

  • parent

    • 类型: AdvancementWidget
    • 修饰符: private
    • 源码定位: L52
    • 说明:

      TODO

  • children

    • 类型: List<AdvancementWidget>
    • 修饰符: private final
    • 源码定位: L53
    • 说明:

      TODO

  • progress

    • 类型: AdvancementProgress
    • 修饰符: private
    • 源码定位: L54
    • 说明:

      TODO

  • x

    • 类型: int
    • 修饰符: private final
    • 源码定位: L55
    • 说明:

      TODO

  • y

    • 类型: int
    • 修饰符: private final
    • 源码定位: L56
    • 说明:

      TODO

内部类/嵌套类型

构造器

public AdvancementWidget(AdvancementTab tab, Minecraft minecraft, AdvancementNode advancementNode, DisplayInfo display) @ L58

  • 构造器名:AdvancementWidget
  • 源码定位:L58
  • 修饰符:public

参数:

  • tab: AdvancementTab
  • minecraft: Minecraft
  • advancementNode: AdvancementNode
  • display: DisplayInfo

说明:

TODO

方法

下面的方法块按源码顺序生成。

private int getMaxProgressWidth() @ L84

  • 方法名:getMaxProgressWidth
  • 源码定位:L84
  • 返回类型:int
  • 修饰符:private

参数:

说明:

TODO

private static float getMaxWidth(StringSplitter splitter, List<FormattedText> input) @ L95

  • 方法名:getMaxWidth
  • 源码定位:L95
  • 返回类型:float
  • 修饰符:private static

参数:

  • splitter: StringSplitter
  • input: List

说明:

TODO

private List<FormattedText> findOptimalLines(Component input, int preferredWidth) @ L99

  • 方法名:findOptimalLines
  • 源码定位:L99
  • 返回类型:List
  • 修饰符:private

参数:

  • input: Component
  • preferredWidth: int

说明:

TODO

private AdvancementWidget getFirstVisibleParent(AdvancementNode node) @ L120

  • 方法名:getFirstVisibleParent
  • 源码定位:L120
  • 返回类型:AdvancementWidget
  • 修饰符:private

参数:

  • node: AdvancementNode

说明:

TODO

public void extractConnectivity(GuiGraphicsExtractor graphics, int xo, int yo, boolean background) @ L128

  • 方法名:extractConnectivity
  • 源码定位:L128
  • 返回类型:void
  • 修饰符:public

参数:

  • graphics: GuiGraphicsExtractor
  • xo: int
  • yo: int
  • background: boolean

说明:

TODO

public void extractRenderState(GuiGraphicsExtractor graphics, int xo, int yo) @ L157

  • 方法名:extractRenderState
  • 源码定位:L157
  • 返回类型:void
  • 修饰符:public

参数:

  • graphics: GuiGraphicsExtractor
  • xo: int
  • yo: int

说明:

TODO

public int getWidth() @ L176

  • 方法名:getWidth
  • 源码定位:L176
  • 返回类型:int
  • 修饰符:public

参数:

说明:

TODO

public void setProgress(AdvancementProgress progress) @ L180

  • 方法名:setProgress
  • 源码定位:L180
  • 返回类型:void
  • 修饰符:public

参数:

  • progress: AdvancementProgress

说明:

TODO

public void addChild(AdvancementWidget widget) @ L184

  • 方法名:addChild
  • 源码定位:L184
  • 返回类型:void
  • 修饰符:public

参数:

  • widget: AdvancementWidget

说明:

TODO

public void extractHover(GuiGraphicsExtractor graphics, int xo, int yo, float fade, int screenxo, int screenyo) @ L188

  • 方法名:extractHover
  • 源码定位:L188
  • 返回类型:void
  • 修饰符:public

参数:

  • graphics: GuiGraphicsExtractor
  • xo: int
  • yo: int
  • fade: float
  • screenxo: int
  • screenyo: int

说明:

TODO

private void extractMultilineText(GuiGraphicsExtractor graphics, List<FormattedCharSequence> lines, int x, int y, int color) @ L285

  • 方法名:extractMultilineText
  • 源码定位:L285
  • 返回类型:void
  • 修饰符:private

参数:

  • graphics: GuiGraphicsExtractor
  • lines: List
  • x: int
  • y: int
  • color: int

说明:

TODO

public boolean isMouseOver(int xo, int yo, int mouseX, int mouseY) @ L293

  • 方法名:isMouseOver
  • 源码定位:L293
  • 返回类型:boolean
  • 修饰符:public

参数:

  • xo: int
  • yo: int
  • mouseX: int
  • mouseY: int

说明:

TODO

public void attachToParent() @ L305

  • 方法名:attachToParent
  • 源码定位:L305
  • 返回类型:void
  • 修饰符:public

参数:

说明:

TODO

public int getY() @ L314

  • 方法名:getY
  • 源码定位:L314
  • 返回类型:int
  • 修饰符:public

参数:

说明:

TODO

public int getX() @ L318

  • 方法名:getX
  • 源码定位:L318
  • 返回类型:int
  • 修饰符:public

参数:

说明:

TODO

代码

@OnlyIn(Dist.CLIENT)
public class AdvancementWidget {
    private static final Identifier TITLE_BOX_SPRITE = Identifier.withDefaultNamespace("advancements/title_box");
    private static final int HEIGHT = 26;
    private static final int BOX_X = 0;
    private static final int BOX_WIDTH = 200;
    private static final int FRAME_WIDTH = 26;
    private static final int ICON_X = 8;
    private static final int ICON_Y = 5;
    private static final int ICON_WIDTH = 26;
    private static final int TITLE_PADDING_LEFT = 3;
    private static final int TITLE_PADDING_RIGHT = 5;
    private static final int TITLE_X = 32;
    private static final int TITLE_PADDING_TOP = 9;
    private static final int TITLE_PADDING_BOTTOM = 8;
    private static final int TITLE_MAX_WIDTH = 163;
    private static final int TITLE_MIN_WIDTH = 80;
    private static final int[] TEST_SPLIT_OFFSETS = new int[]{0, 10, -10, 25, -25};
    private final AdvancementTab tab;
    private final AdvancementNode advancementNode;
    private final DisplayInfo display;
    private final ItemStack icon;
    private final List<FormattedCharSequence> titleLines;
    private final int width;
    private final List<FormattedCharSequence> description;
    private final Minecraft minecraft;
    private @Nullable AdvancementWidget parent;
    private final List<AdvancementWidget> children = Lists.newArrayList();
    private @Nullable AdvancementProgress progress;
    private final int x;
    private final int y;
 
    public AdvancementWidget(AdvancementTab tab, Minecraft minecraft, AdvancementNode advancementNode, DisplayInfo display) {
        this.tab = tab;
        this.advancementNode = advancementNode;
        this.display = display;
        this.minecraft = minecraft;
        this.titleLines = minecraft.font.split(display.getTitle(), 163);
        this.x = Mth.floor(display.getX() * 28.0F);
        this.y = Mth.floor(display.getY() * 27.0F);
        int titleWidth = Math.max(this.titleLines.stream().mapToInt(minecraft.font::width).max().orElse(0), 80);
        int maxProgressWidth = this.getMaxProgressWidth();
        int longestDescLine = 29 + titleWidth + maxProgressWidth;
        this.description = Language.getInstance()
            .getVisualOrder(
                this.findOptimalLines(
                    ComponentUtils.mergeStyles(display.getDescription(), Style.EMPTY.withColor(display.getType().getChatColor())), longestDescLine
                )
            );
 
        for (FormattedCharSequence line : this.description) {
            longestDescLine = Math.max(longestDescLine, minecraft.font.width(line));
        }
 
        this.width = longestDescLine + 3 + 5;
        this.icon = display.getIcon().create();
    }
 
    private int getMaxProgressWidth() {
        int maxCriteraRequired = this.advancementNode.advancement().requirements().size();
        if (maxCriteraRequired <= 1) {
            return 0;
        } else {
            int spacing = 8;
            Component fakeMaxProgress = Component.translatable("advancements.progress", maxCriteraRequired, maxCriteraRequired);
            return this.minecraft.font.width(fakeMaxProgress) + 8;
        }
    }
 
    private static float getMaxWidth(StringSplitter splitter, List<FormattedText> input) {
        return (float)input.stream().mapToDouble(splitter::stringWidth).max().orElse(0.0);
    }
 
    private List<FormattedText> findOptimalLines(Component input, int preferredWidth) {
        StringSplitter splitter = this.minecraft.font.getSplitter();
        List<FormattedText> bestSplit = null;
        float bestDistance = Float.MAX_VALUE;
 
        for (int testMargin : TEST_SPLIT_OFFSETS) {
            List<FormattedText> testSplit = splitter.splitLines(input, preferredWidth - testMargin, Style.EMPTY);
            float distance = Math.abs(getMaxWidth(splitter, testSplit) - preferredWidth);
            if (distance <= 10.0F) {
                return testSplit;
            }
 
            if (distance < bestDistance) {
                bestDistance = distance;
                bestSplit = testSplit;
            }
        }
 
        return bestSplit;
    }
 
    private @Nullable AdvancementWidget getFirstVisibleParent(AdvancementNode node) {
        do {
            node = node.parent();
        } while (node != null && node.advancement().display().isEmpty());
 
        return node != null && !node.advancement().display().isEmpty() ? this.tab.getWidget(node.holder()) : null;
    }
 
    public void extractConnectivity(GuiGraphicsExtractor graphics, int xo, int yo, boolean background) {
        if (this.parent != null) {
            int depX = xo + this.parent.x + 13;
            int splitX = xo + this.parent.x + 26 + 4;
            int depY = yo + this.parent.y + 13;
            int myX = xo + this.x + 13;
            int myY = yo + this.y + 13;
            int col = background ? -16777216 : -1;
            if (background) {
                graphics.horizontalLine(splitX, depX, depY - 1, col);
                graphics.horizontalLine(splitX + 1, depX, depY, col);
                graphics.horizontalLine(splitX, depX, depY + 1, col);
                graphics.horizontalLine(myX, splitX - 1, myY - 1, col);
                graphics.horizontalLine(myX, splitX - 1, myY, col);
                graphics.horizontalLine(myX, splitX - 1, myY + 1, col);
                graphics.verticalLine(splitX - 1, myY, depY, col);
                graphics.verticalLine(splitX + 1, myY, depY, col);
            } else {
                graphics.horizontalLine(splitX, depX, depY, col);
                graphics.horizontalLine(myX, splitX, myY, col);
                graphics.verticalLine(splitX, myY, depY, col);
            }
        }
 
        for (AdvancementWidget child : this.children) {
            child.extractConnectivity(graphics, xo, yo, background);
        }
    }
 
    public void extractRenderState(GuiGraphicsExtractor graphics, int xo, int yo) {
        if (!this.display.isHidden() || this.progress != null && this.progress.isDone()) {
            float amount = this.progress == null ? 0.0F : this.progress.getPercent();
            AdvancementWidgetType iconFrame;
            if (amount >= 1.0F) {
                iconFrame = AdvancementWidgetType.OBTAINED;
            } else {
                iconFrame = AdvancementWidgetType.UNOBTAINED;
            }
 
            graphics.blitSprite(RenderPipelines.GUI_TEXTURED, iconFrame.frameSprite(this.display.getType()), xo + this.x + 3, yo + this.y, 26, 26);
            graphics.fakeItem(this.icon, xo + this.x + 8, yo + this.y + 5);
        }
 
        for (AdvancementWidget child : this.children) {
            child.extractRenderState(graphics, xo, yo);
        }
    }
 
    public int getWidth() {
        return this.width;
    }
 
    public void setProgress(AdvancementProgress progress) {
        this.progress = progress;
    }
 
    public void addChild(AdvancementWidget widget) {
        this.children.add(widget);
    }
 
    public void extractHover(GuiGraphicsExtractor graphics, int xo, int yo, float fade, int screenxo, int screenyo) {
        Font font = this.minecraft.font;
        int titleBarHeight = 9 * this.titleLines.size() + 9 + 8;
        int titleTop = yo + this.y + (26 - titleBarHeight) / 2;
        int titleBarBottom = titleTop + titleBarHeight;
        int descriptionTextHeight = this.description.size() * 9;
        int descriptionHeight = 6 + descriptionTextHeight;
        boolean leftSide = screenxo + xo + this.x + this.width + 26 >= this.tab.getScreen().width;
        Component progressText = this.progress == null ? null : this.progress.getProgressText();
        int progressWidth = progressText == null ? 0 : font.width(progressText);
        boolean topSide = titleBarBottom + descriptionHeight >= 113;
        float amount = this.progress == null ? 0.0F : this.progress.getPercent();
        int firstHalfWidth = Mth.floor(amount * this.width);
        AdvancementWidgetType firstHalf;
        AdvancementWidgetType secondHalf;
        AdvancementWidgetType iconFrame;
        if (amount >= 1.0F) {
            firstHalfWidth = this.width / 2;
            firstHalf = AdvancementWidgetType.OBTAINED;
            secondHalf = AdvancementWidgetType.OBTAINED;
            iconFrame = AdvancementWidgetType.OBTAINED;
        } else if (firstHalfWidth < 2) {
            firstHalfWidth = this.width / 2;
            firstHalf = AdvancementWidgetType.UNOBTAINED;
            secondHalf = AdvancementWidgetType.UNOBTAINED;
            iconFrame = AdvancementWidgetType.UNOBTAINED;
        } else if (firstHalfWidth > this.width - 2) {
            firstHalfWidth = this.width / 2;
            firstHalf = AdvancementWidgetType.OBTAINED;
            secondHalf = AdvancementWidgetType.OBTAINED;
            iconFrame = AdvancementWidgetType.UNOBTAINED;
        } else {
            firstHalf = AdvancementWidgetType.OBTAINED;
            secondHalf = AdvancementWidgetType.UNOBTAINED;
            iconFrame = AdvancementWidgetType.UNOBTAINED;
        }
 
        int secondBarWidth = this.width - firstHalfWidth;
        int titleLeft;
        if (leftSide) {
            titleLeft = xo + this.x - this.width + 26 + 6;
        } else {
            titleLeft = xo + this.x;
        }
 
        int backgroundHeight = titleBarHeight + descriptionHeight;
        if (!this.description.isEmpty()) {
            if (topSide) {
                graphics.blitSprite(RenderPipelines.GUI_TEXTURED, TITLE_BOX_SPRITE, titleLeft, titleBarBottom - backgroundHeight, this.width, backgroundHeight);
            } else {
                graphics.blitSprite(RenderPipelines.GUI_TEXTURED, TITLE_BOX_SPRITE, titleLeft, titleTop, this.width, backgroundHeight);
            }
        }
 
        if (firstHalf != secondHalf) {
            graphics.blitSprite(
                RenderPipelines.GUI_TEXTURED, firstHalf.boxSprite(), 200, titleBarHeight, 0, 0, titleLeft, titleTop, firstHalfWidth, titleBarHeight
            );
            graphics.blitSprite(
                RenderPipelines.GUI_TEXTURED,
                secondHalf.boxSprite(),
                200,
                titleBarHeight,
                200 - secondBarWidth,
                0,
                titleLeft + firstHalfWidth,
                titleTop,
                secondBarWidth,
                titleBarHeight
            );
        } else {
            graphics.blitSprite(RenderPipelines.GUI_TEXTURED, firstHalf.boxSprite(), titleLeft, titleTop, this.width, titleBarHeight);
        }
 
        graphics.blitSprite(RenderPipelines.GUI_TEXTURED, iconFrame.frameSprite(this.display.getType()), xo + this.x + 3, yo + this.y, 26, 26);
        int descriptionLeft = titleLeft + 5;
        if (leftSide) {
            this.extractMultilineText(graphics, this.titleLines, descriptionLeft, titleTop + 9, -1);
            if (progressText != null) {
                graphics.text(font, progressText, xo + this.x - progressWidth, titleTop + 9, -1);
            }
        } else {
            this.extractMultilineText(graphics, this.titleLines, xo + this.x + 32, titleTop + 9, -1);
            if (progressText != null) {
                graphics.text(font, progressText, xo + this.x + this.width - progressWidth - 5, titleTop + 9, -1);
            }
        }
 
        if (topSide) {
            this.extractMultilineText(graphics, this.description, descriptionLeft, titleTop - descriptionTextHeight + 1, -16711936);
        } else {
            this.extractMultilineText(graphics, this.description, descriptionLeft, titleBarBottom, -16711936);
        }
 
        graphics.fakeItem(this.icon, xo + this.x + 8, yo + this.y + 5);
    }
 
    private void extractMultilineText(GuiGraphicsExtractor graphics, List<FormattedCharSequence> lines, int x, int y, int color) {
        Font font = this.minecraft.font;
 
        for (int i = 0; i < lines.size(); i++) {
            graphics.text(font, lines.get(i), x, y + i * 9, color);
        }
    }
 
    public boolean isMouseOver(int xo, int yo, int mouseX, int mouseY) {
        if (!this.display.isHidden() || this.progress != null && this.progress.isDone()) {
            int x0 = xo + this.x;
            int x1 = x0 + 26;
            int y0 = yo + this.y;
            int y1 = y0 + 26;
            return mouseX >= x0 && mouseX <= x1 && mouseY >= y0 && mouseY <= y1;
        } else {
            return false;
        }
    }
 
    public void attachToParent() {
        if (this.parent == null && this.advancementNode.parent() != null) {
            this.parent = this.getFirstVisibleParent(this.advancementNode);
            if (this.parent != null) {
                this.parent.addChild(this);
            }
        }
    }
 
    public int getY() {
        return this.y;
    }
 
    public int getX() {
        return this.x;
    }
}

引用的其他类