AbstractSignEditScreen.java

net.minecraft.client.gui.screens.inventory.AbstractSignEditScreen

信息

  • 全限定名:net.minecraft.client.gui.screens.inventory.AbstractSignEditScreen
  • 类型:public abstract class
  • 包:net.minecraft.client.gui.screens.inventory
  • 源码路径:src/main/java/net/minecraft/client/gui/screens/inventory/AbstractSignEditScreen.java
  • 起始行号:L31
  • 继承:Screen
  • 职责:

    TODO

字段/常量

  • sign

    • 类型: SignBlockEntity
    • 修饰符: protected final
    • 源码定位: L32
    • 说明:

      TODO

  • text

    • 类型: SignText
    • 修饰符: private
    • 源码定位: L33
    • 说明:

      TODO

  • messages

    • 类型: String[]
    • 修饰符: private final
    • 源码定位: L34
    • 说明:

      TODO

  • isFrontText

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

      TODO

  • woodType

    • 类型: WoodType
    • 修饰符: protected final
    • 源码定位: L36
    • 说明:

      TODO

  • cursorBlinkStartTime

    • 类型: long
    • 修饰符: private
    • 源码定位: L37
    • 说明:

      TODO

  • line

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

      TODO

  • signField

    • 类型: TextFieldHelper
    • 修饰符: private
    • 源码定位: L39
    • 说明:

      TODO

  • preeditOverlay

    • 类型: IMEPreeditOverlay
    • 修饰符: private
    • 源码定位: L40
    • 说明:

      TODO

  • cursorPosScratch

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

      TODO

内部类/嵌套类型

构造器

public AbstractSignEditScreen(SignBlockEntity sign, boolean isFrontText, boolean shouldFilter) @ L43

  • 构造器名:AbstractSignEditScreen
  • 源码定位:L43
  • 修饰符:public

参数:

  • sign: SignBlockEntity
  • isFrontText: boolean
  • shouldFilter: boolean

说明:

TODO

public AbstractSignEditScreen(SignBlockEntity sign, boolean isFrontText, boolean shouldFilter, Component title) @ L47

  • 构造器名:AbstractSignEditScreen
  • 源码定位:L47
  • 修饰符:public

参数:

  • sign: SignBlockEntity
  • isFrontText: boolean
  • shouldFilter: boolean
  • title: Component

说明:

TODO

方法

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

protected void init() @ L56

  • 方法名:init
  • 源码定位:L56
  • 返回类型:void
  • 修饰符:protected

参数:

说明:

TODO

public void tick() @ L72

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

参数:

说明:

TODO

private boolean isValid() @ L79

  • 方法名:isValid
  • 源码定位:L79
  • 返回类型:boolean
  • 修饰符:private

参数:

说明:

TODO

public boolean keyPressed(KeyEvent event) @ L83

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

参数:

  • event: KeyEvent

说明:

TODO

public boolean charTyped(CharacterEvent event) @ L98

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

参数:

  • event: CharacterEvent

说明:

TODO

public boolean preeditUpdated(PreeditEvent event) @ L104

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

参数:

  • event: PreeditEvent

说明:

TODO

public void extractRenderState(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) @ L110

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

参数:

  • graphics: GuiGraphicsExtractor
  • mouseX: int
  • mouseY: int
  • a: float

说明:

TODO

public void onClose() @ L117

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

参数:

说明:

TODO

public void removed() @ L122

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

参数:

说明:

TODO

public boolean isPauseScreen() @ L136

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

参数:

说明:

TODO

public boolean isInGameUi() @ L141

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

参数:

说明:

TODO

protected abstract void extractSignBackground(GuiGraphicsExtractor graphics) @ L146

  • 方法名:extractSignBackground
  • 源码定位:L146
  • 返回类型:void
  • 修饰符:protected abstract

参数:

  • graphics: GuiGraphicsExtractor

说明:

TODO

protected abstract Vector3f getSignTextScale() @ L148

  • 方法名:getSignTextScale
  • 源码定位:L148
  • 返回类型:Vector3f
  • 修饰符:protected abstract

参数:

说明:

TODO

protected abstract float getSignYOffset() @ L150

  • 方法名:getSignYOffset
  • 源码定位:L150
  • 返回类型:float
  • 修饰符:protected abstract

参数:

说明:

TODO

private void extractSign(GuiGraphicsExtractor graphics) @ L152

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

参数:

  • graphics: GuiGraphicsExtractor

说明:

TODO

private void extractSignText(GuiGraphicsExtractor graphics, Vector2f cursorPosOutput) @ L172

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

参数:

  • graphics: GuiGraphicsExtractor
  • cursorPosOutput: Vector2f

说明:

TODO

private void setMessage(String message) @ L230

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

参数:

  • message: String

说明:

TODO

private void onDone() @ L236

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

参数:

说明:

TODO

代码

@OnlyIn(Dist.CLIENT)
public abstract class AbstractSignEditScreen extends Screen {
    protected final SignBlockEntity sign;
    private SignText text;
    private final String[] messages;
    private final boolean isFrontText;
    protected final WoodType woodType;
    private long cursorBlinkStartTime;
    private int line;
    private @Nullable TextFieldHelper signField;
    private @Nullable IMEPreeditOverlay preeditOverlay;
    private final Vector2f cursorPosScratch = new Vector2f();
 
    public AbstractSignEditScreen(SignBlockEntity sign, boolean isFrontText, boolean shouldFilter) {
        this(sign, isFrontText, shouldFilter, Component.translatable("sign.edit"));
    }
 
    public AbstractSignEditScreen(SignBlockEntity sign, boolean isFrontText, boolean shouldFilter, Component title) {
        super(title);
        this.sign = sign;
        this.text = sign.getText(isFrontText);
        this.isFrontText = isFrontText;
        this.woodType = SignBlock.getWoodType(sign.getBlockState().getBlock());
        this.messages = IntStream.range(0, 4).mapToObj(index -> this.text.getMessage(index, shouldFilter)).map(Component::getString).toArray(String[]::new);
    }
 
    @Override
    protected void init() {
        this.minecraft.textInputManager().startTextInput();
        this.cursorBlinkStartTime = Util.getMillis();
        this.addRenderableWidget(
            Button.builder(CommonComponents.GUI_DONE, button -> this.onDone()).bounds(this.width / 2 - 100, this.height / 4 + 144, 200, 20).build()
        );
        this.signField = new TextFieldHelper(
            () -> this.messages[this.line],
            this::setMessage,
            TextFieldHelper.createClipboardGetter(this.minecraft),
            TextFieldHelper.createClipboardSetter(this.minecraft),
            s -> this.minecraft.font.width(s) <= this.sign.getMaxTextLineWidth()
        );
    }
 
    @Override
    public void tick() {
        if (!this.isValid()) {
            this.onDone();
        }
    }
 
    private boolean isValid() {
        return this.minecraft.player != null && !this.sign.isRemoved() && !this.sign.playerIsTooFarAwayToEdit(this.minecraft.player.getUUID());
    }
 
    @Override
    public boolean keyPressed(KeyEvent event) {
        if (event.isUp()) {
            this.line = this.line - 1 & 3;
            this.signField.setCursorToEnd();
            return true;
        } else if (event.isDown() || event.isConfirmation()) {
            this.line = this.line + 1 & 3;
            this.signField.setCursorToEnd();
            return true;
        } else {
            return this.signField.keyPressed(event) ? true : super.keyPressed(event);
        }
    }
 
    @Override
    public boolean charTyped(CharacterEvent event) {
        this.signField.charTyped(event);
        return true;
    }
 
    @Override
    public boolean preeditUpdated(@Nullable PreeditEvent event) {
        this.preeditOverlay = event != null ? new IMEPreeditOverlay(event, this.font, this.sign.getTextLineHeight()) : null;
        return true;
    }
 
    @Override
    public void extractRenderState(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) {
        super.extractRenderState(graphics, mouseX, mouseY, a);
        graphics.centeredText(this.font, this.title, this.width / 2, 40, -1);
        this.extractSign(graphics);
    }
 
    @Override
    public void onClose() {
        this.onDone();
    }
 
    @Override
    public void removed() {
        ClientPacketListener connection = this.minecraft.getConnection();
        if (connection != null) {
            connection.send(
                new ServerboundSignUpdatePacket(
                    this.sign.getBlockPos(), this.isFrontText, this.messages[0], this.messages[1], this.messages[2], this.messages[3]
                )
            );
        }
 
        this.minecraft.textInputManager().stopTextInput();
    }
 
    @Override
    public boolean isPauseScreen() {
        return false;
    }
 
    @Override
    public boolean isInGameUi() {
        return true;
    }
 
    protected abstract void extractSignBackground(GuiGraphicsExtractor graphics);
 
    protected abstract Vector3f getSignTextScale();
 
    protected abstract float getSignYOffset();
 
    private void extractSign(GuiGraphicsExtractor graphics) {
        graphics.pose().pushMatrix();
        float offsetX = this.width / 2.0F;
        float offsetY = this.getSignYOffset();
        graphics.pose().translate(offsetX, offsetY);
        graphics.pose().pushMatrix();
        this.extractSignBackground(graphics);
        graphics.pose().popMatrix();
        Vector3f textScale = this.getSignTextScale();
        graphics.pose().scale(textScale.x(), textScale.y());
        this.cursorPosScratch.zero();
        this.extractSignText(graphics, this.cursorPosScratch);
        graphics.pose().popMatrix();
        if (this.preeditOverlay != null) {
            this.cursorPosScratch.mul(textScale.x(), textScale.y()).add(offsetX, offsetY);
            this.preeditOverlay.updateInputPosition((int)this.cursorPosScratch.x, (int)this.cursorPosScratch.y);
            graphics.setPreeditOverlay(this.preeditOverlay);
        }
    }
 
    private void extractSignText(GuiGraphicsExtractor graphics, Vector2f cursorPosOutput) {
        int color = this.text.hasGlowingText() ? this.text.getColor().getTextColor() : AbstractSignRenderer.getDarkColor(this.text);
        boolean showCursor = TextCursorUtils.isCursorVisible(Util.getMillis() - this.cursorBlinkStartTime);
        boolean needsValidCursorPos = this.preeditOverlay != null;
        int cursorPos = this.signField.getCursorPos();
        int selectionPos = this.signField.getSelectionPos();
        int signMidpoint = 4 * this.sign.getTextLineHeight() / 2;
        int cursorY = this.line * this.sign.getTextLineHeight() - signMidpoint;
 
        for (int i = 0; i < this.messages.length; i++) {
            String line = this.messages[i];
            if (line != null) {
                if (this.font.isBidirectional()) {
                    line = this.font.bidirectionalShaping(line);
                }
 
                int x1 = -this.font.width(line) / 2;
                graphics.text(this.font, line, x1, i * this.sign.getTextLineHeight() - signMidpoint, color, false);
                if (i == this.line && cursorPos >= 0 && (showCursor || needsValidCursorPos)) {
                    int cursorPosition = this.font.width(line.substring(0, Math.max(Math.min(cursorPos, line.length()), 0)));
                    int cursorX = cursorPosition - this.font.width(line) / 2;
                    if (cursorPos >= line.length()) {
                        if (showCursor) {
                            TextCursorUtils.extractAppendCursor(graphics, this.font, cursorX, cursorY, color, false);
                        }
 
                        cursorPosOutput.set((float)cursorX, (float)cursorY);
                    }
                }
            }
        }
 
        for (int ix = 0; ix < this.messages.length; ix++) {
            String line = this.messages[ix];
            if (line != null && ix == this.line && cursorPos >= 0) {
                int cursorPosition = this.font.width(line.substring(0, Math.max(Math.min(cursorPos, line.length()), 0)));
                int cursorX = cursorPosition - this.font.width(line) / 2;
                if (cursorPos < line.length()) {
                    if (showCursor) {
                        TextCursorUtils.extractInsertCursor(graphics, cursorX, cursorY, ARGB.opaque(color), this.sign.getTextLineHeight());
                    }
 
                    cursorPosOutput.set((float)cursorX, (float)cursorY);
                }
 
                if (selectionPos != cursorPos) {
                    int startIndex = Math.min(cursorPos, selectionPos);
                    int endIndex = Math.max(cursorPos, selectionPos);
                    int startPosX = this.font.width(line.substring(0, startIndex)) - this.font.width(line) / 2;
                    int endPosX = this.font.width(line.substring(0, endIndex)) - this.font.width(line) / 2;
                    int fromX = Math.min(startPosX, endPosX);
                    int toX = Math.max(startPosX, endPosX);
                    graphics.textHighlight(fromX, cursorY, toX, cursorY + this.sign.getTextLineHeight(), true);
                }
            }
        }
    }
 
    private void setMessage(String message) {
        this.messages[this.line] = message;
        this.text = this.text.setMessage(this.line, Component.literal(message));
        this.sign.setText(this.text, this.isFrontText);
    }
 
    private void onDone() {
        this.minecraft.setScreen(null);
    }
}

引用的其他类

  • GuiGraphicsExtractor

    • 引用位置: 参数
  • Button

    • 引用位置: 方法调用
    • 关联成员: Button.builder()
  • IMEPreeditOverlay

    • 引用位置: 字段/构造调用
    • 关联成员: IMEPreeditOverlay()
  • TextCursorUtils

    • 引用位置: 方法调用
    • 关联成员: TextCursorUtils.extractAppendCursor(), TextCursorUtils.extractInsertCursor(), TextCursorUtils.isCursorVisible()
  • TextFieldHelper

    • 引用位置: 字段/方法调用/构造调用
    • 关联成员: TextFieldHelper(), TextFieldHelper.createClipboardGetter(), TextFieldHelper.createClipboardSetter()
  • Screen

    • 引用位置: 继承
  • CharacterEvent

    • 引用位置: 参数
  • KeyEvent

    • 引用位置: 参数
  • PreeditEvent

    • 引用位置: 参数
  • AbstractSignRenderer

    • 引用位置: 方法调用
    • 关联成员: AbstractSignRenderer.getDarkColor()
  • Component

    • 引用位置: 参数/方法调用
    • 关联成员: Component.literal(), Component.translatable()
  • ServerboundSignUpdatePacket

    • 引用位置: 构造调用
    • 关联成员: ServerboundSignUpdatePacket()
  • ARGB

    • 引用位置: 方法调用
    • 关联成员: ARGB.opaque()
  • Util

    • 引用位置: 方法调用
    • 关联成员: Util.getMillis()
  • SignBlock

    • 引用位置: 方法调用
    • 关联成员: SignBlock.getWoodType()
  • SignBlockEntity

    • 引用位置: 参数/字段
  • SignText

    • 引用位置: 字段
  • WoodType

    • 引用位置: 字段