ChatScreen.java

net.minecraft.client.gui.screens.ChatScreen

信息

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

    TODO

字段/常量

  • MOUSE_SCROLL_SPEED

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

      TODO

  • USAGE_TEXT

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

      TODO

  • RESTRICTED_NARRATION_TEXT

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

      TODO

  • USAGE_BACKGROUND_COLOR

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

      TODO

  • closeOnSubmit

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

      TODO

  • historyBuffer

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

      TODO

  • historyPos

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

      TODO

  • input

    • 类型: EditBox
    • 修饰符: protected
    • 源码定位: L39
    • 说明:

      TODO

  • initial

    • 类型: String
    • 修饰符: protected
    • 源码定位: L40
    • 说明:

      TODO

  • isDraft

    • 类型: boolean
    • 修饰符: protected
    • 源码定位: L41
    • 说明:

      TODO

  • displayMode

    • 类型: ChatComponent.DisplayMode
    • 修饰符: private
    • 源码定位: L42
    • 说明:

      TODO

  • exitReason

    • 类型: ChatScreen.ExitReason
    • 修饰符: protected
    • 源码定位: L43
    • 说明:

      TODO

  • commandSuggestions

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

      TODO

内部类/嵌套类型

  • net.minecraft.client.gui.screens.ChatScreen.ChatConstructor

    • 类型: interface
    • 修饰符: public
    • 源码定位: L334
    • 说明:

      TODO

  • net.minecraft.client.gui.screens.ChatScreen.ExitReason

    • 类型: enum
    • 修饰符: protected static
    • 源码定位: L339
    • 说明:

      TODO

构造器

public ChatScreen(String initial, boolean isDraft) @ L46

  • 构造器名:ChatScreen
  • 源码定位:L46
  • 修饰符:public

参数:

  • initial: String
  • isDraft: boolean

说明:

TODO

public ChatScreen(String initial, boolean isDraft, boolean closeOnSubmit) @ L50

  • 构造器名:ChatScreen
  • 源码定位:L50
  • 修饰符:public

参数:

  • initial: String
  • isDraft: boolean
  • closeOnSubmit: boolean

说明:

TODO

方法

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

protected void init() @ L57

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

参数:

说明:

TODO

protected void setInitialFocus() @ L86

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

参数:

说明:

TODO

public void resize(int width, int height) @ L91

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

参数:

  • width: int
  • height: int

说明:

TODO

public void onClose() @ L97

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

参数:

说明:

TODO

public void removed() @ L103

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

参数:

说明:

TODO

protected boolean shouldDiscardDraft() @ L114

  • 方法名:shouldDiscardDraft
  • 源码定位:L114
  • 返回类型:boolean
  • 修饰符:protected

参数:

说明:

TODO

private void onEdited(String value) @ L119

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

参数:

  • value: String

说明:

TODO

public boolean keyPressed(KeyEvent event) @ L125

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

参数:

  • event: KeyEvent

说明:

TODO

public boolean mouseScrolled(double x, double y, double scrollX, double scrollY) @ L172

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

参数:

  • x: double
  • y: double
  • scrollX: double
  • scrollY: double

说明:

TODO

public boolean mouseClicked(MouseButtonEvent event, boolean doubleClick) @ L187

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

参数:

  • event: MouseButtonEvent
  • doubleClick: boolean

说明:

TODO

private boolean insertionClickMode() @ L208

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

参数:

说明:

TODO

private boolean handleComponentClicked(Style clicked, boolean allowInsertions) @ L212

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

参数:

  • clicked: Style
  • allowInsertions: boolean

说明:

TODO

public void insertText(String text, boolean replace) @ L240

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

参数:

  • text: String
  • replace: boolean

说明:

TODO

public void moveInHistory(int dir) @ L249

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

参数:

  • dir: int

说明:

TODO

private FormattedCharSequence formatChat(String text, int offset) @ L269

  • 方法名:formatChat
  • 源码定位:L269
  • 返回类型:FormattedCharSequence
  • 修饰符:private

参数:

  • text: String
  • offset: int

说明:

TODO

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

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

参数:

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

说明:

TODO

public void extractBackground(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) @ L284

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

参数:

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

说明:

TODO

public boolean isPauseScreen() @ L288

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

参数:

说明:

TODO

public boolean isAllowedInPortal() @ L293

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

参数:

说明:

TODO

protected void updateNarrationState(NarrationElementOutput output) @ L298

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

参数:

  • output: NarrationElementOutput

说明:

TODO

public void handleChatInput(String msg, boolean addToRecent) @ L313

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

参数:

  • msg: String
  • addToRecent: boolean

说明:

TODO

public String normalizeChatMessage(String message) @ L328

  • 方法名:normalizeChatMessage
  • 源码定位:L328
  • 返回类型:String
  • 修饰符:public

参数:

  • message: String

说明:

TODO

代码

@OnlyIn(Dist.CLIENT)
public class ChatScreen extends Screen {
    public static final double MOUSE_SCROLL_SPEED = 7.0;
    private static final Component USAGE_TEXT = Component.translatable("chat_screen.usage");
    private static final Component RESTRICTED_NARRATION_TEXT = Component.translatable("chat_screen.restricted.narration");
    public static final int USAGE_BACKGROUND_COLOR = -805306368;
    private final boolean closeOnSubmit;
    private String historyBuffer = "";
    private int historyPos = -1;
    protected EditBox input;
    protected String initial;
    protected boolean isDraft;
    private ChatComponent.DisplayMode displayMode = ChatComponent.DisplayMode.FOREGROUND;
    protected ChatScreen.ExitReason exitReason = ChatScreen.ExitReason.INTERRUPTED;
    private CommandSuggestions commandSuggestions;
 
    public ChatScreen(String initial, boolean isDraft) {
        this(initial, isDraft, true);
    }
 
    public ChatScreen(String initial, boolean isDraft, boolean closeOnSubmit) {
        super(Component.translatable("chat_screen.title"));
        this.closeOnSubmit = closeOnSubmit;
        this.initial = initial;
        this.isDraft = isDraft;
    }
 
    @Override
    protected void init() {
        this.historyPos = this.minecraft.gui.getChat().getRecentChat().size();
        this.input = new EditBox(this.minecraft.fontFilterFishy, 4, this.height - 12, this.width - 4, 12, Component.translatable("chat.editBox")) {
            {
                Objects.requireNonNull(ChatScreen.this);
            }
 
            @Override
            protected MutableComponent createNarrationMessage() {
                return super.createNarrationMessage().append(ChatScreen.this.commandSuggestions.getNarrationMessage());
            }
        };
        this.input.setMaxLength(256);
        this.input.setBordered(false);
        this.input.setValue(this.initial);
        this.input.setResponder(this::onEdited);
        this.input.addFormatter(this::formatChat);
        this.input.setCanLoseFocus(false);
        this.addRenderableWidget(this.input);
        this.commandSuggestions = new CommandSuggestions(this.minecraft, this, this.input, this.font, false, false, 1, 10, true, -805306368);
        this.commandSuggestions.setAllowHiding(false);
        this.commandSuggestions.setAllowSuggestions(false);
        ChatAbilities chatAbilities = this.minecraft.player.chatAbilities();
        this.displayMode = chatAbilities.hasAnyRestrictions() ? ChatComponent.DisplayMode.FOREGROUND_RESTRICTED : ChatComponent.DisplayMode.FOREGROUND;
        this.commandSuggestions.setRestrictions(chatAbilities.canSendMessages(), chatAbilities.canSendCommands());
        this.commandSuggestions.updateCommandInfo();
    }
 
    @Override
    protected void setInitialFocus() {
        this.setInitialFocus(this.input);
    }
 
    @Override
    public void resize(int width, int height) {
        this.initial = this.input.getValue();
        this.init(width, height);
    }
 
    @Override
    public void onClose() {
        this.exitReason = ChatScreen.ExitReason.INTENTIONAL;
        super.onClose();
    }
 
    @Override
    public void removed() {
        this.minecraft.gui.getChat().resetChatScroll();
        this.initial = this.input.getValue();
        if (this.shouldDiscardDraft() || StringUtils.isBlank(this.initial)) {
            this.minecraft.gui.getChat().discardDraft();
        } else if (!this.isDraft) {
            this.minecraft.gui.getChat().saveAsDraft(this.initial);
        }
    }
 
    protected boolean shouldDiscardDraft() {
        return this.exitReason != ChatScreen.ExitReason.INTERRUPTED
            && (this.exitReason != ChatScreen.ExitReason.INTENTIONAL || !this.minecraft.options.saveChatDrafts().get());
    }
 
    private void onEdited(String value) {
        this.commandSuggestions.setAllowSuggestions(true);
        this.commandSuggestions.updateCommandInfo();
        this.isDraft = false;
    }
 
    @Override
    public boolean keyPressed(KeyEvent event) {
        if (this.commandSuggestions.keyPressed(event)) {
            return true;
        } else if (this.isDraft && event.key() == 259) {
            this.input.setValue("");
            this.isDraft = false;
            return true;
        } else if (super.keyPressed(event)) {
            return true;
        } else if (event.isConfirmation()) {
            if (!this.commandSuggestions.hasAllowedInput()) {
                return true;
            } else {
                this.handleChatInput(this.input.getValue(), true);
                if (this.closeOnSubmit) {
                    this.exitReason = ChatScreen.ExitReason.DONE;
                    this.minecraft.setScreen(null);
                } else {
                    this.input.setValue("");
                    this.minecraft.gui.getChat().resetChatScroll();
                }
 
                return true;
            }
        } else {
            switch (event.key()) {
                case 264:
                    this.moveInHistory(1);
                    break;
                case 265:
                    this.moveInHistory(-1);
                    break;
                case 266:
                    this.minecraft.gui.getChat().scrollChat(this.minecraft.gui.getChat().getLinesPerPage() - 1);
                    break;
                case 267:
                    this.minecraft.gui.getChat().scrollChat(-this.minecraft.gui.getChat().getLinesPerPage() + 1);
                    break;
                default:
                    return false;
            }
 
            return true;
        }
    }
 
    @Override
    public boolean mouseScrolled(double x, double y, double scrollX, double scrollY) {
        scrollY = Mth.clamp(scrollY, -1.0, 1.0);
        if (this.commandSuggestions.mouseScrolled(scrollY)) {
            return true;
        } else {
            if (!this.minecraft.hasShiftDown()) {
                scrollY *= 7.0;
            }
 
            this.minecraft.gui.getChat().scrollChat((int)scrollY);
            return true;
        }
    }
 
    @Override
    public boolean mouseClicked(MouseButtonEvent event, boolean doubleClick) {
        if (this.commandSuggestions.mouseClicked(event)) {
            return true;
        } else {
            if (event.button() == 0) {
                int screenHeight = this.minecraft.getWindow().getGuiScaledHeight();
                ActiveTextCollector.ClickableStyleFinder finder = new ActiveTextCollector.ClickableStyleFinder(this.getFont(), (int)event.x(), (int)event.y())
                    .includeInsertions(this.insertionClickMode());
                this.minecraft.gui.getChat().captureClickableText(finder, screenHeight, this.minecraft.gui.getGuiTicks(), this.displayMode);
                Style clicked = finder.result();
                if (clicked != null && this.handleComponentClicked(clicked, this.insertionClickMode())) {
                    this.initial = this.input.getValue();
                    return true;
                }
            }
 
            return super.mouseClicked(event, doubleClick);
        }
    }
 
    private boolean insertionClickMode() {
        return this.minecraft.hasShiftDown();
    }
 
    private boolean handleComponentClicked(Style clicked, boolean allowInsertions) {
        ClickEvent event = clicked.getClickEvent();
        if (allowInsertions) {
            if (clicked.getInsertion() != null) {
                this.insertText(clicked.getInsertion(), false);
            }
        } else if (event != null) {
            Objects.requireNonNull(event);
            switch (event) {
                case ClickEvent.Custom customEvent when customEvent.id().equals(ChatComponent.QUEUE_EXPAND_ID):
                    ChatListener chatListener = this.minecraft.getChatListener();
                    if (chatListener.queueSize() != 0L) {
                        chatListener.acceptNextDelayedMessage();
                    }
                    break;
                case ClickEvent.Custom customEventx when customEventx.id().equals(ChatComponent.GO_TO_RESTRICTIONS_SCREEN):
                    this.minecraft.setScreen(new RestrictionsScreen(this, this.minecraft.player.chatAbilities()));
                    break;
                default:
                    defaultHandleGameClickEvent(event, this.minecraft, this);
            }
 
            return true;
        }
 
        return false;
    }
 
    @Override
    public void insertText(String text, boolean replace) {
        if (replace) {
            this.input.setValue(text);
        } else {
            this.input.insertText(text);
        }
    }
 
    public void moveInHistory(int dir) {
        int newPos = this.historyPos + dir;
        int max = this.minecraft.gui.getChat().getRecentChat().size();
        newPos = Mth.clamp(newPos, 0, max);
        if (newPos != this.historyPos) {
            if (newPos == max) {
                this.historyPos = max;
                this.input.setValue(this.historyBuffer);
            } else {
                if (this.historyPos == max) {
                    this.historyBuffer = this.input.getValue();
                }
 
                this.input.setValue(this.minecraft.gui.getChat().getRecentChat().get(newPos));
                this.commandSuggestions.setAllowSuggestions(false);
                this.historyPos = newPos;
            }
        }
    }
 
    private @Nullable FormattedCharSequence formatChat(String text, int offset) {
        return this.isDraft ? FormattedCharSequence.forward(text, Style.EMPTY.withColor(ChatFormatting.GRAY).withItalic(true)) : null;
    }
 
    @Override
    public void extractRenderState(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) {
        graphics.fill(2, this.height - 14, this.width - 2, this.height - 2, this.minecraft.options.getBackgroundColor(Integer.MIN_VALUE));
        this.minecraft
            .gui
            .getChat()
            .extractRenderState(graphics, this.font, this.minecraft.gui.getGuiTicks(), mouseX, mouseY, this.displayMode, this.insertionClickMode());
        super.extractRenderState(graphics, mouseX, mouseY, a);
        this.commandSuggestions.extractRenderState(graphics, mouseX, mouseY);
    }
 
    @Override
    public void extractBackground(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) {
    }
 
    @Override
    public boolean isPauseScreen() {
        return false;
    }
 
    @Override
    public boolean isAllowedInPortal() {
        return true;
    }
 
    @Override
    protected void updateNarrationState(NarrationElementOutput output) {
        output.add(NarratedElementType.TITLE, this.getTitle());
        if (this.displayMode.showRestrictedPrompt) {
            output.add(NarratedElementType.USAGE, CommonComponents.joinForNarration(USAGE_TEXT, RESTRICTED_NARRATION_TEXT));
        } else {
            output.add(NarratedElementType.USAGE, USAGE_TEXT);
        }
 
        String value = this.input.getValue();
        if (!value.isEmpty()) {
            output.nest().add(NarratedElementType.TITLE, Component.translatable("chat_screen.message", value));
        }
    }
 
    public void handleChatInput(String msg, boolean addToRecent) {
        msg = this.normalizeChatMessage(msg);
        if (!msg.isEmpty()) {
            if (addToRecent) {
                this.minecraft.gui.getChat().addRecentChat(msg);
            }
 
            if (msg.startsWith("/")) {
                this.minecraft.player.connection.sendCommand(msg.substring(1));
            } else {
                this.minecraft.player.connection.sendChat(msg);
            }
        }
    }
 
    public String normalizeChatMessage(String message) {
        return StringUtil.trimChatMessage(StringUtils.normalizeSpace(message.trim()));
    }
 
    @FunctionalInterface
    @OnlyIn(Dist.CLIENT)
    public interface ChatConstructor<T extends ChatScreen> {
        T create(String initial, boolean isDraft);
    }
 
    @OnlyIn(Dist.CLIENT)
    protected static enum ExitReason {
        INTENTIONAL,
        INTERRUPTED,
        DONE;
    }
}

引用的其他类